2011-08-08 49 views
14

我開始使用協議緩衝區庫,但注意到它使用了大量的內存。 pympler.asizeof表明我的一個物體大約有76k!基本上,它包含一些字符串,一些數字和一些枚舉,以及一​​些可選的列表。如果我寫的是與C結構相同的東西,我預計它會少於幾百字節,並且實際上ByteSize方法返回121(序列化字符串的大小)。谷歌協議緩衝區巨大python

是你期望從圖書館?我聽說它很慢,但這是無法使用的,使我更傾向於認爲我濫用了它。

編輯

這裏是我構造的示例。這是一個Pb文件類似,但比簡單的我一直在使用

package pb; 

message A { 
    required double a  = 1; 
} 

message B { 
    required double b  = 1; 
} 

message C { 
    required double c  = 1; 
    optional string s  = 2; 
} 

message D { 
    required string d  = 1; 
    optional string e  = 2; 
    required A a   = 3; 
    optional B b   = 4; 
    repeated C c   = 5; 
} 

在這裏,我使用它

>>> import pb_pb2 
>>> a = pb_pb2.D() 
>>> a.d = "a" 
>>> a.e = "e" 
>>> a.a.a = 1 
>>> a.b.b = 2 
>>> c = a.c.add() 
>>> c.c = 5 
>>> c.s = "s" 
>>> import pympler.asizeof 
>>> pympler.asizeof.asizeof(a) 
21440 
>>> a.ByteSize() 
42 

我的protobuf的2.2.0版本(這個有點老點)和python 2.6.4。

+1

一些演示代碼再生的行爲將是很好。 – phihag

+1

@ PHPhag這是類似的再現行爲。 –

回答

5

對象實例在Python中比在編譯語言中具有更大的內存佔用量。例如,下面的代碼,它創建非常簡單的模仿類的原顯示1440:

class A: 
    def __init__(self): 
    self.a = 0.0 

class B: 
    def __init__(self): 
    self.b = 0.0 

class C: 
    def __init__(self): 
    self.c = 0.0 
    self.s = "" 

class D: 
    def __init__(self): 
    self.d = "" 
    self.e = "" 
    self.e_isset = 1 
    self.a = A() 
    self.b = B() 
    self.b_isset = 1 
    self.c = [C()] 

d = D() 
print asizeof(d) 

我並不感到驚訝,protobuf的系統產生的類需要20倍以上的內存,爲他們增添了不少鍋爐板。

C++版本肯定不會受此影響。

+0

我並不期待它很小,但正如你在這個例子中看到的,一個非常基本的對象是20k!這比持有必要信息所需的規模增加了500倍。 10的因子也許可以,但是500意味着你不能在內存中保存這些對象的數量(相對)很少。根據合同,pympler建議int的大小是24,這可能是從C++到Python的6倍增長。 –

+1

如果這很重要,您可以嘗試通過使用'__slots__'類屬性來減小大小。 –

+0

我不知道爲什麼'pb_pb2.D'需要存儲實際的Python對象的任何根本原因。如果沒有,這個邏輯不一定會成立。如果它不需要,它聽起來好像寫得不好。 –