日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
.NET、Mono與Java、C++性能測試大PK

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

站在用戶的角度思考問題,與客戶深入溝通,找到通遼網(wǎng)站設(shè)計與通遼網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站制作、網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名申請、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋通遼地區(qū)。

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

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

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

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

如何計算啟動時間

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

在調(diào)用者進程(BenchMarkStartup.exe)中獲得當(dāng)前的UTC系統(tǒng)時間;

啟動測試進程,將前面獲得的進程創(chuàng)建時間作為參數(shù)傳遞給它;

在分支進程中,獲得main函數(shù)開始執(zhí)行時的當(dāng)前系統(tǒng)UTC時間;

在同一進程中,計算并調(diào)整時間差;

執(zhí)行到退出代碼時返回時間差;

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

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

影響性能的因素

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

C++性能測試代碼

C++測試代碼是直接由調(diào)用者進程調(diào)用的,當(dāng)它獲得一個命令行參數(shù)時,它會將其轉(zhuǎn)換成__int64來表示FILETIME,其值是從1601/1/1到現(xiàn)在的100 毫微秒間隔數(shù),因此我們可以獲得時間差,以毫秒數(shù)返回,用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;
  27. }

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

 
 
 
 
  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.             // 關(guān)閉進程和線程處理 
  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.         // 關(guān)閉進程和線程處理 
  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();
  125. }

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

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

#p#

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

在調(diào)用的.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;
  21. }

使用Mono

要使用Mono必須先從這里下載并安裝好Mono,然后修改環(huán)境變量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項目,如果你只需運行二進制文件,需要下載和安裝對應(yīng)的運行時,生成(Build)時需要Visual Studio 2003和Visual Studio 2010,或如果你喜歡使用命令生成,還需要特定的SDK。為了強制加載目標(biāo)運行時版本,我為所有.NET執(zhí)行文件創(chuàng)建了配置文件,內(nèi)容如下,不同的地方就是版本號:

 
 
 
 
  1.  

Java性能測試代碼

首先要從這里下載并安裝Java SDK,同樣也需要向PATH環(huán)境變量添加Java路徑,在開始生成前,還需要設(shè)置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缺乏測量持續(xù)時間的解決方案,我不得不使用毫秒,其它框架可以提供更細(xì)粒度的時間單位,但毫秒在這次的測試中已經(jīng)夠用了。

獲取內(nèi)存使用情況和處理器時間

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

 
 
 
 
  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;
  23. }

最小工作集是調(diào)用的進程占用的內(nèi)存由EmptyWorkingSet API收縮后,我計算出的一個值。

測試結(jié)果

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

運行時 冷啟動時間(ms) 冷啟動CPU時間(ms) 熱啟動時間(ms) 熱啟動CPU時間(ms) 專用字節(jié)(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時間要低,你可能認(rèn)為這違背了基本的物理定律,但需要注意這里的CPU時間指的是進程的整個生命周期,而啟動時間僅僅指進入到main函數(shù)時的時間,通過這我們知道可以通過一些優(yōu)化提高這些框架的啟動速度,正如你前面看到的,C++由于沒有框架,因此優(yōu)勢很明顯,調(diào)用者進程通過預(yù)加載一些通用dll使啟動更快。

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

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

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

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

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

運行時 冷啟動時間(ms) 冷啟動CPU時間(ms) 熱啟動時間(ms) 熱啟動CPU時間(ms) 專用字節(jié)(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操作,從測試結(jié)果來看,它比加載框架所用的時間更多。

運行測試

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

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

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

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

小結(jié)

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

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

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


當(dāng)前文章:.NET、Mono與Java、C++性能測試大PK
分享路徑:http://www.5511xx.com/article/coehoej.html