SORU
13 Mayıs 2015, ÇARŞAMBA


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
13 Mayıs 2015, ÇARŞAMBA


[] {} çü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.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Exalto_Gamer

    Exalto_Gamer

    15 EKİM 2014
  • nigahiga

    nigahiga

    21 Temmuz 2006
  • Wii Minute Radio

    Wii Minute R

    31 Mayıs 2008