SORU
26 AĞUSTOS 2009, ÇARŞAMBA


Sözlük vs ve neden?daha verimli olan Nesne

Ne bellek kullanımı ve CPU tüketimi açısından Python ile daha verimli bir Sözlüğü ya da Nesne?

Arka plan: Python içine veri büyük miktarda yük var. Alan bir konteyner için sadece bir nesne oluşturdum. 4M örnekleri oluşturma ve bir sözlük içine koyarak 10 dakika ve bellek ~6 GB aldı. Sözlük hazır olduktan sonra, erişim, göz açıp kapayıncaya kadar.

Örnek: Performansını kontrol etmek için aynı şeyi iki basit programlar yazdım - bir nesne, diğer sözlük kullanıyor:

Nesne (~18sec yürütme süresi):

class Obj(object):
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

Sözlük (~12sec zaman yürütme):

all = {}
for i in range(1000000):
  o = {}
  o['i'] = i
  o['l'] = []
  all[i] = o

Soru: Yanlış bir şey yapıyor veya sözlük sadece daha hızlı nesne daha olur muyum? Eğer gerçekten sözlük daha iyi yapar, birisi açıklayabilir mi?

CEVAP
26 AĞUSTOS 2009, ÇARŞAMBA


__slots__ kullanarak denediniz mi?

Belgeleri http://docs.python.org/reference/datamodel.html#slots:

"Varsayılan olarak, eski ve yeni tarzı hem sınıfları öznitelik depolama için bir sözlük var. Bu nesneler çok az örnek değişkenleri olması için alan kaybına yol açar. Uzay tüketimi örnekleri çok sayıda oluştururken akut hale gelebilir.

Varsayılan yeni tarzı bir sınıf tanımı __slots__ tanımlayarak kılınabilir. __slots__ bildirimi her örneği örnek değişkenler ve saklı bir dizi sadece yeterli alan her değişken için bir değer alır. Alanı __dict__ her örnek için oluşturulmadı çünkü kaydedilir."

Bu sefer hafıza olarak kayıt ediyor mu?

Bilgisayarımda üç yaklaşımlarının karşılaştırılması:

test_slots.py:

class Obj(object):
  __slots__ = ('i', 'l')
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

test_obj.py:

class Obj(object):
  def __init__(self, i):
    self.i = i
    self.l = []
all = {}
for i in range(1000000):
  all[i] = Obj(i)

test_dict.py:

all = {}
for i in range(1000000):
  o = {}
  o['i'] = i
  o['l'] = []
  all[i] = o

test_namedtuple.py (2.6) destekledi:

import collections

Obj = collections.namedtuple('Obj', 'i l')

all = {}
for i in range(1000000):
  all[i] = Obj(i, [])

Çalıştırmak kriter (CPython 2.5 kullanarak):

$ lshw | grep product | head -n 1
          product: Intel(R) Pentium(R) M processor 1.60GHz
$ python --version
Python 2.5
$ time python test_obj.py && time python test_dict.py && time python test_slots.py 

real    0m27.398s (using 'normal' object)
real    0m16.747s (using __dict__)
real    0m11.777s (using __slots__)

CPython adlı dizi test de dahil olmak üzere 2.6.2 kullanma:

$ python --version
Python 2.6.2
$ time python test_obj.py && time python test_dict.py && time python test_slots.py && time python test_namedtuple.py 

real    0m27.197s (using 'normal' object)
real    0m17.657s (using __dict__)
real    0m12.249s (using __slots__)
real    0m12.262s (using namedtuple)

Yani Evet pek sürpriz), __slots__ kullanarak hızlı başlamanıza yardımcı olur. Adlı bir başlık kullanarak __slots__ benzer performansa sahiptir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Gali B

    Gali B

    1 EYLÜL 2006
  • max2sims2

    max2sims2

    19 Kasım 2008
  • William Sledd

    William Sled

    24 EYLÜL 2006