Python到底有多慢? -- 比JAVA慢超10倍,比VC慢30倍!(附C#, C++, Delphi, Lazarus的效率對比)
誰都知道Python最大的缺點就是效能差,到底多差網上沒有具體資料,今天自己做了一個測試 。
首先要宣告一下, 這個簡單測試只是通過對陣列的建立、統計的耗時比較, 本以為陣列操作是python的強項,應該差別不大,但結果讓人大跌眼鏡:建立陣列Python耗時是java的 14倍多, 統計耗時Python是java的24倍多。
硬體環境:
Win8.1 64位、i5 4670K 超到4.2GHZ,記憶體8G
軟體:
python 3.4, JDK 1.6
Phton的:
import time c_rows=10000 c_cols=10000 lvStart=time.time() #print(lvStart) # 建立 [10000][10000]的整數陣列 lvArr=[[] for row in range(1,c_rows+1,1)] lvRows=len(lvArr) for row in range(0,lvRows,1): lvArr[row]=[col for col in range(1,c_cols+1,1)] lvEnd=time.time() print("Create lvArray Use:%f" %((lvEnd-lvStart)*1000)) lvStart=time.time() lvSum=sum(list(map(sum,lvArr))) lvEnd=time.time() print("lvArray summary is :%d" %(lvSum)) print("Calculate lvArray Use:%f" %((lvEnd-lvStart)*1000))
結果:
Create lvArray Use:3654.559135
lvArray summary is :500050000000
Calculate lvArray Use:962.199926
[Finished in 6.3s]
========
JAVA的:
public class Test { public static void main(String[] args) { long lvStart = System.currentTimeMillis(); int[][] lvArr = new int[10000][10000]; for (int row = 0; row < lvArr.length; row++) { for (int col = 0; col < lvArr[row].length; col++) { lvArr[row][col] = col + 1; } } long lvEnd = System.currentTimeMillis(); System.out.println(String.format("Create lvArray Use:%d", lvEnd - lvStart)); lvStart = System.currentTimeMillis(); long lvSum = 0; for (int row = 0; row < lvArr.length; row++) { for (int col = 0; col < lvArr[row].length; col++) { lvSum += lvArr[row][col]; } } lvEnd = System.currentTimeMillis(); System.out.println(String.format("lvArray summary is :%d", lvSum)); System.out.println(String.format("Calculate lvArray Use:%d", lvEnd-lvStart)); } }
結果:
Create lvArray Use:257
lvArray summary is :500050000000
Calculate lvArray Use:39
原本以為Python會在列表、陣列方法的運算用到平行計算,但沒有,感覺很可惜。
C/Delphi這些硬傢伙就不對比了,絕對秒得沒影。
--------------
再來一段C#的效率:
public static void test() { const int arr_length = 10000; long lvStart = Environment.TickCount; //Debug.WriteLine(String.Format("Create lvArray Use:{0}", Environment.TickCount - lvStart)); int[][] lvArr = new int[arr_length][]; for (int row = 0; row < arr_length ; row++) { lvArr[row] = new int[arr_length]; for (int col = 0; col < arr_length ; col++) { lvArr[row][col] = col + 1; } } long lvEnd = Environment.TickCount; Debug.WriteLine(String.Format("Create lvArray Use:{0}", lvEnd - lvStart)); lvStart = Environment.TickCount; long lvSum = 0; for (int row = 0; row < arr_length; row++) { for (int col = 0; col < arr_length; col++) { lvSum += lvArr[row][col]; } } lvEnd = Environment.TickCount; Debug.WriteLine(String.Format("lvArray summary is :{0}", lvSum)); Debug.WriteLine(String.Format("Calculate lvArray Use:{0}", lvEnd - lvStart)); }
輸出 :
Create lvArray Use:343
lvArray summary is :500050000000
Calculate lvArray Use:172
----------
VC (vs2017編譯器), 相同的程式碼在2015上編譯要慢很多
const int arr_length = 10000;
void test(){
CString lvOutStr;
long lv1;
long lvStart = GetTickCount64();
lv1 = lvStart;
//Debug.WriteLine(String.Format("Create lvArray Use:{0}", Environment.TickCount - lvStart));
int* lvArr[arr_length];
for (int row = 0; row < arr_length; row++) {
lvArr[row] = new int[arr_length];
for (int col = 0; col < arr_length; col++) {
*(lvArr[row] + col) = col + 1;
}
}
long lvEnd = GetTickCount64();
lvOutStr.Format(_T("Create lvArray Use:%d\n"), lvEnd - lvStart);
OutputDebugString(lvOutStr);
lvStart = GetTickCount64();
INT64 lvSum = 0;
for (int row = 0; row < arr_length; row++)
{
for (int col = 0; col < arr_length; col++)
{
lvSum += *(lvArr[row] + col);
}
}
for (int row = 0; row < arr_length; row++) {
delete[] lvArr[row];
}
lvEnd = GetTickCount64();
lvOutStr.Format(_T("lvArray summary is :%lld\n"), lvSum);
OutputDebugString(lvOutStr);
lvOutStr.Format(_T("Calculate lvArray Use:%d\n"), lvEnd - lvStart);
OutputDebugString(lvOutStr);
}
輸出 :
Create lvArray Use:94
lvArray summary is :500050000000
Calculate lvArray Use:62
codetyphon(lazarus, gcc 64編譯器)
type
TarrInt = array of pinteger;
procedure TForm1.Button1Click(Sender: TObject);
var
lvStart, lvEnd: LongWord;
lvArr: TArrInt;
lvSize: integer;
col, row: integer;
lvSum: UInt64;
lvVal:PInteger;
lvOut:string;
begin
lvSize := 10000;
{getmem(lvOut,1);
fillchar(lvOut^,0,1);}
lvOut:='';
lvStart := GetTickCount;
setLength(lvArr, lvSize);
for row := 0 to lvSize - 1 do
begin
getmem(lvArr[row], sizeof(integer) * lvSize);
lvVal:=lvArr[row] ;
for col := 0 to lvSize - 1 do
begin
//lvVal:=integer(lvVal)+1;
lvVal^ := col + 1;
Inc(lvVal);
end;
end;
lvEnd := GetTickCount();
//lvOut.add(Format('Create lvArray Use:%d', [lvEnd - lvStart]));
lvOut:=lvOut+Format('Create lvArray Use:%d'#13#10, [lvEnd - lvStart]);
lvStart := GetTickCount;
lvSum := 0;
for row := 0 to lvSize - 1 do
begin
lvVal:=lvArr[row] ;
for col := 0 to lvSize - 1 do
begin
lvSum := lvSum + lvVal^;
Inc(lvVal);
end;
end;
for row := 0 to lvSize - 1 do
begin
freemem(lvArr[row],sizeof(integer) * lvSize);
end;
lvEnd := GetTickCount();
//lvOut.add(Format('lvArray summary is :%d', [lvSum]));
lvOut:=lvOut+Format('lvArray summary is :%d'#13#10, [lvSum]);
lvOut:=lvOut+Format('Calculate lvArray Use:%d'#13#10, [lvEnd - lvStart]);
memo1.Text:=lvOut;
//StrDispose(lvOut);
//memo1.Lines.Text := lvOut.Text;
end;
輸出:
Create lvArray Use:125
lvArray summary is :500050000000
Calculate lvArray Use:79
Delphi EX10.2(64位編譯器),
type
TarrInt = array of pinteger;
procedure TForm1.Button1Click(Sender: TObject);
var
lvStart, lvEnd: cardinal;
lvArr: TArrInt;
lvSize: integer;
col, row: integer;
lvSum: UInt64;
lvVal:PInteger;
lvOut:pchar;
begin
lvSize := 10000;
{getmem(lvOut,1);
fillchar(lvOut^,0,1);}
lvOut:=strnew('');
lvStart := GetTickCount;
setLength(lvArr, lvSize);
for row := 0 to lvSize - 1 do
begin
getmem(lvArr[row], sizeof(integer) * lvSize);
lvVal:=lvArr[row] ;
for col := 0 to lvSize - 1 do
begin
//lvVal:=integer(lvVal)+1;
lvVal^ := col + 1;
Inc(lvVal);
end;
end;
lvEnd := GetTickCount();
//lvOut.add(Format('Create lvArray Use:%d', [lvEnd - lvStart]));
StrCat(lvOut,pchar(Format('Create lvArray Use:%d'#13#10, [lvEnd - lvStart])));
lvStart := GetTickCount;
lvSum := 0;
for row := 0 to lvSize - 1 do
begin
lvVal:=lvArr[row] ;
for col := 0 to lvSize - 1 do
begin
lvSum := lvSum + lvVal^;
Inc(lvVal);
end;
end;
for row := 0 to lvSize - 1 do
begin
freemem(lvArr[row]);
end;
lvEnd := GetTickCount();
//lvOut.add(Format('lvArray summary is :%d', [lvSum]));
strcat(lvOut,pchar(Format('lvArray summary is :%d'#13#10, [lvSum])));
strcat(lvOut,pchar(Format('Calculate lvArray Use:%d'#13#10, [lvEnd - lvStart])));
memo1.Text:=strpas(lvOut);
StrDispose(lvOut);
//memo1.Lines.Text := lvOut.Text;
end;
輸出 :
Create lvArray Use:104
lvArray summary is :500050000000
Calculate lvArray Use:63
幾種編譯器對10000X10000的陣列進行記憶體分配/初始化及運算, 所有測試都在預設引數下編譯/執行, release模式, 結果對比如下:
編譯器 | 效能(單位ms) |
VC(64位) | 156 |
Delphi EX Tokyo(64位) | 167 |
Delphi XE7(64位) | 172 |
CodeTyphon/Lazarus(gcc編譯器,64位) | 203 |
JAVA(64位) | 296 |
C#(vs2017,64位) | 512 |
Delphi 7(32位) | 532 |
python | 4617 |
Delphi7編譯質量並不差, 輸在記憶體管理器的效率上.