程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> C語言在2013年仍很重要

C語言在2013年仍很重要

編輯:C++入門知識

本文作者在開發Dynym項目,這是一個動態語言的通用運行時。在開發時,作者以其 他語言的運行速度作為基礎比較語言的運行速度,因此發現了一些小秘密。迭代計算斐波那契數列是測試各種語言執行速度的常見方法。作者以不同的語言進行測 試,最終發現C語言要比Python編寫的計算斐波那契數列快278.5倍。在底層開發,以及專注性能的應用程序中,選擇是顯而易見的。而為什麼會有如此 大的運行性能差距呢。作者進一步研究了程序的反匯編代碼,發現差別出在內存的訪問次數,以及預測的CPU指令的正確性方面。

原作者注:在本文最開始,我並沒說明進行模2^64的計算——我當然明白那些不是“正確的”斐波那契數列,其實我不是想分析大數,我只是想探尋編譯器產生的代碼和計算機體系結構而已。

最近,我一直在開發Dynvm——一個通用的動態語言運行時。就像其他任何好的語言運行時項目一樣,開發是由基准測試程 序驅動的。因此,我一直在用基准測試程序測試各種由不同語言編寫的算法,以此對其典型的運行速度有一個感覺上的認識。一個經典的測試就是迭代計算斐波那契 數列。為簡單起見,我以2^64為模,用兩種語言編寫實現了該算法。

用Python語言實現如下:

  1. SZ = 2**64 
  2. i = 0 
  3. a, b = 1, 0 
  4. while i < n: 
  5.     t = b 
  6.     b = (b+a) % SZ 
  7.     a = t 
  8.     i = i + 1 
  9. return b 

用C語言實現如下:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. typedef unsigned long ulong; 
  4.   
  5. int main(int argc, char *argv[]) 
  6.     ulong n = atoi(argv[1]); 
  7.     ulong a = 1; 
  8.     ulong b = 0; 
  9.     ulong t; 
  10.   
  11.     for(ulong i = 0; i < n; i++) { 
  12.         t = b; 
  13.         b = a+b; 
  14.         a = t; 
  15.     } 
  16.   
  17.     printf("%lu\n", b); 
  18.     return 0; 

用其他語言實現的代碼示例,我已放在github上。

Dynvm包含一個基准測試程序框架,該框架可以允許在不同語言之間對比運行速度。在一台Intel i7-3840QM調頻到1.2 GHz)機器上,當 n=1,000,000 時,對比結果如下:

  1. ======================================================= 
  2.   語言                               時間 (秒) 
  3. ======================================================= 
  4.   Java                               0.133 
  5.   C Language                         0.006 
  6.   CPython                            0.534 
  7.   Javascript V8                      0.284 

很明顯,C語言是這裡的老大,但是java的結果有點誤導性,因為大部分的時間是由JIT編譯器啟動~120ms)占用的。當n=100,000,000時,結果變得更明朗:

  1. ======================================================= 
  2.   語言                              時間秒) 
  3. ======================================================= 
  4.   Java                               0.300 
  5.   C Language                         0.172 
  6.   CPython                            47.909 
  7.   Javascript V8                      24.179 

在這裡,我們探究下為什麼C語言在2013年仍然很重要,以及為什麼編程世界不會完全“跳槽”到Python或者 V8/Node。有時你需要原始性能,但是動態語言仍在這方面艱難掙扎著,即使對以上很簡單的例子而言。我個人相信這種情況會克服掉,通過幾個項目我們能 在這方面看到很大的希望:JVM、V8、PyPy、LuaJIT等等,但在2013年我們還沒有到達“目的地”。

然而,我們無法回避這樣的問題:為什麼差距如此之大?在C語言和Python之間有278.5倍的性能差距!最不可思議的地方是,從語法角度講,以上例子中的C語言和Python內部循環基本上一模一樣。

為了找到問題的答案,我搬出了反匯編器,發現了以下現象:

  1. 0000000000400480 <main>: 
  2. 247   400480:       48 83 ec 08             sub    $0x8,%rsp 
  3. 248   400484:       48 8b 7e 08             mov    0x8(%rsi),%rdi 
  4. 249   400488:       ba 0a 00 00 00          mov    $0xa,%edx 
  5. 250   40048d:       31 f6                   xor    %esi,%esi 
  6. 251   40048f:       e8 cc ff ff ff          callq  400460 <strtol@plt> 
  7. 252   400494:       48 98                   cltq 
  8. 253   400496:       31 d2                   xor    %edx,%edx 
  9. 254   400498:       48 85 c0                test   %rax,%rax 
  10. 255   40049b:       74 26                   je     4004c3 <main+0x43> 
  11. 256   40049d:       31 c9                   xor    %ecx,%ecx 
  12. 257   40049f:       31 f6                   xor    %esi,%esi 
  13. 258   4004a1:       bf 01 00 00 00          mov    $0x1,%edi 
  14. 259   4004a6:       eb 0e                   jmp    4004b6 <main+0x36> 
  15. 260   4004a8:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1) 
  16. 261   4004af:       00 
  17. 262   4004b0:       48 89 f7                mov    %rsi,%rdi 
  18. 263   4004b3:       48 89 d6                mov    %rdx,%rsi 
  19. 264   4004b6:       48 83 c1 01             add    $0x1,%rcx 
  20. 265   4004ba:       48 8d 14 3e             lea    (%rsi,%rdi,1),%rdx 
  21. 266   4004be:       48 39 c8                cmp    %rcx,%rax 
  22. 267   4004c1:       77 ed                   ja     4004b0 <main+0x30> 
  23. 268   4004c3:       be ac 06 40 00          mov    $0x4006ac,%esi 
  24. 269   4004c8:       bf 01 00 00 00          mov    $0x1,%edi 
  25. 270   4004cd:       31 c0                   xor    %eax,%eax 
  26. 271   4004cf:       e8 9c ff ff ff          callq  400470 <__printf_chk@plt> 
  27. 272   4004d4:       31 c0                   xor    %eax,%eax 
  28. 273   4004d6:       48 83 c4 08             add    $0x8,%rsp 
  29. 274   4004da:       c3                      retq 
  30. 275   4004db:       90                      nop 
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved