1. 程式人生 > >修改Android系統原始碼,優化開機速度。

修改Android系統原始碼,優化開機速度。

下面部分寫的比較零散,整合了一下,可以移步到最新一篇:

通常情況下,Android系統開機保持在20s~25s應該算是合格比較好的狀態。

最近幾天在看關於Android系統開機啟動過程的相關內容。做個筆記。

關於有話Android系統開機時間有話,採取三個措施有話,修改ZygoteInit.java。 Android系統開機啟動過程這裡就不說了,網上很多大牛對應的文章。

1. 修改ZygoteInit.java 中預載入資源函式preload() ,  preloadClasses(); 與 preloadResources(); 並行載入。
2. 修改讀取配置資訊過程中GC頻率。
3. 提升程序優先順序。

1. 

    static void preload() {
        //
        Thread  preloadRsThread = new Thread(new Runnable(){

            @Override
            public void run() {
                // TODO Auto-generated method stub
            //將該資源載入放在子執行緒中  。載入資原始檔要比載入classes檔案要快,因此這裡不提升子執行緒優先順序。  
            preloadResources();
            }

        }) ;

        preloadRsThread.start() ;
        preloadClasses();
        //wait preloadRes complete.
        try {
            preloadRsThread.join() ;
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
        //暴露什麼問題。
        preloadOpenGL();
    }


2.
/**
     * Performs Zygote process initialization. Loads and initializes
     * commonly used classes.
     *
     * Most classes only cause a few hundred bytes to be allocated, but
     * a few will allocate a dozen Kbytes (in one case, 500+K).
     */
    private static void preloadClasses() {
        final VMRuntime runtime = VMRuntime.getRuntime();

        InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(
                PRELOADED_CLASSES);
        if (is == null) {
            Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + ".");
        } else {
            Log.i(TAG, "Preloading classes...");
            long startTime = SystemClock.uptimeMillis();

            // Drop root perms while running static initializers.
            setEffectiveGroup(UNPRIVILEGED_GID);
            setEffectiveUser(UNPRIVILEGED_UID);

            // Alter the target heap utilization.  With explicit GCs this
            // is not likely to have any effect.
            float defaultUtilization = runtime.getTargetHeapUtilization();
            runtime.setTargetHeapUtilization(0.8f);

            // Start with a clean slate.
            System.gc();
            runtime.runFinalizationSync();
            Debug.startAllocCounting();

            try {
                BufferedReader br
                    = new BufferedReader(new InputStreamReader(is), 256);

                int count = 0;
                String line;
                while ((line = br.readLine()) != null) {
                    // Skip comments and blank lines.
                    line = line.trim();
                    if (line.startsWith("#") || line.equals("")) {
                        continue;
                    }

                    try {
                        if (false) {
                            Log.v(TAG, "Preloading " + line + "...");
                        }
                        Class.forName(line);
                        //減少GC頻率,modify   begin
                        if (count%128==0&&Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {//end
                            if (false) {
                                Log.v(TAG,
                                    " GC at " + Debug.getGlobalAllocSize());
                            }
                            System.gc();
                            runtime.runFinalizationSync();
                            Debug.resetGlobalAllocSize();
                        }
                        count++;
                    } catch (ClassNotFoundException e) {
                        Log.w(TAG, "Class not found for preloading: " + line);
                    } catch (UnsatisfiedLinkError e) {
                        Log.w(TAG, "Problem preloading " + line + ": " + e);
                    } catch (Throwable t) {
                        Log.e(TAG, "Error preloading " + line + ".", t);
                        if (t instanceof Error) {
                            throw (Error) t;
                        }
                        if (t instanceof RuntimeException) {
                            throw (RuntimeException) t;
                        }
                        throw new RuntimeException(t);
                    }
                }

                Log.i(TAG, "...preloaded " + count + " classes in "
                        + (SystemClock.uptimeMillis()-startTime) + "ms.");
            } catch (IOException e) {
                Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
            } finally {
                IoUtils.closeQuietly(is);
                // Restore default.
                runtime.setTargetHeapUtilization(defaultUtilization);

                // Fill in dex caches with classes, fields, and methods brought in by preloading.
                runtime.preloadDexCaches();

                Debug.stopAllocCounting();

                // Bring back root. We'll need it later.
                setEffectiveUser(ROOT_UID);
                setEffectiveGroup(ROOT_GID);
            }
        }
    }

3.
//    ZygoteInit.java入口
    public static void main(String argv[]) {
        try {

            //優化開機速度 begin
            /* 20150127 begin */
            //獲取當前程序優先順序
            int currentPriority = Process.getThreadPriority(Process.myPid()) ;
            //提升當前程序優先順序。
            Process.setThreadPriority(Process.THREAD_PRIORITY_AUDIO) ;
            /* 20150127 end */
            
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

//            1.註冊socket服務端
            registerZygoteSocket();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
//            5.載入資源
            preload();
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            gc();
            
            /* 20150127 begin */
            Process.setThreadPriority(currentPriority) ;
            /* 20150127 end */
            //優化開機速度 end
            // Disable tracing so that forked processes do not inherit stale tracing tags from
            // Zygote.
            Trace.setTracingEnabled(false);

            // If requested, start system server directly from Zygote
            if (argv.length != 2) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }
//          2. 呼叫starySystemServer()方法
            if (argv[1].equals("start-system-server")) {
                startSystemServer();
            } else if (!argv[1].equals("")) {
                throw new RuntimeException(argv[0] + USAGE_STRING);
            }

            Log.i(TAG, "Accepting command socket connections");

            //3.迴圈監聽並接收客戶端請求。
            runSelectLoop();
//關閉socket
            closeServerSocket();
        } catch (MethodAndArgsCaller caller) {
//          4  《深入理解Android卷1》作者說這裡比較重要
            caller.run();
        } catch (RuntimeException ex) {
            Log.e(TAG, "Zygote died with exception", ex);
            closeServerSocket();
            throw ex;
        }
    }

4.修改gc呼叫閥值
   /** when preloading, GC after allocating this many bytes 
     * 
     * 20150127 優化開機速度
     */
    
    //- private static final int PRELOAD_GC_THRESHOLD = 50000;
    private static final int PRELOAD_GC_THRESHOLD = 64*1024*1024;
    
    /*20150127 優化開機速度 end*/


另外,Android系統啟動過程中,會預先載入資原始檔,這些檔案中,包含了很多系統應用會頻繁使用到的資原始檔,比如圖片資源等。因此,我們自己的新新增其他的部分資源也可以預先載入到記憶體,

這樣不僅提升響應速度,而且也可以加快應用的冷啟動速度。

Android系統性能優化是個大工程,從一個小小的細節出發,或許能收穫哪怕幾百毫秒的時間,也是不錯的。細節決定成敗。

關於程序優先順序:

		Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND); //設定執行緒優先順序為後臺,這樣當多個執行緒併發後很多無關緊要的執行緒分配的CPU時間將會減少,有利於主執行緒的處理,有以下幾種:
		int THREAD_PRIORITY_AUDIO ;//標準音樂播放使用的執行緒優先順序
		int THREAD_PRIORITY_BACKGROUND ;//標準後臺程式
		int THREAD_PRIORITY_DEFAULT ;// 預設應用的優先順序
		int THREAD_PRIORITY_DISPLAY ;//標準顯示系統優先順序,主要是改善UI的重新整理
		int THREAD_PRIORITY_FOREGROUND ; //標準前臺執行緒優先順序
		int THREAD_PRIORITY_LESS_FAVORABLE ;//低於favorable
		int THREAD_PRIORITY_LOWEST  ;//有效的執行緒最低的優先順序
		int THREAD_PRIORITY_MORE_FAVORABLE ; //高於favorable
		int THREAD_PRIORITY_URGENT_AUDIO  ;//標準較重要音訊播放優先順序
		int THREAD_PRIORITY_URGENT_DISPLAY  ;//標準較重要顯示優先順序,對於輸入事件同樣適用。


Android系統開機優化,可以修改的地方還有很多。後續會補上。

此外,Android開機過程中,PackageManagerService會掃描系統內建apk,因此這個過程也是耗費時間比較長的。

在這個過程中下功夫還是很有必要。

比如odex優化等。

相關推薦

修改Android系統原始碼優化開機速度

下面部分寫的比較零散,整合了一下,可以移步到最新一篇: 通常情況下,Android系統開機保持在20s~25s應該算是合格比較好的狀態。 最近幾天在看關於Android系統開機啟動過程的相關內容。做個筆記。 關於有話Android系統開機時間有話,採取三個措施有話,修

線上看Android系統原始碼那些相見恨晚的幾種方案

前言:最近在研究MediaCodec,u盤壞了,之前下載的原始碼也就自然沒有了,真是個難過的事情,不能因為沒有原始碼了,就阻擋我的計劃了呀,於是就是今天一文,線上看Android原始碼,加之此前很多人也有向我留言,如何看android系統的原始碼,今天來敲黑

線上看Android系統原始碼AndroidXRef的簡易使用方法

轉載自:http://blog.csdn.net/hejjunlin/article/details/53454514 前言:最近在研究MediaCodec,u盤壞了,之前下載的原始碼也就自然沒有了,真是個難過的事情,不能因為沒有原始碼了,就阻擋我的計劃了呀,於是就是今

Android 使用X5核心時優化載入速度

最近在做Webview載入頁面的時候,用到了騰訊的X5核心,但是在使用過程中發現每次點選連結時,都會有一定的延遲,之後才能跳轉到對應的頁面,這體驗很不好。。。 所以就抽時間找問題,解決問題。 原因 通過一步一步的除錯,發現在載入X5核心的時候,X5核心需

一行代碼繞過原密碼直接修改win系統密碼bat命令超神奇

今天 user type 文章 一閃而過 你知道 系統管理 超級 proc 其實我一直想學習bat命令,這種批處理,能用的好,省了很多軟件,也省了很多電腦空間。 以後就多發點簡單又強大實用的命令代碼文章,大家一起共勉。 今天要介紹的是,用一行簡單的命令來直接修改Windo

Android系統原始碼分析之-ContentProvider

距離上一次寫部落格已經半年多了,這半年發生了很多事情,也有了很多感觸,最主要是改變了忙碌了工作,更加重視身體的健康,為此也把工作地點從深圳這個一線城市換到了珠海,工作相對沒有那麼累,身體感覺也好了很多。所以在工作完成之餘,也有了更多的時間來自我學習和提高,後續會用更多時間來寫更多實用的東西,幫助我們理解

【安卓本卓】Android系統原始碼篇之(二)Source Insight

Source Insight(以下簡稱SI) 一、SI簡介        SI是一款面向專案開發的程式編輯器和程式碼瀏覽器,它提供了一個檢視將分散在各個地方的程式碼匯合在一起形成一個虛擬的整體,供開發者方便地閱讀和編輯,如下圖所示。它已經持續維護了10多年了,旨在提

android hardware 簡述(Android系統原始碼情景分析 筆記)

轉自 https://blog.csdn.net/u013377887/article/details/52965988   1.Android原始碼開發的C可執行原始檔一般存在external目錄下  2  Android的幾層框架.  &n

Android系統原始碼分析--View繪製流程之-setContentView

上一篇分析了四大元件之ContentProvider,這也是四大元件最後一個。因此,從這篇開始我們分析新的篇章--View繪製流程,View繪製流程在Android開發中佔有非常重要的位置,只要有檢視的顯示,都離不開View的繪製,所以瞭解View繪製原理對於應用開發以及系統的學習至關重要。由於View

修改Android系統預設時間

一 : 修改Android系統預設時間 原始碼路徑:frameworks/base/services/java/com/android/server/SystemServer.java 主要變數EARLIEST_SUPPORTED_TIME // The earliest suppo

Android 系統原始碼不編譯xxxTests模組的mk檔案註釋

1. 編譯xxxTests模組導致的編譯不過 build/core/Makefile:2789: warning: ignoring old commands for target `out/target/product/sp9832e_op54_go/sp9832e_op54_g

Android系統原始碼情景分析 [羅昇陽著][帶書籤和原始碼]

在組織上,本書劃分為初識Android系統、Android專用驅動系統和Android應用程式框架三大篇。初識Android系統篇介紹了參考書籍、基礎知識以及實驗環境搭建;Android專用驅動系統篇介紹了Logger日誌驅動程式、Binder程序間通訊驅動程

Android FrameWork學習(二)Android系統原始碼除錯

為了更進一步地學習跟研究 Android 系統原始碼,今天我們來講講如何進行 Android 系統原始碼的除錯,只有學會了如何進行系統原始碼的除錯,才能幫助我們更高效地閱讀跟理解原始碼。 我們知道,Android Framework 的程式碼主要由Java、C\

【安卓本卓】Android系統原始碼篇之(一)原始碼獲取、原始碼目錄結構及原始碼閱讀工具簡介

前言 古人常說,“熟讀唐詩三百首,不會作詩也會吟”,說明了大量閱讀詩歌名篇對學習作詩有非常大的幫助。做開發也一樣,Android原始碼是全世界最優秀的Android工程師編寫的程式碼,也是Android開發中絕對的權威所在。Android系統開源,且佔據了當今手機系統世界的絕大部分江山,各大手機廠商要做手機系

如何學習Android系統原始碼

參考資料 Android系統的原始碼非常龐大和複雜,我們不能貿然進入,否則很容易在裡面迷入方向,進而失去研究它的信心。我們應該在分析它的原始碼之前學習好一些理論知識,下面就介紹一些與Android系統相關的資料。 我們知道,Android系統是基於Linux核心來開發

分享45個android例項原始碼很好很強大.收藏吧!!!

新增微訊號:apkbus,回覆“視訊”即可獲取400套免費Android開發視訊教程分享45個android例項原始碼,很好很強大http://www.apkbus.com/android-20978-1-1.htmlandriod鬧鐘原始碼http://www.apkbu

修改gradle中央倉庫加快訪問速度

開啟gradle專案的build.gradle檔案 找到repositories,註釋掉mavenCentral(),使用阿里雲的倉庫地址 repositories { //m

Android系統移植與除錯之-------)如何修改Android系統預設顯示

1、首先解決【設定】介面預設顯示【開發者選項】的問題 檢視原始碼:packages/apps/Settings/src/com/android/settings/SettingsActivity.java 在updateTilesList(List target)方法中,可以找到【開發

安卓學習過程、怎樣閱讀 Android 系統原始碼

問:對於想深入學習底層架構的同學,應該怎樣閱讀 Android 系統原始碼呢? 我覺得閱讀系統原始碼非常有必要遵循的一個原則就是抽絲剝繭、點到即止。應該認準一個功能點,然後去分析這個功能點是如何實現的。但只要去追尋主體的實現邏輯即可,千萬不要試圖去搞懂每一行程式碼都是什麼意思,那樣很容易會陷入到思維陷阱當中

收集了很多音樂播放器類的Android專案原始碼非常不錯的開源專案【轉】

JieCaoVideoPlayer立志成為Android平臺使用最廣泛的視訊播放控制元件http://neast.cn/forum.php?mod=viewthread&tid=61610&fromuid=5 OPlayer Android平臺基於Vitamio的開源播放器http://ne