1. 程式人生 > >Python到底有多慢? -- 比JAVA慢超10倍,比VC慢30倍!(附C#, C++, Delphi, Lazarus的效率對比)

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編譯質量並不差, 輸在記憶體管理器的效率上.