精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

CPU調頻、線程綁核、優先級控制實踐

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

0、背景

為了進一步優化App性能,最近針對如何提高應用對CPU的資源使用、以及在多線程環境下如何提高關鍵線程的執行優先級做了技術調研。本文是對技術調研過程的階段性總結,將分別介紹普通應用如何調控App頻率、如何將指定線程綁定到特定CPU、如何通過提升線程優先級獲得更多CPU時間片。

1、CPU調頻

1.1 概念

通常更高的CPU頻率代表了更快的運行速度,一個設備可能包含多個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動態控制的。目前的Androd設備普遍采用schedutil gover進行調頻控制,它會根據運行過程的CPU負載進行調頻,不過默認的調頻存在一些限制,比如調頻之間的間隔需>10ms, 并且根據schedutil的升頻計算公式,并不保證能直接升頻到最高頻率。

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

在Android系統 :可以通過 

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

來修改目標CPU的頻率,但這需要root權限才能執行。對于普遍的應用程序,經過調研發現,高通提供了一套針對高通芯片的性能Jon告知SDKPower,利用這個套機制可以實現CPU頻率等資源的管理。

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

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

1.2 實現

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

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

圖片圖片

圖片圖片

通過對應API文檔及使用示例得知perfLocakAcquire 該函數接受 2個參數,第一個參數為持續時間、第二個參數為一個int數組,表示具體的操作,數組中的內容為 k-v 結構形式,比如 [config1,value,config2,value] . 該函數執行時會返回一個 PerfLock句柄,后續通過調用 perfLockReleaseHandler 可以提前取消之前的操作。

這里簡單羅列一些配置項對應的值:

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


/**
         * 對應控制小核最小頻率
         */
const val MPCTLV3_MIN_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40800100


/**
         * 對應控制小核最大頻率
         */
const val MPCTLV3_MAX_FREQ_CLUSTER_LITTLE_CORE_0 = 0x40804100


/**
         * 對應控制大核最小頻率
         */
const val MPCTLV3_MIN_FREQ_CLUSTER_BIG_CORE_0 = 0x40800000


/**
         * 對應控制大核最大頻率
         */
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


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

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

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

圖片圖片

根據上面的知識點,最終該工具類完整的實現代碼如下:

首先在init 函數中反射并獲取 "android.util.BoostFramework”類的相應函數

提供 boostCpu 函數,該函數傳入一個參數,表示提升CPU頻率持續多久,該函數內部調用perfLockAcquire 函數 將所有CPU頻率提升到最高值

提供 stopBoost 函數,該函數會將前面調用的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進入深度低功耗模式, 對應 /dev/cpu_dma_latency, 默認空,不允許則設置為1
         */
        const val MPCTLV3_ALL_CPUS_PWR_CLPS_DIS = 0x40400000


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


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


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


        /**
         * 設置大核最大頻率,十六進制
         */
        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


        /**
         * 調度優化?  啟動 值為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.
     *
     *   這個函數并不強制調用,只用于提前取消所有已配置的加速效果。
     */
    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/下的文件可以獲取對應CPU所能運行的最小、最大、以及當前的頻率。

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

可以發現提頻前,0~3 這些小核中,3個運行在最大調頻頻率,1個運行在最小調頻頻率。4~6中核都運行在最小頻率,7號大核直接摸魚運行在最小頻率。

在提頻后,運行數據如下:

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

2、線性CPU親和性

2.1 概念

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

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

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

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

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

2.2 親和性控制

2.2.1 API

在linux系統中,可以通過taskset命令或者程序中調用 sched_setaffinity 指定線程的CPU親和性。

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

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

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

當我嘗試在 Android設備上直接調用 taskset命令,系統提示無權限。

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

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

通過其源碼實現可以發現該工具實現就是套了層皮,底層實現還是調用的 sched_setaffinity函數。

2.3 應用層控制實現

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

#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核心數
  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); //設置對應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;
  }


}

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

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

2.4 驗證

到目前所講的都還是理論階段,那么我們如何確認修改線程的CPU親和性之后,這個線程確實被遷移到目標CPU上執行了呢?

在之前寫過的一篇CPU相關的文章《Android 高版本采集系統CPU使用率的方式》中,我們提及了 stat文件記錄了線程當前指向狀態的相關信息。根據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線程對應操作系統的線程id(tid),關于 tid 的獲取可以參考之前的文章:《Android虛擬機線程啟動過程解析, 獲取Java線程真實線程Id的方式》。

我們通過獲取Java Thread對象的 nativePeer值,這個地址對應了Android native層的Thread對象指針地址,再根據tls_32bit_sized_values結構的tid屬性偏移值,進行類型強轉,從而獲取系統線程id。

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

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

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

3、線程優先級

3.1 概念

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

3.2 實現

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

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

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

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

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

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

測試結果如下:

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

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

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

3.3 驗證

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

根據輸出結果可以發現,優先級為-20的線程占用了cpu98%的執行時間,其他線程幾乎沒得到執行。

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

圖片圖片

從這個結果看,線程優先級的效果還是比較明顯的。

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

以下是指定了 task4的優先級,但并沒有綁定CPU核的情況輸出的結果:

圖片圖片

這里有2個信息:

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

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

4、總結

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

參考資料:

  • 升頻計算公式: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 高版本采集系統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

責任編輯:武曉燕 來源: 得物技術
相關推薦

2009-08-28 17:10:59

C#線程優先級

2010-03-18 14:09:20

Java線程同步

2025-02-03 08:23:33

2012-08-14 09:38:29

WAN優化

2024-04-30 11:00:10

數據中心

2025-07-30 00:00:01

優先級線程池排序

2020-06-04 08:36:55

Linux內核線程

2022-12-23 09:41:14

優先級反轉

2023-03-06 07:53:36

JavaN種內部類

2024-05-20 10:03:15

線程池優先級隊列排序方法

2010-09-01 14:10:36

CSS優先級

2010-08-31 11:04:48

CSS優先級

2010-09-13 17:30:07

CSS優先級

2022-06-02 09:29:55

線程組線程樹狀結構

2024-12-03 00:44:50

2021-04-06 10:45:18

React前端優先級

2020-09-30 09:07:37

DevOps

2025-05-26 09:40:02

!importantCSS 優先級開發

2023-10-25 10:21:24

瀏覽器HTTP請求

2023-11-03 08:22:09

Android系統算法
點贊
收藏

51CTO技術棧公眾號

国产成人久久婷婷精品流白浆| 综合国产精品| 久久亚洲电影| 欧美日韩一区二区三区在线 | 国产精品一区二区婷婷| 久久女人天堂| 91视频xxxx| 久久久精品一区二区| 亚洲熟妇av一区二区三区 | 久久影视电视剧免费网站| 国产xxxxx在线观看| 三级外国片在线观看视频| 亚洲一区二区网站| 精品久久久久久久一区二区蜜臀| 神马影院一区二区三区| 粉嫩aⅴ一区二区三区| 91丨精品丨国产| 国产精品久久久久久久久动漫 | 国产成人av电影在线| xvideos国产精品| 中文字幕成人在线视频| 黄色片在线看| 久久久精品午夜少妇| 国产视频欧美视频| 精品丰满人妻无套内射| 亚洲黄色片视频| 女人色偷偷aa久久天堂 | jlzzjlzzjlzz亚洲人| 日本不卡免费一区| 在线亚洲免费视频| 日本一区二区三区视频免费看| 日本一区二区欧美| 精品久久对白| 亚洲www啪成人一区二区麻豆| 成人影片在线播放| 中文字幕在线观看成人| 欧美一级做a| 国产精品对白交换视频| 国内精品久久久久久久果冻传媒| 日韩aaaaaa| 欧美一区成人| 日韩日本欧美亚洲| 天天干天天舔天天操| 黄色成人在线观看网站| 日韩欧美国产一区二区| 欧美亚洲国产免费| 亚洲第一区av| 91精品一区二区三区综合在线爱 | 国产精品国产三级国产普通话三级| 国产女人水真多18毛片18精品 | 精品亚洲国产视频| 欧美熟妇精品一区二区蜜桃视频| 24小时免费看片在线观看| 成人免费观看视频| 91av视频在线| 久久只有这里有精品| 日韩中文视频| 亚洲日本一区二区三区| 国产欧美日本在线| 国产丰满美女做爰| 国产一区二区在线视频| 久久免费国产精品1| 在线 丝袜 欧美 日韩 制服| 国产亚洲精品精品国产亚洲综合| 色综合色综合色综合色综合色综合 | 日韩美女啊v在线免费观看| 亚洲尤物视频网| 91精品国产乱码久久久张津瑜| 国内精品久久久久久久影视麻豆 | 亚洲色图欧美日韩| 成人软件在线观看| 亚洲日本va午夜在线影院| 在线无限看免费粉色视频| 天堂网在线中文| 日本女人一区二区三区| 欧美精品videossex88| 国产精品一二三区在线观看| 日韩视频一二区| 91国内精品野花午夜精品 | 亚洲一级中文字幕| 精品国产一区一区二区三亚瑟| 欧美一区永久视频免费观看| 男人天堂999| 色呦呦网站在线观看| 国产欧美日韩另类一区| 国内精品一区二区| 久久天堂电影| 国产福利91精品一区二区三区| 国产精品第二页| 国产一级淫片免费| 一区二区电影在线观看| 欧美精品第一页在线播放| 制服.丝袜.亚洲.中文.综合懂色| 综合亚洲视频| 91国产美女在线观看| 中文字幕免费高清网站| 免费日韩一区二区| 68精品久久久久久欧美| 波多野结衣一区二区三区在线| 精品一区二区免费| 精品一区二区三区中文字幕 | www.天堂av.com| p色视频免费在线观看| 在线免费观看日本欧美爱情大片| 欧美另类xxx| 99久久99久久精品免费看小说.| 激情视频极品美女日韩| 999久久久免费精品国产| 蜜桃精品一区二区| avav免费在线观看| 激情另类小说区图片区视频区| 91手机视频在线观看| 国产乱码在线观看| 国产激情一区二区三区四区| 亚洲欧美国内爽妇网| 国产日韩1区| 91精品国产91热久久久做人人| 国产日韩视频一区| 日韩欧美在线精品| 中文字幕av亚洲精品一部二部| 美女精品视频一区| 999精品在线视频| 欧美三级美国一级| 久久免费视频在线| 91精品视频免费在线观看 | 亚洲人成无码网站久久99热国产| 欧美黄色视屏| 亚洲一区二区三区四区在线免费观看 | 国产精品久久综合青草亚洲AV| 老司机精品视频导航| 国产精品欧美一区二区| 91丨九色丨海角社区| 成人涩涩免费视频| av影院在线播放| 丁香花视频在线观看| 午夜精品久久久久久久蜜桃app| 免费精品99久久国产综合精品应用| 国产精品成人国产| 91精品蜜臀在线一区尤物| 成人一区二区三区仙踪林| 一级毛片精品毛片| 日韩电影免费观看中文字幕 | 国产精品拍天天在线| 综合网五月天| 好看的中文字幕在线播放| 欧美日韩国产一二三| 91人妻一区二区三区| 成人av综合网| 亚洲网站视频福利| 人妻少妇无码精品视频区| 国产一区二区三区成人欧美日韩在线观看| 亚洲影影院av| 午夜dj在线观看高清视频完整版| 欧美二区三区的天堂| 亚洲黄色小说在线观看| 欧美女激情福利| 奇米4444一区二区三区| 国产一区二区女内射| 国产精品毛片久久久久久久| 亚洲最大综合网| 香蕉大人久久国产成人av| 久久偷看各类女兵18女厕嘘嘘| 国产精品久久久久久久久毛片| 国产精品久久久久久久久免费丝袜 | 国产精选第一页| 99国产精品国产精品久久| 亚洲午夜在线观看| 岛国av免费在线观看| 欧美亚洲免费在线一区| 日韩精品国产一区| 婷婷久久五月天| 亚洲精品乱码日韩| 欧美理论电影在线播放| 黄色一级a毛片| 欧美激情一区二区三区四区| 制服丝袜综合网| 香蕉综合视频| 国产精品一区二区av| 国产裸舞福利在线视频合集| 欧美日韩在线观看一区二区| av最新在线观看| 粉嫩av一区二区三区| 久章草在线视频| 欧洲乱码伦视频免费| 成人欧美在线观看| 电影在线高清| 91精品福利在线一区二区三区| 日本免费在线播放| 欧美激情中文字幕一区二区| 宇都宫紫苑在线播放| 国产精品腿扒开做爽爽爽挤奶网站| 日本一区二区三区免费看| 成人污污视频| 中文字幕亚洲一区| 一级成人黄色片| 成人av在线影院| 久久视频免费在线| 97久久精品一区二区三区的观看方式| 久久夜色精品国产欧美乱| 人成网站在线观看| 青草久久视频| av在线电影播放| 国产午夜精品一区二区三区嫩草| 亚洲资源在线网| 一区二区在线视频观看| 国产成人精品免费久久久久| 亚洲 精品 综合 精品 自拍| 亚洲免费资源在线播放| 在线观看岛国av| 亚洲精品乱码久久久久久蜜桃麻豆| 91视频婷婷| 永久免费网站在线| 69堂亚洲精品首页| 毛片视频网站在线观看| 亚洲欧美国产77777| 亚洲精品成人无码| 成人h版在线观看| 亚洲第一天堂久久| 一本一道久久综合狠狠老| 久久亚洲国产精品日日av夜夜| eeuss鲁一区二区三区| 在线电影av不卡网址| 综合久久中文字幕| 欧美日韩激情视频8区| 香港三日本8a三级少妇三级99| 免费不卡在线观看| 日韩中文字幕久久| 午夜剧场免费在线观看| 麻豆成人91精品二区三区| 精品人妻少妇一区二区| 2023国产精品久久久精品双| 日韩欧美激情一区二区| 成人高清一区| 欧美在线视频免费播放| 91www在线| 欧美激情第三页| 日本黄在线观看| 欧美图区在线视频| 日本一区二区免费电影| 天天操天天干天天综合网| 日韩人妻无码一区二区三区| 高清国产一区二区三区| 欧美精品 - 色网| 欧美日韩国产综合网| 制服国产精品| 欧美激情理论| 手机成人av在线| 我不卡影院28| 好吊色欧美一区二区三区| 激情开心成人网| 国产成人精品久久亚洲高清不卡| 日韩福利一区| 国产精品欧美久久久| 日本精品网站| 国产美女被下药99| 白浆在线视频| 91高潮精品免费porn| 中文字幕在线免费观看视频| 精品国产自在精品国产浪潮| jizzjizz在线观看| 精品国产一区二区在线| 好操啊在线观看免费视频| 日韩成人在线视频观看| 黄色av网站免费在线观看| 亚洲国产欧美精品| 国产人妖一区二区| 日本韩国欧美国产| 自拍偷拍色综合| 欧美日本韩国一区| 精品国产av 无码一区二区三区 | 国产精品美女久久久久aⅴ国产馆 国产精品美女久久久久av爽李琼 国产精品美女久久久久高潮 | 日韩免费电影一区二区| 成人看的视频| 成人在线观看www| 久久最新网址| 成人精品一二区| 成人av色网站| 99久久99久久| 亚洲图片久久| 国产伦视频一区二区三区| 日韩精品丝袜美腿| 亚洲精品视频一二三| 亚洲97av| 最近中文字幕免费mv| 亚洲黄色高清| 三级视频中文字幕| 国产99一区视频免费| 亚洲天堂久久新| 中文字幕免费在线观看视频一区| 51调教丨国产调教视频| 国产91精品精华液一区二区三区| av无码一区二区三区| 亚洲精品黑牛一区二区三区| 亚洲在线一区二区| 亚欧日韩另类中文欧美| 亚洲欧美电影在线观看| 合欧美一区二区三区| 国产v亚洲v天堂无码久久久| 在线欧美视频| 日本丰满大乳奶| 一区二区日韩免费看| 成人精品视频在线播放| 日韩电影一区二区三区四区| 粗暴91大变态调教| 香蕉成人久久| 男女污污视频网站| 久久久国际精品| 久久精品视频18| 亚洲一区二区三区视频在线| 波多野结衣绝顶大高潮| 亚洲精品在线电影| 男人天堂一区二区| 日韩少妇与小伙激情| av资源亚洲| 国产精品99久久久久久久久| 在线精品国产亚洲| 一级二级三级欧美| 乱人伦精品视频在线观看| xxxx国产视频| 99久久精品99国产精品| 污污的视频在线免费观看| 色婷婷国产精品| 日本韩国在线观看| 欧美另类高清videos| 国产91欧美| 欧美理论一区二区| 国产视频一区三区| 国产免费a级片| 97久久精品人人爽人人爽蜜臀| 性色av无码久久一区二区三区| 亚洲美女在线国产| 国语对白做受69按摩| 日韩经典中文字幕在线观看| 韩国日本一区| 波多野结衣久草一区| 天天影视欧美综合在线观看| 亚洲不卡视频在线| 韩国av一区二区三区四区| 国产精品情侣呻吟对白视频| 亚洲色大成网站www久久九九| 五月激情丁香网| 亚洲色图激情小说| 男人在线资源站| 欧美激情精品久久久久久大尺度 | 久久婷婷麻豆| 爱爱免费小视频| 色婷婷综合中文久久一本| 日韩a在线观看| 日本亚洲欧美成人| 国产亚洲欧美日韩精品一区二区三区| 欧美成人蜜桃| 久久精品人人做人人爽电影蜜月| 极品粉嫩小仙女高潮喷水久久| 午夜国产精品影院在线观看| 天堂中文网在线| 欧美诱惑福利视频| www欧美在线观看| 中文字幕一区二区三区精彩视频| 久久99这里只有精品| 永久免费看片直接| 欧美一级欧美三级| 国产在线日本| 国产精品普通话| 国产精品国产三级国产在线观看| 看看黄色一级片| 亚洲精品乱码久久久久久黑人 | 亚洲神马久久| 色婷婷av777| 欧美日韩一区二区三区在线看| 久久77777| 国产精品福利视频| 久久久夜精品| 精品亚洲乱码一区二区| 欧美v亚洲v综合ⅴ国产v| 国产传媒av在线| 日本一区视频在线| 国产美女在线精品| 日本系列第一页| 一本色道久久88亚洲综合88| 日韩成人精品一区二区三区| 毛片av在线播放| 91免费国产在线观看| 中文字幕第315页| 亚洲精品久久久久久久久| 欧美日韩精品免费观看视完整| 亚洲一区在线直播| 成人国产亚洲欧美成人综合网| 黄色污污网站在线观看| 亚洲国模精品一区| 外国电影一区二区| 激情五月婷婷六月| 国产剧情一区二区三区| 情侣偷拍对白清晰饥渴难耐| 精品国产一区二区三区av性色 | 亚洲无线视频| 免费看黄色的视频| 日韩欧美中文一区二区| 欧美精品总汇| 欧美一区免费视频| 国产乱码精品一区二区三区av|