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

.NET、Mono與Java、C++性能測試大PK

原創
開發 后端 新聞
四年一屆的世界杯終于落下帷幕,四支強隊為金杯曾展開最后的爭奪。而在開發領域,.NET、Mono與Java、C++之間的爭論似乎一直沒有停過,本文將為大家做一個橫向的對比,看看誰的性能更好。

【51CTO外電頭條】任何計算設備硬件資源都是有限的,越多的程序和服務競爭資源,用戶的體驗越糟糕(通常表現為延遲較長),性能下降的部分原因是因為安裝了不需要的組件,還有部分原因是程序內部的設計問題,如讓程序隨系統啟動而啟動,或不管你是否會使用它,都讓它在后臺運行著,這些運行著但又未使用的進程都會搶占有限的系統資源。

雖然我見過一些有關程序性能測試的文章,但卻未見過對程序的啟動時間進行測試的,更別說是不同編程語言(框架),或同一框架的不同版本了,但這種測試結果對于選擇特定硬件系統后,確定編程語言是非常有幫助的。本文將介紹當前比較流行的語言(框架) -.NET,Java,Mono和C++程序的啟動性能對比,所有測試都是在它們各自的默認設置下進行的。但.NET,Mono,Java托管代碼和C++原生代碼誰的啟動時間最短,誰的性能***呢?首先來看一下熱啟動的對比結果吧!

熱啟動性能對比

圖 1 Mono,Java,.NET和C++程序熱啟動性能對比(值越小越好)

由于測試中有諸多因素會影響結果,為了使測試結果顯得更公平,我們只使用了一些簡單的,可重復的測試,所有語言都可執行這些測試。

首先我們要測試的是從進程創建到進入main函數所花的時間,簡稱為“啟動時間”,要精確地測試出啟動時間是很困難的,有時只有憑用戶的感覺,接下來測量了內存占用情況,內核和用戶消耗的處理器時間。

如何計算啟動時間

在下面的內容中,凡是提到操作系統API,我指的操作系統都是指Windows XP,由于沒有現成的操作系統API可以獲得程序的啟動時間,因此我用了自己發明的方法來計算,我使用了簡單的進程間通信機制來解決這個問題,創建進程時將創建時間作為一個命令行參數傳遞給測試進程,執行到退出代碼時返回當前時間和創建時間的差,具體步驟說明如下:

在調用者進程(BenchMarkStartup.exe)中獲得當前的UTC系統時間;

啟動測試進程,將前面獲得的進程創建時間作為參數傳遞給它;

在分支進程中,獲得main函數開始執行時的當前系統UTC時間;

在同一進程中,計算并調整時間差;

執行到退出代碼時返回時間差;

在調用者進程(BenchMarkStartup.exe)中捕捉退出代碼。

本文會使用到兩個啟動時間:冷啟動時間和熱啟動時間,冷啟動表示系統重啟后,程序的***次啟動時間,熱啟動時間表示程序關閉后,再次啟動所花的時間。冷啟動需要的時間往往會長一些,因為需要加載I/O組件,熱啟動可以利用操作系統的預取功能,因此熱啟動的時間要短得多。

影響性能的因素

對于托管的運行時,與原生代碼比起來,JIT編譯器將會消耗額外的CPU時間和內存。特別是對于冷啟動時間的對比可能會有失公允,C++原生代碼肯定會占有優勢,而托管型的Mono,Java和.NET代碼需要更長的加載時間。另外,如果其它程序加載了你需要的庫,I/O操作也會減少,啟動時間也會得到改善。在Java方面,也有一些啟動加速程序,如Java Quick Starter,Jinitiator,為了公平起見,應該禁用它們。緩存和預取功能也應該留給操作系統去管理,不要浪費不必要的資源。

C++性能測試代碼

C++測試代碼是直接由調用者進程調用的,當它獲得一個命令行參數時,它會將其轉換成__int64來表示FILETIME,其值是從1601/1/1到現在的100 毫微秒間隔數,因此我們可以獲得時間差,以毫秒數返回,用32位大小就足夠了。

  1. int _tmain(int argc, _TCHAR* argv[])  
  2. {  
  3.    
  4.     FILETIME   ft;  
  5.     GetSystemTimeAsFileTime(&ft);  
  6.     static const __int64 startEpoch2 = 0; // 1601/1/1  
  7.     if( argc < 2 )  
  8.     {  
  9.     ::Sleep(5000);  
  10.     return -1;  
  11.     }  
  12.     FILETIME userTime;  
  13.     FILETIME kernelTime;  
  14.     FILETIME createTime;  
  15.     FILETIME exitTime;  
  16.    
  17.     if(GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime))  
  18.     {  
  19.       __int64 diff;  
  20.       __int64 *pMainEntryTime = reinterpret_cast<__int64 *>(&ft);  
  21.       _int64 launchTime = _tstoi64(argv[1]);  
  22.       diff = (*pMainEntryTime -launchTime)/10000;      
  23.       return (int)diff;  
  24.     }  
  25.     else 
  26.         return -1;  

下面是創建測試進程的代碼,傳遞給它的是初始時間,返回的是啟動時間。***個調用計算冷啟動時間,后面的調用計算的是熱啟動時間。

  1. DWORD BenchMarkTimes( LPCTSTR szcProg)  
  2. {  
  3.     ZeroMemory( strtupTimes, sizeof(strtupTimes) );  
  4.     ZeroMemory( kernelTimes, sizeof(kernelTimes) );  
  5.     ZeroMemory( preCreationTimes, sizeof(preCreationTimes) );  
  6.     ZeroMemory( userTimes, sizeof(userTimes) );  
  7.     BOOL res = TRUE;  
  8.     TCHAR cmd[100];  
  9.     int i,result = 0;  
  10.     DWORD dwerr = 0;  
  11.     PrepareColdStart();  
  12.     ::Sleep(3000);//3秒延遲  
  13.     for(i = 0; i <= COUNT && res; i++)  
  14.     {  
  15.         STARTUPINFO si;  
  16.         PROCESS_INFORMATION pi;  
  17.         ZeroMemory( &si, sizeof(si) );  
  18.         si.cb = sizeof(si);  
  19.         ZeroMemory( &pi, sizeof(pi) );  
  20.         ::SetLastError(0);  
  21.         __int64 wft = 0;  
  22.         if(StrStrI(szcProg, _T("java")) && !StrStrI(szcProg, _T(".exe")))  
  23.         {  
  24.             wft = currentWindowsFileTime();  
  25.             _stprintf_s(cmd,100,_T("java -client -cp .\\.. %s \"%I64d\""), szcProg,wft);  
  26.         }  
  27.         else if(StrStrI(szcProg, _T("mono")) && StrStrI(szcProg, _T(".exe")))  
  28.         {   
  29.                 wft = currentWindowsFileTime();  
  30.                 _stprintf_s(cmd,100,_T("mono %s \"%I64d\""), szcProg,wft);  
  31.         }  
  32.         else 
  33.         {  
  34.                 wft = currentWindowsFileTime();  
  35.                 _stprintf_s(cmd,100,_T("%s \"%I64d\""), szcProg,wft);           
  36.         }  
  37.    
  38.         // 啟動子進程   
  39.         if( !CreateProcess( NULL,cmd,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi ))   
  40.         {  
  41.             dwerr = GetLastError();  
  42.  _tprintf( _T("CreateProcess failed for '%s' with error code %d:%s.\n"),szcProg, dwerr,GetErrorDescription(dwerr) );  
  43.             return dwerr;  
  44.             //中斷;  
  45.         }  
  46.    
  47.         //等待20秒,或直到子進程退出  
  48.         dwerr = WaitForSingleObject( pi.hProcess, 20000 );  
  49.         if(dwerr != WAIT_OBJECT_0)  
  50.         {  
  51.             dwerr = GetLastError();  
  52.  _tprintf( _T("WaitForSingleObject failed for '%s' with error code %d\n"),szcProg, dwerr );  
  53.             // 關閉進程和線程處理   
  54.             CloseHandle( pi.hProcess );  
  55.             CloseHandle( pi.hThread );  
  56.             break;  
  57.         }  
  58.         res = GetExitCodeProcess(pi.hProcess,(LPDWORD)&result);  
  59.         FILETIME CreationTime,ExitTime,KernelTime,UserTime;  
  60.         if(GetProcessTimes(pi.hProcess,&CreationTime,&ExitTime,&KernelTime,&UserTime))  
  61.         {  
  62.             __int64 *pKT,*pUT, *pCT;  
  63.             pKT = reinterpret_cast<__int64 *>(&KernelTime);  
  64.             pUT = reinterpret_cast<__int64 *>(&UserTime);  
  65.             pCT = reinterpret_cast<__int64 *>(&CreationTime);  
  66.             if(i == 0)  
  67.             {  
  68.                 _tprintf( _T("cold start times:\nStartupTime %d ms"), result);  
  69.                 _tprintf( _T(", PreCreationTime: %u ms"), ((*pCT)- wft)/ 10000);   
  70.                 _tprintf( _T(", KernelTime: %u ms"), (*pKT) / 10000);  
  71.                 _tprintf( _T(", UserTime: %u ms\n"), (*pUT) / 10000);   
  72.                 _tprintf( _T("Waiting for statistics for %d warm samples"), COUNT);   
  73.             }  
  74.             else 
  75.             {  
  76.                 _tprintf( _T("."));  
  77.                 kernelTimes[i-1] = (int)((*pKT) / 10000);  
  78.                 preCreationTimes[i-1] = (int)((*pCT)- wft)/ 10000;   
  79.                 userTimes[i-1] = (int)((*pUT) / 10000);  
  80.                 strtupTimes[i-1] = result;      
  81.             }  
  82.         }  
  83.         else 
  84.         {  
  85.             printf( "GetProcessTimes failed for %p", pi.hProcess );   
  86.         }  
  87.         // 關閉進程和線程處理   
  88.         CloseHandle( pi.hProcess );  
  89.         CloseHandle( pi.hThread );  
  90.         if((int)result < 0)  
  91.         {  
  92.             _tprintf( _T("%s failed with code %d: %s\n"),cmd, result,GetErrorDescription(result) );  
  93.             return result;  
  94.         }  
  95.         ::Sleep(1000); //1秒延時  
  96.     }  
  97.     if(i <= COUNT )  
  98.     {  
  99.        _tprintf( _T("\nThere was an error while running '%s', last error code = %d\n"),cmd,GetLastError());  
  100.        return result;  
  101.     }  
  102.     double median, mean, stddev;  
  103.     if(CalculateStatistics(&strtupTimes[0], COUNT, median, mean, stddev))  
  104.     {  
  105.         _tprintf( _T("\nStartupTime: mean = %6.2f ms, median = %3.0f ms, standard deviation = %6.2f ms\n"),   
  106.             mean,median,stddev);  
  107.     }  
  108.     if(CalculateStatistics(&preCreationTimes[0], COUNT, median, mean, stddev))  
  109.     {  
  110.         _tprintf( _T("PreCreation: mean = %6.2f ms, median = %3.0f ms, standard deviation = %6.2f ms\n"),   
  111.             mean,median,stddev);  
  112.     }  
  113.     if(CalculateStatistics(&kernelTimes[0], COUNT, median, mean, stddev))  
  114.     {  
  115.         _tprintf( _T("KernelTime : mean = %6.2f ms, median = %3.0f ms, standard deviation = %6.2f ms\n"),   
  116.             mean,median,stddev);  
  117.     }  
  118.     if(CalculateStatistics(&userTimes[0], COUNT, median, mean, stddev))  
  119.     {  
  120.         _tprintf( _T("UserTime   : mean = %6.2f ms, median = %3.0f ms, standard deviation = %6.2f ms\n"),   
  121.             mean,median,stddev);  
  122.     }  
  123.    
  124.     return GetLastError();  

注意啟動Mono和Java程序的命令行與.NET或原生代碼有些不同,我也沒有使用性能監視計數器。

如果你想知道我為什么沒有使用GetProcessTimes提供的創建時間,我可以告訴你有兩個原因。首先,對于.NET和Mono,需要DllImport,對于Java需要JNI,這樣就使程序變得更加臃腫了;第二個原因是我發現創建時間不是CreateProcess API被調用的真正時間。從本地硬盤運行測試時,由這兩個因素引起的時間會相差0-10毫秒,如果是從網絡驅動器運行,時間會有數百毫秒的出入,如果是從軟盤上運行,甚至可能達到幾秒。我把這個時間差叫做預創建時間,我猜測這是因為操作系統沒有考慮創建新進程時,從存儲介質讀取文件所花的時間所致,因為只在冷啟動時有這個差異,而熱啟動就沒有。

#p#

.NET和Mono C#性能測試代碼

[[12874]]

在調用的.NET代碼中計算啟動時間和C++有點不同,它使用了DateTime中的FromFileTimeUtc輔助方法。

  1. private const long TicksPerMiliSecond = TimeSpan.TicksPerSecond / 1000;  
  2. static int Main(string[] args)  
  3. {  
  4.     DateTime mainEntryTime = DateTime.UtcNow;//100 nanoseconds units since 1601/1/1  
  5.     int result = 0;  
  6.    
  7.     if (args.Length > 0)  
  8.     {  
  9.         DateTime launchTime = System.DateTime.FromFileTimeUtc(long.Parse(args[0]));  
  10.         long diff = (mainEntryTime.Ticks - launchTime.Ticks) / TicksPerMiliSecond;  
  11.         result = (int)diff;  
  12.    
  13.     }  
  14.     else 
  15.     {  
  16.         System.GC.Collect(2, GCCollectionMode.Forced);  
  17.         System.GC.WaitForPendingFinalizers();  
  18.         System.Threading.Thread.Sleep(5000);  
  19.     }  
  20.     return result;  

使用Mono

要使用Mono必須先從這里下載并安裝好Mono,然后修改環境變量PATH,增加C:\PROGRA~1\MONO-2~1.4\bin\,注意你使用的Mono版本號可能會有些不同,另外,安裝時可以不選中GTK#和XSP組件,因為本次測試用不著它們,為了簡化編譯操作,我特意寫了一個buildMono.bat批處理文件,已包含在本文提供的下載包中。

使用更多.NET版本

我還包括了1.1,2.0,3.5和4.0版本的C# Visual Studio項目,如果你只需運行二進制文件,需要下載和安裝對應的運行時,生成(Build)時需要Visual Studio 2003和Visual Studio 2010,或如果你喜歡使用命令生成,還需要特定的SDK。為了強制加載目標運行時版本,我為所有.NET執行文件創建了配置文件,內容如下,不同的地方就是版本號:

  1. <?xml version="1.0" encoding="utf-8" ?> 
  2. <configuration> 
  3. <startup> 
  4.  <supportedRuntime version="v1.1.4322" /> 
  5. </startup> 
  6. </configuration> 

Java性能測試代碼

[[12875]]

首先要從這里下載并安裝Java SDK,同樣也需要向PATH環境變量添加Java路徑,在開始生成前,還需要設置javac.exe的編譯路徑,如:

  1. set path=C:\Program Files\Java\jdk1.6.0_16\bin;%path% 
在本文提供的壓縮包中,我提供了一個buildJava.bat批處理文件來幫助你完成生成操作,Java性能測試代碼如下:
 
  1. public static void main(String[] args)  
  2. {  
  3.     long mainEntryTime = System.currentTimeMillis();//miliseconds since since 1970/1/1  
  4.     int result = 0;  
  5.     if (args.length > 0)  
  6.     {  
  7.         //FileTimeUtc adjusted for java epoch  
  8.         long fileTimeUtc = Long.parseLong(args[0]);//100 nanoseconds units since 1601/1/1  
  9. long launchTime = fileTimeUtc - 116444736000000000L;//100 nanoseconds units since 1970/1/1  
  10.         launchTime /= 10000;//miliseconds since since 1970/1/1  
  11.         result = (int)(mainEntryTime - launchTime);  
  12.     }  
  13.     else 
  14.     {  
  15.         try 
  16.         {  
  17.             System.gc();  
  18.             System.runFinalization();  
  19.             Thread.sleep(5000);  
  20.         }  
  21.         catch (Exception e)  
  22.         {  
  23.             e.printStackTrace();  
  24.         }  
  25.    
  26.     }  
  27.     java.lang.System.exit(result);  
  28. }  

由于Java缺乏測量持續時間的解決方案,我不得不使用毫秒,其它框架可以提供更細粒度的時間單位,但毫秒在這次的測試中已經夠用了。

獲取內存使用情況和處理器時間

Windows進程有許多層面都會使用內存,我將僅限于測量專用字節,最小工作集和峰值工作集。如果你想知道沒有參數時,調用的進程為什么會等待5秒,現在你應該有答案了。在等待2秒后,調用者將使用下面的代碼測量內存使用情況:

 
  1. BOOL PrintMemoryInfo( const PROCESS_INFORMATION& pi)  
  2. {  
  3.  //wait 2 seconds while the process is sleeping for 5 seconds  
  4.     if(WAIT_TIMEOUT != WaitForSingleObject( pi.hProcess, 2000 ))  
  5.      return FALSE;  
  6.     if(!EmptyWorkingSet(pi.hProcess))  
  7.     printf( "EmptyWorkingSet failed for %x\n", pi.dwProcessId );  
  8.     BOOL bres = TRUE;  
  9.     PROCESS_MEMORY_COUNTERS_EX pmc;  
  10. if ( GetProcessMemoryInfo( pi.hProcess, (PROCESS_MEMORY_COUNTERS*)&pmc, sizeof(pmc)) )  
  11.     {  
  12.     printf( "PrivateUsage: %lu KB,", pmc.PrivateUsage/1024 );  
  13.         printf( " Minimum WorkingSet: %lu KB,", pmc.WorkingSetSize/1024 );  
  14.         printf( " PeakWorkingSet: %lu KB\n", pmc.PeakWorkingSetSize/1024 );   
  15.    
  16.     }  
  17.     else 
  18.    {  
  19.     printf( "GetProcessMemoryInfo failed for %p", pi.hProcess );   
  20.     bres = FALSE;  
  21.    }  
  22.     return bres;  

最小工作集是調用的進程占用的內存由EmptyWorkingSet API收縮后,我計算出的一個值。

測試結果

這些測試產生的結果很多,我只挑選了與本文主題相關的一些數據,并將熱啟動的測試結果也一并展示出來了,如圖1所示。如果你以調試模式執行測試,產生的結果會更多,對于熱啟動,我執行了9次測試,而冷啟動只有一次,我只采用了中間值(即去掉了***分和***分),處理器內核和用戶時間被歸結到一塊兒,總稱為CPU時間,下表的結果是來自一臺奔四3.0GHz,2GB內存的Windows XP機器的測試結果。

運行時
冷啟動時間(ms)
冷啟動CPU時間(ms)
熱啟動時間(ms)
熱啟動CPU時間(ms)
專用字節(KB)
最小工作集(KB)
峰值工作集(KB)
.Net 1.1
1844
156
93
93
3244
104
4712
.Net 2.0
1609
93
78
93
6648
104
5008
.Net 3.5
1766
125
93
77
6640
104
4976
.Net 4.0
1595
77
46
77
7112
104
4832
Java 1.6
1407
108
94
92
39084
120
11976
Mono 2.6.4
1484
156
93
92
4288
100
5668
CPP code
140
30
15
15
244
40
808

注意其中.NET 2.0和.NET 4.0的熱啟動時間比熱啟動CPU時間要低,你可能認為這違背了基本的物理定律,但需要注意這里的CPU時間指的是進程的整個生命周期,而啟動時間僅僅指進入到main函數時的時間,通過這我們知道可以通過一些優化提高這些框架的啟動速度,正如你前面看到的,C++由于沒有框架,因此優勢很明顯,調用者進程通過預加載一些通用dll使啟動更快。

我沒有所有運行時的歷史數據,但從.NET各版本的表現來看,越新的版本會通過消耗更多的內存來提速,如下圖所示。

.NET框架不同版本程序熱啟動時性能表現

圖 2 .NET框架不同版本程序熱啟動時性能表現(值越小越好)

為托管運行時使用原生鏡像

除了C++原生代碼外,所有運行時都使用了中間代碼,下一步如果可能應該嘗試生成原生鏡像,并再次評估它們的性能,Java沒有一個易于使用的工具來完成這項任務,GCJ只能完成一半的任務,而且它還不是官方運行時的一部分,因此我會忽略它。Mono有一個類似的功能叫做Ahead of Time(AOT),遺憾的是,AOT尚不能在Windows上工作。.NET從一開始就支持原生代碼生成,ngen.exe就是運行時的一部分。

為了方便你,我在本文提供的壓縮包中提供了一個make_nativeimages.bat批處理文件,用它快速生成測試用程序集的原生鏡像。下表展示了.NET框架各版本原生鏡像的測試結果。

運行時
冷啟動時間(ms)
冷啟動CPU時間(ms)
熱啟動時間(ms)
熱啟動CPU時間(ms)
專用字節(KB)
最小工作集(KB)
峰值工作集(KB)
.Net 1.1
2110
140
109
109
3164
108
4364
.Net 2.0
1750
109
78
77
6592
108
4796
.Net 3.5
1859
140
78
77
6588
108
4800
.Net 4.0
1688
108
62
61
7044
104
4184

我們似乎又再次遇到違背物理定律的事情了,上表顯示原生編譯的程序集冷啟動時間更高,不必大驚小怪,因為加載原生鏡像也需要大量的I/O操作,從測試結果來看,它比加載框架所用的時間更多。

運行測試

你可以將測試的可執行文件作為一個參數傳遞給BenchMarkStartup.exe運行一個特殊的測試,對于Java,包名必須匹配目錄結構,因此JavaPerf.StartupTest需要一個..\JavaPerf文件夾。

我在本文提供的壓縮包中提供了一個runall.bat批處理文件,但它無法捕捉現實的冷啟動時間。

如果你想執行真實的測試,你可以手動重啟,或在夜間每隔20-30分鐘調度執行release文件夾的benchmark.bat批處理文件,然后從文本日志文件獲得結果。重啟機器后,它將會運行所有運行時的真實測試。

***的計算機通常會控制CPU頻率以節約能源,但這可能會影響到測試結果,因此在運行測試之前,除了前面我已經提到的事情外,你還必須將電源使用方案設置為“高性能”,以便獲得一致的結果。

小結

如果你有條件下載文后提供的壓縮包按照本文介紹的內容親自做一下對比測試,相信你對托管運行時和原生代碼有更深刻的認識,如果你正在猶豫不決地選擇開發平臺,本文也可以幫助你確定清晰的方向,另外,你還可以參照本文創建其它運行時或UI測試。

本文使用到的測試源代碼和批處理文件從這里下載,我還對Java和Mono專門制作了一個壓縮包,從這里下載。

原文名:Benchmark start-up and system performance for .Net, Mono, Java and C++ native code

【編輯推薦】

  1. 使用ASP.NET 4的自動啟動特性
  2. 詳解.NET 4.0并行計算支持歷史
  3. 詳讀.NET 4.0環境配置
  4. 詳解.NET 4.0中異常處理方面的新特性
  5. 三方面詮釋.NET 4.0的新特性 

 

責任編輯:彭凡 來源: 51CTO
相關推薦

2010-10-20 10:30:58

PHPJSP

2009-09-08 11:24:20

2014-04-17 10:37:43

C++.NET Native

2009-11-06 14:01:48

EPON接入技術

2023-11-21 16:13:38

C++代碼

2021-11-28 08:04:27

.Net性能測試

2020-05-25 17:04:09

AMD云主機評測

2019-07-29 09:19:26

編程語言PythonJava

2012-08-17 10:22:26

HTML5性能瀏覽器

2010-11-01 12:56:02

云計算高性能計算

2012-01-04 01:35:46

Power虛擬機x86性能大賽

2012-02-27 09:28:34

HadoopFourinone淘寶

2024-04-18 11:07:30

C++語言

2010-05-27 12:58:16

MySQL性能測試

2022-08-22 15:32:59

C++C代碼

2020-02-02 15:42:22

PythonC++編程語言

2021-06-10 09:40:12

C++性能優化Linux

2010-01-12 09:48:51

無線交換機

2017-12-13 08:20:15

芯片驍龍?人工智能

2013-07-31 16:56:08

系統級編程語言語言性能語言
點贊
收藏

51CTO技術棧公眾號

精品人妻一区二区三区麻豆91| 蜜桃精品一区二区| 午夜伦理在线视频| 成人午夜免费视频| 奇门遁甲1982国语版免费观看高清| 18禁裸乳无遮挡啪啪无码免费| 成人全视频在线观看在线播放高清 | 亚洲a级精品| 欧美日韩一级视频| 国产精品www在线观看| 精品国产一区二区三区四区| 国产欧美一区二区在线观看| 91精品在线看| 天天综合网久久综合网| 999成人精品视频线3| 亚洲国产高清福利视频| 国产一二三区av| 国产伦理精品| 亚洲黄色免费电影| 欧美性xxxx69| 亚洲国产精品视频在线| 日本欧美韩国一区三区| 国模私拍一区二区三区| 免费观看a级片| 韩国女主播一区二区三区| 欧美日韩亚洲综合在线 | 欧美日韩国产精品| 国产盗摄视频在线观看| 国产黄色片在线播放| 国产.精品.日韩.另类.中文.在线.播放| yiren22亚洲综合伊人22| 久久丫精品久久丫| 自拍偷拍亚洲图片| 91福利精品视频| 国产一区二区网| 中文av资源在线| 国产精品视频观看| 蜜桃av色综合| 天堂中文字幕av| 国产精品99久久久久久久女警 | 亚洲国产毛片完整版| 亚洲欧美日本一区二区| 久久精品 人人爱| 色天使色偷偷av一区二区| 黄页网站在线观看视频| 国产黄色大片在线观看| 樱桃视频在线观看一区| 中国黄色录像片| 麻豆传媒在线观看| 中文字幕日韩精品一区| 亚洲精品乱码久久久久久蜜桃91 | aiai久久| 欧美xxxx在线观看| 成人啪啪18免费游戏链接| 亚洲日本免费电影| 在线不卡中文字幕| 欧美体内she精高潮| 在线免费成人| 欧美精品vⅰdeose4hd| 午夜剧场在线免费观看| 亚洲欧洲日韩精品在线| 日韩精品在线一区| 动漫美女无遮挡免费| 精品亚洲自拍| 日韩精品免费在线播放| 国产美女精品久久| 操欧美老女人| 久久精品国产亚洲| 精品无码人妻一区二区三区| 伊人久久亚洲影院| 国产91精品青草社区| 黄色污污网站在线观看| 青青国产91久久久久久| 国产又爽又黄的激情精品视频| 亚洲无码精品在线观看| 国产精品一区在线观看乱码| 国产99视频精品免费视频36| 性感美女一级片| 99re91这里只有精品| 久久精品国产一区二区三区免费看 | 色综合久久久久网| 性猛交ⅹ×××乱大交| 国产999精品在线观看| 精品日韩一区二区| 国产全是老熟女太爽了| 色喇叭免费久久综合网| 欧美成人精品xxx| 日韩av片在线播放| 日本欧洲一区二区| 国产成人成网站在线播放青青| 日韩一级片免费观看| 国产欧美久久久精品影院| 性欧美18一19内谢| 欧美gv在线观看| 男女啊啊啊视频| 麻豆国产精品视频| 国产专区一区二区| 最新国产在线观看| 亚洲一级二级在线| 校园春色 亚洲色图| 在线播放一区二区精品视频| 亚洲亚裔videos黑人hd| 久久免费在线观看视频| 麻豆久久久久久| 精品一卡二卡三卡四卡日本乱码| 99se视频在线观看| 黑人与娇小精品av专区| 欧洲美女亚洲激情| 激情五月色综合国产精品| 欧美国产精品日韩| 伊人久久一区二区| 久久久影视传媒| 日韩精品视频在线观看视频| 欧美日韩卡一| 亚洲日韩欧美视频| 欧美一级视频免费观看| 国产一区在线观看视频| 亚洲精品一区二区三区av| 麻豆视频在线观看免费网站黄| 欧美福利视频一区| 中文字幕在线观看免费高清| 最新国产乱人伦偷精品免费网站| 91嫩草在线视频| 91在线导航| 色呦呦日韩精品| 久久久久国产精品区片区无码| 久久久久久久久丰满| 国产精品极品美女粉嫩高清在线| 天堂在线观看av| 亚洲一区欧美一区| 国产乱国产乱老熟300部视频| 久久影视一区| 国产成人av一区二区三区在线观看| 91免费国产视频| 日韩黄色影院| 欧美午夜精品理论片a级按摩| 免费看毛片的网站| 欧美日韩蜜桃| 91gao视频| 岛国成人毛片| 91精品黄色片免费大全| 日本成人精品视频| 开心九九激情九九欧美日韩精美视频电影 | 国产欧美日韩在线看| 黄色片久久久久| 免费av一区二区三区四区| 欧美在线免费视频| 青青青草网站免费视频在线观看| 欧美日韩国产色视频| 日b视频在线观看| 国产欧美精品| 欧美一区激情视频在线观看| 网友自拍亚洲| 中文字幕亚洲欧美日韩在线不卡| 欧美激情一区二区三区免费观看 | 黑人巨大精品欧美一区| 吴梦梦av在线| 日韩欧美中文在线观看| 久久久久久久久久国产精品| 噜噜噜久久,亚洲精品国产品| 亚洲国产一区视频| 加勒比精品视频| 久久综合导航| 亚洲人成网站在线播放2019| 日本一区二区三区中文字幕| 久久精品成人欧美大片| 国产aⅴ一区二区三区| 亚洲一区二区欧美日韩| 中文字幕av网址| 麻豆国产精品一区二区三区 | 91精品国产色综合久久| 国产第一页在线播放| 久久先锋资源网| 三上悠亚av一区二区三区| 国产精品久久久久一区二区三区厕所| 91在线视频一区| 老司机深夜福利在线观看| 国产亚洲欧美视频| av中文字幕免费| 精品久久久久久久大神国产| 摸摸摸bbb毛毛毛片| 国产精品性做久久久久久| 国产一区二区视频播放| 欧洲激情视频| 都市激情久久久久久久久久久| 亚洲黄色中文字幕| 精品国产欧美一区二区三区成人| 亚洲大尺度视频| 色婷婷av一区| 久久久久久久久久久久国产| 久久麻豆一区二区| 少妇丰满尤物大尺度写真| 国产精品最新自拍| 日本不卡一区二区三区四区| 欧美日韩一区二区三区不卡视频| 成人国产精品久久久久久亚洲| av在线理伦电影| 自拍偷拍亚洲欧美| 视频二区在线| 欧美一级淫片007| 亚洲图片欧美日韩| 亚洲午夜精品网| 正在播放国产对白害羞| bt7086福利一区国产| 亚洲天堂伊人网| 鲁大师成人一区二区三区| 丰满女人性猛交| 精品日产免费二区日产免费二区| 国产66精品久久久久999小说| 国产精品蜜月aⅴ在线| 日本91av在线播放| 草草草在线视频| 一本久久青青| 国产91一区二区三区| www.久久热| 国产精品久久av| 日本三级一区| 欧美极品欧美精品欧美视频| 色大18成网站www在线观看| 精品丝袜一区二区三区| 后入内射欧美99二区视频| 欧美精品自拍偷拍| a片在线免费观看| 欧美性猛交xxxx黑人| 国产第一页在线播放| 亚洲黄色录像片| 天天综合天天做| 亚洲欧洲在线观看av| ass极品国模人体欣赏| 日本一区二区三区四区在线视频 | 国产欧美1区2区3区| 黄色国产在线观看| www.在线成人| 精品人妻在线视频| 国产成人精品免费视频网站| 亚洲欧美天堂在线| 黄一区二区三区| 亚洲图片 自拍偷拍| 国产一区二区在线观看视频| 亚洲xxx在线观看| 久草在线在线精品观看| 精品久久久99| 国产伦精品一区二区三区在线观看 | 亚洲精品一区二区三区樱花| 国产成人影院| 欧洲一区二区日韩在线视频观看免费| 久久99青青| 四虎永久国产精品| 色综合久久网| 色哺乳xxxxhd奶水米仓惠香| 在线中文字幕第一区| japanese在线播放| 影音国产精品| 九九九九免费视频| 日韩精品每日更新| 国产精品区在线| 国内精品国产成人| 日韩大尺度视频| 99久久er热在这里只有精品15| 日b视频在线观看| 国产午夜精品久久久久久免费视 | www日韩tube| 日韩一区二区久久久| www在线视频| 隔壁老王国产在线精品| 电影一区二区三| 91精品国产自产在线| 日韩精品中文字幕吗一区二区| 高清不卡一区二区三区| 啪啪国产精品| 欧美激情一区二区三区在线视频| 成人3d精品动漫精品一二三| 7777在线视频| 国产精品呻吟| 牛夜精品久久久久久久| 国产成人在线色| 日本高清www| 亚洲欧美日韩一区二区三区在线观看 | 1314成人网| av午夜一区麻豆| av免费播放网站| 亚洲国产精品久久人人爱| 亚洲AV无码成人精品区东京热| 欧美日韩国产片| 日本激情一区二区三区| 这里只有精品视频| 第一av在线| 国产精品永久免费视频| 成人激情自拍| 亚洲一区二区三区免费观看| 在线看片一区| 玖玖爱视频在线| 久久综合丝袜日本网| 天天做夜夜爱爱爱| 欧美午夜www高清视频| 国产草草影院ccyycom| 亚洲美女性视频| 永久免费网站在线| 国产精品免费一区| 国产精品中文字幕制服诱惑| 欧美一区二区高清在线观看| 欧美激情亚洲| 日韩精品无码一区二区三区免费| 国产高清不卡一区二区| 久久久国产一级片| 欧美性xxxx极品hd欧美风情| 国产日韩免费视频| 一二美女精品欧洲| 欧美sm一区| 国产高清一区二区三区| 婷婷久久综合| av污在线观看| 久久久久国产精品厨房| 国产成年人免费视频| 欧美一区二区三区男人的天堂 | 欧美精品做受xxx性少妇| 色婷婷综合久久久中字幕精品久久 | 国产高清不卡视频| 中文字幕亚洲综合久久| 第84页国产精品| 久久久人人爽| 亚洲看片一区| 2一3sex性hd| 亚洲国产日韩一区二区| 国产偷拍一区二区| 日韩中文字幕视频在线| 久久99久久99精品免观看软件| 精品日韩欧美| 国产精品五区| aaaaa一级片| 色婷婷综合五月| 青春有你2免费观看完整版在线播放高清| 久久久久久久久久婷婷| 911亚洲精品| 日韩一级特黄毛片| 国产精品一区二区免费不卡| 亚洲欧美另类日本| 欧美猛男超大videosgay| 日本高清中文字幕在线| 国产欧美日韩专区发布| 欧美成人激情| 亚洲午夜激情影院| 亚洲女人小视频在线观看| 国产精品伊人久久| 欧美成人自拍视频| 99re热精品视频| 国产女大学生av| 久久嫩草精品久久久久| 日日夜夜综合网| 亚洲欧美制服综合另类| 欧美aaa视频| 一区二区三区视频| 国产伦精品一区二区三区视频青涩| 天天天天天天天天操| 精品久久久三级丝袜| 蜜桃视频m3u8在线观看| 欧美午夜欧美| 激情丁香综合五月| 久久精品久久精品久久| 日韩电影大全免费观看2023年上| 亚洲精品mv| 一区二区三区四区欧美| 国产精品影音先锋| 999这里只有精品| 亚洲视频第一页| 伊人久久大香线蕉综合影院首页| 久久av高潮av| 久久综合久久综合久久| 一二三四区视频| 欧美另类69精品久久久久9999| 国产成人一二片| 日本888xxxx| 亚洲码国产岛国毛片在线| 黄频网站在线观看| 国产精品久久久久久久久久久不卡| 91一区在线| 国产黑丝在线观看| 欧美午夜寂寞影院| 日韩伦理电影网站| 欧美一级日本a级v片| 国产在线视频一区二区三区| 亚洲国产精品午夜在线观看| 亚洲性日韩精品一区二区| 精品一区二区三区中文字幕| 国产白丝袜美女久久久久| 中文字幕不卡的av| 亚洲精品无amm毛片| 国产精品白嫩初高中害羞小美女| 伊人情人综合网| 加勒比一区二区| 欧美mv日韩mv国产| av免费在线一区| 人人妻人人做人人爽| 国产精品久久久久永久免费观看| 欧美视频久久久| 成人免费看片视频| 午夜在线一区| 久久久久久久国产精品毛片| 永久免费毛片在线播放不卡| 国产主播性色av福利精品一区|