2014-01-14 71 views
8

我在調查線程Why is reading lines from stdin much slower in C++ than Python?時發現了令人驚訝的python行爲。爲什麼網格python代碼比分解的更慢?

如果我從該線程

#!/usr/bin/env python 
from __future__ import print_function 
import time 
import sys 


count = 0 
start_time = time.time() 

for line in sys.stdin: 
    count += 1 

delta_sec = time.time() - start_time 
if delta_sec >= 0: 
    lines_per_sec = int(round(count/delta_sec)) 
    print("Read {0:n} lines in {1:.2f} seconds. LPS: {2:n}".format(count, delta_sec, lines_per_sec)) 

它與速度11.5M LPS運行簡單的Python代碼,當我分解整個腳本到單一功能

#!/usr/bin/env python 
from __future__ import print_function 
import time 
import sys 


def test(input): 
    count = 0 
    start_time = time.time() 

    for line in input: 
     count += 1 

    delta_sec = time.time() - start_time 
    if delta_sec >= 0: 
     lines_per_sec = int(round(count/delta_sec)) 
     print("Read {0:n} lines in {1:.2f} seconds. LPS: {2:n}".format(count, delta_sec, lines_per_sec)) 


if __name__ == "__main__": 
    test(sys.stdin) 

碼速度可達23M LPS。

爲什麼這個簡單的重構使我的代碼快2倍?

我在Ubuntu 13.10上運行了python2.7的測試。

+0

locals vs globals – SethMMorton

+1

嘗試'input = sys.stdin for line in input:...'在你的第一個腳本中 –

+0

這個方法不會加速第一個腳本 –

回答

4

看着字節碼幫助我回答這個問題。對於第一個腳本的工作部分 字節碼是:對於相應的第二腳本的一部分

10   58 SETUP_LOOP    27 (to 88) 
      61 LOAD_NAME    3 (sys) 
      64 LOAD_ATTR    6 (stdin) 
      67 GET_ITER   
     >> 68 FOR_ITER    16 (to 87) 
      71 STORE_NAME    7 (line) 
11   74 LOAD_NAME    4 (count) 
      77 LOAD_CONST    4 (1) 
      80 INPLACE_ADD  
      81 STORE_NAME    4 (count) 
      84 JUMP_ABSOLUTE   68 
     >> 87 POP_BLOCK 

和字節代碼:

12   18 SETUP_LOOP    24 (to 45) 
      21 LOAD_FAST    0 (input) 
      24 GET_ITER 
     >> 25 FOR_ITER    16 (to 44) 
      28 STORE_FAST    3 (line) 
13   31 LOAD_FAST    1 (count) 
      34 LOAD_CONST    2 (1) 
      37 INPLACE_ADD 
      38 STORE_FAST    1 (count) 
      41 JUMP_ABSOLUTE   25 
     >> 44 POP_BLOCK 

我看到這個代碼之間的實際差異是LOAD_NAME VS LOAD_FAST和STORE_NAME與STORE_FAST操作碼使用。 文檔http://docs.python.org/2.7/library/dis.html#opcode-LOAD_FAST說 LOAD_FAST僅使用索引進行查找,而LOAD_NAME則通過字符串名稱查找變量。 而第一種方法是兩倍快。

+0

有趣!你用什麼來反彙編字節碼? – JJC

+1

標準的python'dis'模塊幾乎可以反彙編:) –

相關問題