Neden [] liste daha hızlı()?
Geçenlerde []
list()
işlem hızları karşılaştırıldığında ve []
çalışan keşfetmek için sürpriz olduüç kat daha hızlıdaha list()
. Araştırdım aynı testi {}
dict()
ve sonuçlar hemen hemen aynı: []
{}
hem götürmüştü 0.128 / sn milyon döngüleri, while list()
dict()
aldı kabaca 0.428 sn / milyon devir.
Neden bu? []
{}
(muhtemelen ()
''
de) hemen söylemek için bir kopya boş stok değişmez iken onların açıkça adlı muadilleri (list()
, dict()
, tuple()
, str()
) tam gitmek hakkında oluşturarak bir nesne olsun veya olmasın, onlar aslında unsurlar?
Bu iki yöntem farklı nasıl bilmiyorum ama öğrenmek isterim.
BÖYLECE docs
veya bir cevap bulamadım, ve boş parantez için arama beklediğimden daha karmaşık olduğu ortaya çıktı.
timeit.timeit("[]")
timeit.timeit("list()")
timeit.timeit("{}")
listeler ve sözlükleri karşılaştırmak timeit.timeit("dict()")
, sırasıyla çağırarak zamanlama sonuçlarımı aldım. Python 2.7.9 koşuyorum.
GÜNCELLEME:if 1
if True
performansını karşılaştırır ve edebi-versus-global benzer bir senaryo üzerinde değecek gibi o I recently discovered this post; belki de dikkate değer.
CEVAP
[]
{}
çünküdeğişmez sözdizimi. Sadece Python veya sözlük nesnelerin listesini oluşturmak için bayt kodu oluşturmak
>>> import dis
>>> dis.dis(compile('[]', '', 'eval'))
1 0 BUILD_LIST 0
3 RETURN_VALUE
>>> dis.dis(compile('{}', '', 'eval'))
1 0 BUILD_MAP 0
3 RETURN_VALUE
list()
dict()
ayrı nesneleridir. İsimlerini çözülmesi gereken bir yığın işin içinde bağımsız baskı yapar, çerçeve daha sonra almak için saklı olmalı, ve bir çağrı yapılmalıdır. Bu daha fazla zaman alır.
İçin boş durumda, bunun anlamı var en azından bir LOAD_NAME
(olan arama yoluyla genel ad olarak __builtin__
module), ardından CALL_FUNCTION
belirli korumak için geçerli çerçeve:
>>> dis.dis(compile('list()', '', 'eval'))
1 0 LOAD_NAME 0 (list)
3 CALL_FUNCTION 0
6 RETURN_VALUE
>>> dis.dis(compile('dict()', '', 'eval'))
1 0 LOAD_NAME 0 (dict)
3 CALL_FUNCTION 0
6 RETURN_VALUE
Adı arama ayrı ayrı timeit
zaman:
>>> import timeit
>>> timeit.timeit('list', number=10**7)
0.30749011039733887
>>> timeit.timeit('dict', number=10**7)
0.4215109348297119
Zaman tutarsızlık var muhtemelen sözlük karma bir çarpışma. Bu nesneler arama için bu kez bu kez çıkarma ve harfleri kullanarak kez karşı karşılaştırır:
>>> timeit.timeit('[]', number=10**7)
0.30478692054748535
>>> timeit.timeit('{}', number=10**7)
0.31482696533203125
>>> timeit.timeit('list()', number=10**7)
0.9991960525512695
>>> timeit.timeit('dict()', number=10**7)
1.0200958251953125
Yani nesne aramak zorunda 10 milyon çağrı başına 1.00 - 0.31 - 0.30 == 0.39
ek bir saniye sürer.
Yerliler (timeit
bir kur, bir adı bağlama yerel olduğu her şeyi kullanarak): global isim aliasing tarafından genel arama maliyet önleyebilirsiniz
>>> timeit.timeit('_list', '_list = list', number=10**7)
0.1866450309753418
>>> timeit.timeit('_dict', '_dict = dict', number=10**7)
0.19016098976135254
>>> timeit.timeit('_list()', '_list = list', number=10**7)
0.841480016708374
>>> timeit.timeit('_dict()', '_dict = dict', number=10**7)
0.7233691215515137
ama asla CALL_FUNCTION
maliyet üstesinden gelebilir.
Neden bir Liste içinde dolaşmak üzerin...
Neden sıralanmamış bir dizi daha hızlı...
Neden Python kodunu daha hızlı bir işl...
Neden't varsa PyPy 6.3 kat daha h...
Neden bitişik in Java daha hızlı geçiş...