2013-06-05 31 views
10

Tôi đã chỉ rối tung xung quanh khi tôi đi qua quirk này. Và tôi muốn chắc chắn rằng tôi không điên.Có phải "tham gia" chậm hơn trong phiên bản 3.x không?

Các mã sau (chỉ hoạt động trong 2.x và 3.x):

from timeit import timeit 
print ('gen: %s' % timeit('"-".join(str(n) for n in range(1000))', number=10000)) 
print ('list: %s' % timeit('"-".join([str(n) for n in range(1000)])', number=10000)) 

Làm 3 chạy trên mỗi phiên bản, cùng một máy.

lưu ý: Tôi đã nhóm thời gian trên cùng một dòng để tiết kiệm không gian tại đây.

Mở Python 2.7.5:

gen: 2.37875941643, 2.44095773486, 2.41718937347 
list: 2.1132466183, 2.12248106441, 2.11737128131 

Mở Python 3.3.2:

gen: 3.8801268438439718, 3.9939604983350185, 4.166233972077624 
list: 2.976764740845537, 3.0062614747229555, 3.0734980312273894 

Tôi tự hỏi tại sao điều này là .... nó có thể có một cái gì đó để làm với cách dây được thực hiện?


EDIT: tôi đã làm nó một lần nữa mà không sử dụng range() vì đó cũng đã thay đổi chút ít so với 2.x để 3.x Thay vào đó tôi sử dụng mã mới dưới đây:

from timeit import timeit 
print ('gen: %s' % timeit('"-".join(str(n) for n in (1, 2, 3))', number=1000000)) 
print ('list: %s' % timeit('"-".join([str(n) for n in (1, 2, 3)])', number=1000000)) 

thời gian cho Python 2.7.5:

gen: 2.13911803683, 2.16418448199, 2.13403650485 
list: 0.797961223325, 0.767758578433, 0.803272800119 

thời gian cho Python 3.3.2:

gen: 2.8188347625218486, 2.882846655874985, 3.0317612259663718 
list: 1.3590610502957934, 1.4878876089869366, 1.4978070529462615 

EDIT2: Có vẻ như đã có một số điều hơn ném ra khỏi tính toán, vì vậy tôi đã cố gắng đưa nó xuống đến một trần tối thiểu.

Mã mới:

from timeit import timeit 
print ('gen: %s' % timeit('"".join(n for n in ("1", "2", "3"))', number=1000000)) 
print ('list: %s' % timeit('"".join([n for n in ("1", "2", "3")])', number=1000000)) 

Timing Python 2.7.5:

gen: 1.47699698704, 1.46120314534, 1.48290697384 
list: 0.323474182882, 0.301259632897, 0.323756694047 

Timing Python 3.3.2:

gen: 1.633002954259608, 1.6049987598860562, 1.6109927662465935 
list: 0.5621341113519589, 0.5789849850819431, 0.5619928557696119 

Sự khác biệt là rõ ràng, đó là nhanh hơn trong 2.x và chậm hơn trong 3.x Và tôi tò mò là tại sao ...

+2

Trong Python 3, ' dải ô' hoạt động giống như 'xrange' trước đây. Python 2 có thể lưu vào bộ nhớ đệm danh sách được tạo rõ ràng, cung cấp tốc độ quan sát được. (Điều này cũng sẽ giải thích tại sao phiên bản danh sách nhanh hơn phiên bản máy phát điện trong cả 2 và 3.) – chepner

+2

http://docs.python.org/3.0/whatsnew/3.0.html#performance –

+0

@chepner Bạn có một điểm . Tôi đã thử lại bằng cách sử dụng '" x "* 1000' thay vì các hàm phạm vi. Và vẫn còn 2.x là nhanh hơn. –

Trả lời

7

tôi đã không làm việc trên python3.3 được nêu ra. Tất cả những điều tôi đã nêu dưới đây được dựa trên sự quan sát.

Tôi đã sử dụng trình tách rời python cho mã sau trong python 3.3 và python 2.7.3.

s = """ 
''.join([n for n in ('1', '2', '3')]) 
""" 

Tôi nhận thấy có những thay đổi về mã upcodes.

Python 2.7.3

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 
32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dis 
>>> from timeit import timeit 
>>> s = """ 
... ''.join([n for n in ('1', '2', '3')]) 
... """ 
>>> timeit(s, number=100000) 
0.08443676085287867 
>>> 
>>> 
>>> c = compile(s, '<string>', 'exec') 
>>> dis.dis(c) 
    2   0 LOAD_CONST    0 ('') 
       3 LOAD_ATTR    0 (join) 
       6 BUILD_LIST    0 
       9 LOAD_CONST    5 (('1', '2', '3')) 
      12 GET_ITER 
     >> 13 FOR_ITER    12 (to 28) 
      16 STORE_NAME    1 (n) 
      19 LOAD_NAME    1 (n) 
      22 LIST_APPEND    2 
      25 JUMP_ABSOLUTE   13 
     >> 28 CALL_FUNCTION   1 
      31 POP_TOP 
      32 LOAD_CONST    4 (None) 
      35 RETURN_VALUE 
>>> 

python 3,3

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (In 
tel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import dis 
>>> from timeit import timeit 
>>> s = """ 
... ''.join([n for n in ('1', '2', '3')]) 
... """ 
>>> timeit(s, number=100000) 
0.13603410021487614 
>>> 
>>> 
>>> c = compile(s, '<string>', 'exec') 
>>> dis.dis(c) 
    2   0 LOAD_CONST    0 ('') 
       3 LOAD_ATTR    0 (join) 
       6 LOAD_CONST    1 (<code object <listcomp> at 0x01F70BB 
0, file "<string>", line 2>) 
       9 LOAD_CONST    2 ('<listcomp>') 
      12 MAKE_FUNCTION   0 
      15 LOAD_CONST    7 (('1', '2', '3')) 
      18 GET_ITER 
      19 CALL_FUNCTION   1 (1 positional, 0 keyword pair) 
      22 CALL_FUNCTION   1 (1 positional, 0 keyword pair) 
      25 POP_TOP 
      26 LOAD_CONST    6 (None) 
      29 RETURN_VALUE 
>>> 

Từ upcodes tôi rằng đó là danh sách hiểu rằng đã thay đổi vì vậy tôi kiểm tra danh sách hiểu biết trong cả hai phiên bản

Python 2.7.3

Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 
32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> 
>>> 
>>> 
>>> import dis 
>>> from timeit import timeit 
>>> s = """ 
... [i for i in ('1', '2', '3')] 
... """ 
>>> timeit(s, number=100000) 
0.059500395456104374 
>>> c = compile(s, '<string>', 'exec') 
>>> dis.dis(c) 
    2   0 BUILD_LIST    0 
       3 LOAD_CONST    4 (('1', '2', '3')) 
       6 GET_ITER 
     >> 7 FOR_ITER    12 (to 22) 
      10 STORE_NAME    0 (i) 
      13 LOAD_NAME    0 (i) 
      16 LIST_APPEND    2 
      19 JUMP_ABSOLUTE   7 
     >> 22 POP_TOP 
      23 LOAD_CONST    3 (None) 
      26 RETURN_VALUE 
>>> 

python 3,3

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:55:48) [MSC v.1600 32 bit (In 
tel)] on win32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> 
>>> 
>>> 
>>> import dis 
>>> from timeit import timeit 
>>> s = """ 
... [i for i in ('1', '2', '3')] 
... """ 
>>> timeit(s, number=100000) 
0.09876976988887567 
>>> c = compile(s, '<string>', 'exec') 
>>> dis.dis(c) 
    2   0 LOAD_CONST    0 (<code object <listcomp> at 0x01FF0BB 
0, file "<string>", line 2>) 
       3 LOAD_CONST    1 ('<listcomp>') 
       6 MAKE_FUNCTION   0 
       9 LOAD_CONST    6 (('1', '2', '3')) 
      12 GET_ITER 
      13 CALL_FUNCTION   1 (1 positional, 0 keyword pair) 
      16 POP_TOP 
      17 LOAD_CONST    5 (None) 
      20 RETURN_VALUE 
>>> 

Tôi chưa từng làm việc với python3 hoặc kiểm tra các thay đổi. Dường như việc triển khai danh sách hiểu đã được thay đổi. Trong python3.3 có MAKE_FUNCTION và CALL_FUNCTION. (Bây giờ trong python2.7 gọi đến một chức năng là tốn kém. Tôi không chắc liệu trong python3.3 gọi đến chức năng vẫn còn tốn kém hay không. Nếu đó là trường hợp sau đó có thể thêm một số thời gian.)

1

Bạn không so sánh táo với táo.

Trong Python 2, str là những gì được gọi là bytes trong Python 3 (gần như).

Trong Python 3, str là những gì được gọi là unicode bằng Python 2.

+0

Vì vậy, có thể lược tả 2.x 'str' thành 3.x' bytes' và 2.x 'unicode' thành 3.x' str' có thể thú vị. Nó sẽ có khả năng thú vị nếu hai người đó cho thấy những thay đổi hiệu suất khác nhau. – pcurry

Các vấn đề liên quan