成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

CPU調(diào)頻、線程綁核、優(yōu)先級控制實踐

開發(fā) 前端
本文分享了Android系統(tǒng)下自主控制CPU頻率、線程指定核心和優(yōu)先級的方式,不過這些能力需要具體落實到業(yè)務(wù)場景才能夠獲得實際的收益。

0、背景

為了進一步優(yōu)化App性能,最近針對如何提高應(yīng)用對CPU的資源使用、以及在多線程環(huán)境下如何提高關(guān)鍵線程的執(zhí)行優(yōu)先級做了技術(shù)調(diào)研。本文是對技術(shù)調(diào)研過程的階段性總結(jié),將分別介紹普通應(yīng)用如何調(diào)控App頻率、如何將指定線程綁定到特定CPU、如何通過提升線程優(yōu)先級獲得更多CPU時間片。

1、CPU調(diào)頻

1.1 概念

通常更高的CPU頻率代表了更快的運行速度,一個設(shè)備可能包含多個CPU,以我目前使用的Mi 11 Pro為例,它的CPU為8核分別為,1 x 2.84GHz (ARM 最新Cortex X1 核心)+3 x 2.4GHz (Cortex A78)+4 x 1.8GHz (Cortex A55) 。 這里列出的CPU頻率為CPU物理理論上的最大頻率,在實際運行過程中CPU的頻率范圍為governor動態(tài)控制的。目前的Androd設(shè)備普遍采用schedutil gover進行調(diào)頻控制,它會根據(jù)運行過程的CPU負載進行調(diào)頻,不過默認的調(diào)頻存在一些限制,比如調(diào)頻之間的間隔需>10ms, 并且根據(jù)schedutil的升頻計算公式,并不保證能直接升頻到最高頻率。

在實際應(yīng)用中,如果我們已經(jīng)知道接下來需要執(zhí)行高CPU負載任務(wù),通過提前主動升頻來提升性能,就能減少卡頓或者提高任務(wù)的執(zhí)行耗時。

在Android系統(tǒng) :可以通過 

echo [頻率]>/sys/devices/system/cpu/cpu*/cpufreq/scaling set  speed

來修改目標CPU的頻率,但這需要root權(quán)限才能執(zhí)行。對于普遍的應(yīng)用程序,經(jīng)過調(diào)研發(fā)現(xiàn),高通提供了一套針對高通芯片的性能Jon告知SDKPower,利用這個套機制可以實現(xiàn)CPU頻率等資源的管理。

關(guān)于高通這套Framework的具體架構(gòu),可以參考最后附錄中的參考資料的相關(guān)文章,我們只需要知道:

在Java層 /android/util/BoostFramework.java類封裝了一些基本的API提供給framework層調(diào)用。

1.2 實現(xiàn)

通過閱讀BoostFramework的源碼,可以發(fā)現(xiàn)其實現(xiàn)主要是對 QPerformance.jar 和UxPerformance.ja r中的 API 進行了一層反射調(diào)用包裝。那么一樣的,我們也可以通過封裝對 BoostFrameWork 類的調(diào)用提供提頻能力。

不過這些函數(shù)似乎并不是默認公開的內(nèi)容,直接通過google搜索 并沒有找到關(guān)于BoostFramwork或者高通Performance API的相關(guān)信息。最后還是通過其他各種關(guān)鍵字檢索,終于找到了部分有效信息。

圖片圖片

圖片圖片

通過對應(yīng)API文檔及使用示例得知perfLocakAcquire 該函數(shù)接受 2個參數(shù),第一個參數(shù)為持續(xù)時間、第二個參數(shù)為一個int數(shù)組,表示具體的操作,數(shù)組中的內(nèi)容為 k-v 結(jié)構(gòu)形式,比如 [config1,value,config2,value] . 該函數(shù)執(zhí)行時會返回一個 PerfLock句柄,后續(xù)通過調(diào)用 perfLockReleaseHandler 可以提前取消之前的操作。

這里簡單羅列一些配置項對應(yīng)的值:

/**
         * 是否允許CPU進入深度低功耗模式, 對應(yīng) /dev/cpu_dma_latency, 默認空,不允許則設(shè)置為1
         */
const val MPCTLV3_ALL_CPUS_PWR_CLPS_DIS = 0x40400000


/**
         * 對應(yīng)控制小核最小頻率
         */
const val MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40800100


/**
         * 對應(yīng)控制小核最大頻率
         */
const val MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40804100


/**
         * 對應(yīng)控制大核最小頻率
         */
const val MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0 = 0x40800000


/**
         * 對應(yīng)控制大核最大頻率
         */
const val MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0 = 0x40804000


/**
         * 對應(yīng)控制超大核最小頻率
         */
const val MPCTLV3_MIN_FREQ_CLUSTER_PLUS_CORE_0 = 0x40800200;


/**
         * 對應(yīng)控制超大核最小頻率
         */
const val MPCTLV3_MAX_FREQ_CLUSTER_PLUS_CORE_0 = 0x40804200


/**
         * 不太清楚,似乎是調(diào)度加速
         */
const val MPCTLV3_SCHED_BOOST = 0x40C00000;

完整的配置項定義,可以參考:https://github.com/Knight-ZXW/AppOptimizeFramework/blob/master/docs/qualcomms.txt。

另外,如何確定我們的設(shè)備包含高通的這套性能調(diào)控SDK呢?可以通過查看你的Android設(shè)備存儲路徑/system/framework/路徑,如果包含了 QPerformance.jar 及 QXPerformance.jar 就表示接入了SDK。

圖片圖片

根據(jù)上面的知識點,最終該工具類完整的實現(xiàn)代碼如下:

首先在init 函數(shù)中反射并獲取 "android.util.BoostFramework”類的相應(yīng)函數(shù)

提供 boostCpu 函數(shù),該函數(shù)傳入一個參數(shù),表示提升CPU頻率持續(xù)多久,該函數(shù)內(nèi)部調(diào)用perfLockAcquire 函數(shù) 將所有CPU頻率提升到最高值

提供 stopBoost 函數(shù),該函數(shù)會將前面調(diào)用的boostCpu 效果提前取消。

package com.knightboost.optimize.cpuboost


import android.content.Context
import java.lang.reflect.Method
import java.util.concurrent.CopyOnWriteArrayList


class QcmCpuPerformance : CpuPerformance {


    companion object {
        const val TAG = "QcmCpuPerformance";
        /**
         * 是否允許CPU進入深度低功耗模式, 對應(yīng) /dev/cpu_dma_latency, 默認空,不允許則設(shè)置為1
         */
        const val MPCTLV3_ALL_CPUS_PWR_CLPS_DIS = 0x40400000


        /**
         * 設(shè)置小核最小頻率,十六進制
         */
        const val MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40800100


        /**
         * 設(shè)置小核最大頻率, 十六進制
         */
        const val MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40804100


        /**
         * 設(shè)置大核最小頻率,十六進制
         */
        const val MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0 = 0x40800000


        /**
         * 設(shè)置大核最大頻率,十六進制
         */
        const val MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0 = 0x40804000


        const val MPCTLV3_MIN_FREQ_CLUSTER_PLUS_CORE_0 = 0x40800200;


        const val MPCTLV3_MAX_FREQ_CLUSTER_PLUS_CORE_0 = 0x40804200


        /**
         * 調(diào)度優(yōu)化?  啟動 值為01
         */
        const val MPCTLV3_SCHED_BOOST = 0x40C00000;


    }


    var initSuccess = false


    lateinit var acquireFunc: Method
    lateinit var mPerfHintFunc: Method
    lateinit var releaseFunc: Method
    lateinit var frameworkInstance: Any


    var boostHandlers = CopyOnWriteArrayList<Int>()


    /**
     * 配置: 請求將所有CPU核心頻率拉滿,并禁止進入深入低功耗模式
     */
    private var CONFIGS_FREQUENCY_HIGH = intArrayOf(
        MPCTLV3_SCHED_BOOST, 1,
        MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 1,
        MPCTLV3_MAX_FREQ_CLUSTER_BIG_CORE_0, 0xFFF,
        MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
        MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0, 0xFFF,
        MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0, 0xFFF,
        MPCTLV3_MIN_FREQ_CLUSTER_PLUS_CORE_0, 0xFFF,
        MPCTLV3_MAX_FREQ_CLUSTER_PLUS_CORE_0, 0xFFF,
    )


    var DISABLE_POWER_COLLAPSE = intArrayOf(MPCTLV3_ALL_CPUS_PWR_CLPS_DIS, 1)


    /**
     * 初始化CpuBoost 核心功能
     */
    override fun init(context: Context): Boolean {
        try {
            val boostFrameworkClass = Class.forName("android.util.BoostFramework")


            val constructor = boostFrameworkClass.getConstructor(Context::class.java)
                ?: return false


            frameworkInstance = constructor.newInstance(context)


            acquireFunc = boostFrameworkClass.getDeclaredMethod(
                "perfLockAcquire", Integer.TYPE, IntArray::class.java
            )


            mPerfHintFunc = boostFrameworkClass.getMethod(
                "perfHint", Int::class.javaPrimitiveType, String::class.java, Int::class.javaPrimitiveType, Int::class.javaPrimitiveType
            )


            releaseFunc = boostFrameworkClass.getDeclaredMethod(
                "perfLockReleaseHandler", Integer.TYPE
            )
            initSuccess = true
            return true
        } catch (e: Exception) {
            initSuccess = false
            CpuBoostManager.boostErrorLog(TAG, "init failed", e)
            return false
        }
    }


    /**
     * 提升所有核心CPU頻率到最高頻率
     */
    override fun boostCpu(duration: Int): Boolean {
        if (!initSuccess) return false
        return try {
            perfLockAcquire(duration, DISABLE_POWER_COLLAPSE)
            perfLockAcquire(duration, CONFIGS_FREQUENCY_HIGH)
            return true
        } catch (e: Exception) {
            CpuBoostManager.boostErrorLog(TAG, "boostCpuFailed", e)
            false
        }
    }


    /**
     *   Toggle off all optimizations requested Immediately.
     *   Use this function if you want to release before the time duration ends.
     *
     *   這個函數(shù)并不強制調(diào)用,只用于提前取消所有已配置的加速效果。
     */
    override fun stopBoost() {
        val handlers = boostHandlers.toTypedArray()
        for (handler in handlers) {
            try {
                releaseFunc.invoke(frameworkInstance, handler)
            } catch (e: Exception) {
                e.printStackTrace()
            }
        }
    }


    /**
     * Toggle on all optimizations requested.
     * @param duration: The maximum amount of time required to hold the lock.
     *       Only a positive integer value in milliseconds will be accepted.
     *       You may explicitly call perfLockRelease before the timer expires.
     * @param list Enter all optimizations required. Only the optimizations in the
     *       table below are supported. You can only choose one optimization
     *       from each of the numbered sections in the table. Incorrect or
     *       unsupported optimizations will be ignored.
     *
     *       NOTE: Enter the optimizations required in the order they appear in the table.
     */
    private fun perfLockAcquire(duration: Int, list: IntArray): Int {
        val handler = acquireFunc.invoke(frameworkInstance, duration, list) as Int;
        if (handler > 0) {
            boostHandlers.add(handler)
        }
        return handler
    }


}

1.3 驗證

通過讀取:

/sys/devices/system/cpu/cpu$cpuIndex/cpufreq/下的文件可以獲取對應(yīng)CPU所能運行的最小、最大、以及當前的頻率。

在提頻前,當前設(shè)備的CPU頻率信息如下:

可以發(fā)現(xiàn)提頻前,0~3 這些小核中,3個運行在最大調(diào)頻頻率,1個運行在最小調(diào)頻頻率。4~6中核都運行在最小頻率,7號大核直接摸魚運行在最小頻率。

在提頻后,運行數(shù)據(jù)如下:

可以看出,進行提頻后,所有核心都運行在最大頻率上,整機頻率相比之前提升30%, 當然在實際運行過程中,提頻前的工作頻率并不會這么低,這里的數(shù)據(jù)是從CPU幾乎空閑狀態(tài)到直接滿頻的情況。

2、線性CPU親和性

2.1 概念

根據(jù)wikipedia上的解釋,通過設(shè)置CPU親和性可以控制線程在哪些CPU上運行。

通過CPU親和性的概念可以提高線程的運行效率,比如由于CPU存在緩存機制,通過CPU親和性(CPU Affinity)讓同一個線程被重新調(diào)度時,盡量調(diào)度到同一個處理器上,這樣就可以可以避免不必要的 Cache Miss。另一種情況,比如對于一組相同的任務(wù),它們需要訪問的內(nèi)存大部分是相同的,如果控制這組任務(wù)調(diào)度在相同的CPU上,也可以共享相同的cache,從而提高程序的訪問效率。

CPU親和性分為2種,分別為軟親和性和硬親和性:

  • 軟親和性: linux系統(tǒng)會盡可能將一個進程保持在指定的CPU上運行,但不嚴格保證,當所指定的CPU非常繁忙時,它可以遷移到其他空閑CPU上執(zhí)行
  • 硬親和性:linux系統(tǒng)允許指定某個進程運行在特定的一個或一組CPU上,并且只能運行在這些特定的CPU上。

在下文中,我們討論的親和性控制將只涉及到硬親和性。

2.2 親和性控制

2.2.1 API

在linux系統(tǒng)中,可以通過taskset命令或者程序中調(diào)用 sched_setaffinity 指定線程的CPU親和性。

taskset的具體用法為 taskset [-ap] [mask] [PID]

這里的mask指的是CPU掩碼,CPU掩碼描述了具體哪些CPU,以8核CPU為例,

二進制 00000011 (十進制值為3), 表示CPU序號1 和2, 當調(diào)用命令 tasket -p 3 2001 表示序號為2001的進程將只會運行在 cpu 1 或2 上。也就是說CPU掩碼根據(jù)對應(yīng)二進制位置及其0或1的值,表示某個線程的CPU相關(guān)親和性。

當我嘗試在 Android設(shè)備上直接調(diào)用 taskset命令,系統(tǒng)提示無權(quán)限。

為了進一步了解 taskset程序的實現(xiàn),為后續(xù)我們自己實現(xiàn)CPU控制提供參考,這里研究了一下其實現(xiàn)代碼。該工具的實現(xiàn)源碼在 util-linux項目中。

上面提示的 `failed to get xx's affinity`其實是在調(diào)用 sched_getaffinity 函數(shù)時就失敗了。這里我的設(shè)備未Root,因此猜測原因為 sched_setaffinity 、sched_getaffinity 底層涉及的系統(tǒng)調(diào)用只有當前進程才有權(quán)限控制其自身的affinity屬性。

通過其源碼實現(xiàn)可以發(fā)現(xiàn)該工具實現(xiàn)就是套了層皮,底層實現(xiàn)還是調(diào)用的 sched_setaffinity函數(shù)。

2.3 應(yīng)用層控制實現(xiàn)

有了上述背景,在native層編寫一個CPU親和性控制的函數(shù)就比較簡單了,主要涉及到sched.h頭文件的幾個函數(shù), 以下為最終實現(xiàn)示例代碼

#include <jni.h>
#include "unistd.h"
#include "sched.h"
#include "android/log.h"
Java_com_knightboost_optimize_cpuboost_ThreadCpuAffinityManager_setCpuAffinity(JNIEnv *env,
                                                                            jclass clazz,
                                                                            jint tid,
                                                                            jintArray cpu_set) {
  if (tid <= 0) {
    tid = gettid();
  }
  // 獲取當前CPU核心數(shù)
  int cpu_count = sysconf(_SC_NPROCESSORS_CONF);
  jsize size = env->GetArrayLength(cpu_set);
  jint bind_cpus[size];
  env->GetIntArrayRegion(cpu_set, 0, size, bind_cpus);


  cpu_set_t mask;
  CPU_ZERO(&mask);
  for (jint cpu : bind_cpus) {
    if (cpu > 0 && cpu < cpu_count) {
      CPU_SET(cpu, &mask); //設(shè)置對應(yīng)cpu位置的值為1
    } else {
      __android_log_print(ANDROID_LOG_ERROR,
                          "TCpuAffinity",
                          "try bind illegal cpu index %d",cpu);
    }
  }


  int code = sched_setaffinity(tid, sizeof(mask), &mask);
  if (code == 0) {
    // return success
    return JNI_TRUE;
  } else {
    __android_log_print(ANDROID_LOG_ERROR,
                        "TCpuAffinity",
                        "setCpuAffinity() failed code %d",code);
    // return failed
    return JNI_FALSE;
  }


}

該函數(shù)中,首先獲取了當前的CPU核心數(shù),接下來創(chuàng)建一個 cpu_set_t mask變量,調(diào)用宏函數(shù) CPU_SET 將對應(yīng)位置的二進制值設(shè)置為1, 最后調(diào)用 sched_setaffinity 設(shè)置相應(yīng)線程的CPU親和性。

在實際應(yīng)用場景中,我們可以將某個線程需要執(zhí)行繁重任務(wù)時,將它綁定到大核上,當任務(wù)執(zhí)行結(jié)束時,再還原原始的CPU親和性值或者將其CPU親和性值重置為所有CPU。

2.4 驗證

到目前所講的都還是理論階段,那么我們?nèi)绾未_認修改線程的CPU親和性之后,這個線程確實被遷移到目標CPU上執(zhí)行了呢?

在之前寫過的一篇CPU相關(guān)的文章《Android 高版本采集系統(tǒng)CPU使用率的方式》中,我們提及了 stat文件記錄了線程當前指向狀態(tài)的相關(guān)信息。根據(jù)linux手冊, 第 39 處的值就表示了該線程最后運行的CPU。

因此通過讀取該文件,我們就可以獲取線程所運行在哪個CPU上:

/**
     * 獲取目標線程最后運行在哪個CPU
     */
    fun getLastRunOnCpu(tid:Int):Int{
        var path = "/proc/${android.os.Process.myPid()}/task/${tid}/stat"
        try {
            val content = File(path).readText()
            var arrays = StringUtil.splitWorker(content,' ')
            var cpu = arrays[38]
            return cpu.toInt()
        }catch (e:Exception){
            // this task  may already have ended
            return -1;
        }


    }

這里我們需要獲取Java線程對應(yīng)操作系統(tǒng)的線程id(tid),關(guān)于 tid 的獲取可以參考之前的文章:《Android虛擬機線程啟動過程解析, 獲取Java線程真實線程Id的方式》。

我們通過獲取Java Thread對象的 nativePeer值,這個地址對應(yīng)了Android native層的Thread對象指針地址,再根據(jù)tls_32bit_sized_values結(jié)構(gòu)的tid屬性偏移值,進行類型強轉(zhuǎn),從而獲取系統(tǒng)線程id。

在demo中,在修改目標線程CPU后,我們可以持續(xù)打印這個值,以驗證綁核是否成功。

這里我嘗試將目標線程的 affinity修改為大核(CPU序號7),打印結(jié)果如下:

可以看到,在執(zhí)行修改前,目標線程的CPU親和性為0~7核心,且最近1秒基本運行在CPU核心2上,在修改CPU親和性為CPU7后, 目標線程只會運行在CPU7 上。這驗證了功能確實生效了。

3、線程優(yōu)先級

3.1 概念

除了CPU頻率、線程CPU親和性,線程的優(yōu)先級也會影響線程對CPU的使用,線程優(yōu)先級更高意味該線程有更高的概率獲得CPU的執(zhí)行,分配到更多的CPU時間片。

3.2 實現(xiàn)

在Android平臺下,可以通過Process.setThreadPriority(int tid, int priority) ,這適用于無法獲取目標線程的Thread對象,只知道目標線程tid的情況。

當然,如果能夠獲取到Thread對象,也可以通過 Thred對象的 setPriority(int newPriority)設(shè)置。

需要注意的是,這2個函數(shù)優(yōu)先級int值的定義和范圍是不同的,第一個函數(shù)是Android系統(tǒng)提供的Java接口,它的優(yōu)先級沿用linux對線程的優(yōu)先級定義 (-20~19),而第二個函數(shù)是Java jdk提供的,它的優(yōu)先級范圍為1~10。

另外,Process.setThreadPriority(int tid, int priority) 這里的tid 需要的是實際的操作系統(tǒng)線程ID,而不是Java中Thread的id。

另一方面,Thread.setPriority(int newPriority) 函數(shù)設(shè)置的優(yōu)先級并沒有達到最大值,我們測試下使用Thread對象的設(shè)置優(yōu)先級函數(shù)為最高值(Thread.MAX_PRIORITY) 之后的nice值 ,并和 Process.setThreadPriority進行比較,測試代碼如下:

Thread{
            var currentThread = Thread.currentThread()
            var tid = ArtThread.getTid(currentThread)
            Log.e("priorityTest","當前線程 $tid" +
                    " java優(yōu)先級 ${currentThread.priority} nice值 ${ThreadUtil.getNice(tid)}")
            currentThread.priority=Thread.MAX_PRIORITY;
            Log.e("priorityTest","使用 Thread.setPriority 設(shè)置最高優(yōu)級10 后  nice值 ${ThreadUtil.getNice(tid)}")
            Process.setThreadPriority(tid,-20)
            Log.e("priorityTest","使用 Process.setThreadPriority 設(shè)置最高優(yōu)級-20 后  nice值 ${ThreadUtil.getNice(tid)}")
        }.start()

測試結(jié)果如下:

由此可見,如果希望最大程度提高線程優(yōu)先級的話,還是需要使用Process的函數(shù)。

那么這里為什么Android系統(tǒng)下通過Thread.setPriority 設(shè)置的最高優(yōu)先級nice值為什么為-8呢?通過跟蹤native層代碼路徑發(fā)現(xiàn),這里Java線程優(yōu)先級的1~10 在底層的取值 其實是映射了使一個數(shù)組,該數(shù)組存儲了對應(yīng)設(shè)置的nice優(yōu)先級,其中的最高優(yōu)先級10對應(yīng)的 ANDROID_PRIORITY_URGENT_DISPLAY 對應(yīng)的nice值就為-8

Android系統(tǒng)對于什么情況下使用什么nice值 完整定義如下:

3.3 驗證

為了驗證設(shè)置線程優(yōu)先級對線程獲得CPU時間片的提升效果,我們創(chuàng)建一組工作線程,并同時執(zhí)行,每個線程會執(zhí)行一個類似死循環(huán)的工作,這樣每個線程都不會主動讓出CPU,工作5秒后,計算當前線程得到CPU執(zhí)行的時間。為了更好對比線程優(yōu)先級對CPU時間片分配的影響,我們將這組線程統(tǒng)一綁定到一個核心上,這樣可以更好的觀測線程優(yōu)先級對CPU時間片分配的的影響。

根據(jù)輸出結(jié)果可以發(fā)現(xiàn),優(yōu)先級為-20的線程占用了cpu98%的執(zhí)行時間,其他線程幾乎沒得到執(zhí)行。

而如果將線程優(yōu)先級修改為0,也就是默認的線程優(yōu)先級,那么這4個線程將會得到幾乎相同的執(zhí)行時間。

圖片圖片

從這個結(jié)果看,線程優(yōu)先級的效果還是比較明顯的。

不過在實際情況中,如果這些線程并沒有特別指定在某個CPU執(zhí)行,那么它們可能會在任何CPU上執(zhí)行,系統(tǒng)會自動將線程調(diào)度到其他不繁忙的CPU上。

以下是指定了 task4的優(yōu)先級,但并沒有綁定CPU核的情況輸出的結(jié)果:

圖片圖片

這里有2個信息:

  • 一開始task可能會被分配在相同的CPU上,但由于我們的任務(wù)幾乎是一個空循環(huán)任務(wù),對CPU的使用率較高,此時每個任務(wù)都無法得到足夠的CPU時間片執(zhí)行,而1、4核心可能又幾乎是空閑的,因此當系統(tǒng)發(fā)現(xiàn)某些CPU負責較高時,系統(tǒng)自動將部分線程任務(wù)遷移到空閑的CPU上執(zhí)行
  • 由于線程被分配的不同的CPU上,因此這幾個線程之間不存在優(yōu)先級比較關(guān)系,因此每個任務(wù)都得到了充足的CPU時間執(zhí)行。

從這里我們也可以看出,不合理的強綁定CPU核心, 有時候可能會起到相反的效果。

4、總結(jié)

本文分享了Android系統(tǒng)下自主控制CPU頻率、線程指定核心和優(yōu)先級的方式,不過這些能力需要具體落實到業(yè)務(wù)場景才能夠獲得實際的收益。后續(xù)我們將在進程冷啟動、Activity啟動階段、頁面滑動、幀渲染線程優(yōu)化、等業(yè)務(wù)場景進行嘗試。

參考資料:

  • 升頻計算公式:https://docs.kernel.org/scheduler/schedutil.html
  • 高通BoostFramework概要介紹: https://juejin.cn/post/7141196697555714079
  • BosstFrameowrk:https://gerrit.pixelexperience.org/plugins/gitiles/frameworks_base/+/0420df35ae49ed11d503571aa76f80a154f1b4ac/core/java/android/util/BoostFramework.java
  • Android虛擬機線程啟動過程解析, 獲取Java線程真實線程id的方式:https://juejin.cn/post/7138690370694545415
  • Android 高版本采集系統(tǒng)CPU使用率的方式:https://juejin.cn/post/7135034198158475300
  • https://lwn.net/Articles/792502/
  • https://dumps.tadiphone.dev/dumps/oneplus/op516el1/-/blob/qssi-user-13-SKQ1.220519.001-S.202208250304-release-keys--ALLNET/vendor/etc/powerhint.xml
  • https://deepinout.com/qcom-camx-debug-user-guide/camx-perf-debug-user-guide/qcom-perflock-usage.html
  • http://www.manongzj.com/blog/31-sgltmktizd.html
  • powerhint.xml、powerhint.xml
  • https://en.wikipedia.org/wiki/Processor_affinity

責任編輯:武曉燕 來源: 得物技術(shù)
相關(guān)推薦

2009-08-28 17:10:59

C#線程優(yōu)先級

2010-03-18 14:09:20

Java線程同步

2025-02-03 08:23:33

2012-08-14 09:38:29

WAN優(yōu)化

2024-04-30 11:00:10

數(shù)據(jù)中心

2020-06-04 08:36:55

Linux內(nèi)核線程

2022-12-23 09:41:14

優(yōu)先級反轉(zhuǎn)

2023-03-06 07:53:36

JavaN種內(nèi)部類

2024-05-20 10:03:15

線程池優(yōu)先級隊列排序方法

2022-06-02 09:29:55

線程組線程樹狀結(jié)構(gòu)

2010-09-13 17:30:07

CSS優(yōu)先級

2010-08-31 11:04:48

CSS優(yōu)先級

2010-09-01 14:10:36

CSS優(yōu)先級

2024-12-03 00:44:50

2020-09-30 09:07:37

DevOps

2025-05-26 09:40:02

!importantCSS 優(yōu)先級開發(fā)

2021-04-06 10:45:18

React前端優(yōu)先級

2023-10-25 10:21:24

瀏覽器HTTP請求

2010-09-06 14:53:27

CSS優(yōu)先級

2009-08-12 13:07:13

C#運算符優(yōu)先級
點贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 国产精品欧美一区二区三区不卡 | 中文字幕日韩在线 | 成年免费在线观看 | 亚州毛片| 久久亚洲国产精品日日av夜夜 | 国产高清视频在线 | 久久国产欧美一区二区三区精品 | 亚洲日韩中文字幕一区 | 国产精品伦理一区二区三区 | 羞羞视频在线观免费观看 | 国产精品高清在线 | 亚洲精品国产精品国自产在线 | 国产精品不卡一区 | 欧美日韩在线一区二区 | 综合成人在线 | 国产a区 | 欧美一区不卡 | 久久蜜桃资源一区二区老牛 | 黄色视频a级毛片 | 亚洲 欧美 日韩 精品 | 国产亚洲精品久久久久久牛牛 | 99热激情| www.国产| 久久综合一区二区 | 水蜜桃亚洲一二三四在线 | 亚洲欧美在线观看 | 午夜视频一区二区 | 免费超碰 | 777777777亚洲妇女 | 欧美性网 | 成人av在线播放 | 中国一级特黄毛片大片 | 久久久久久免费毛片精品 | 一区二区三区免费 | 久久久久综合 | 人人做人人澡人人爽欧美 | 日本天天色 | 国产女人第一次做爰毛片 | 日韩成人在线一区 | 欧美日韩高清一区 | 久久综合99 |