Python中的Google协议缓冲区问题

14 投票
2 回答
4320 浏览
提问于 2025-04-16 23:09

我开始使用协议缓冲库,但发现它占用了大量内存。使用pympler.asizeof工具查看后,我发现我的一个对象大约有76k!基本上,它包含了一些字符串、数字,还有一些枚举类型,以及一些可选的相同类型的列表。如果我用C语言写一个结构体,我预计它的大小应该在几百字节以内,实际上ByteSize方法返回的大小是121(序列化字符串的大小)。

这是不是你对这个库的预期?我听说它速度慢,但现在这样根本无法使用,这让我更倾向于相信我可能在错误使用它。

编辑

这是我构造的一个例子。这是一个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

我使用的是版本2.2.0的protobuf(现在有点旧了),还有python 2.6.4。

2 个回答

0

编辑:这可能不是你实际遇到的问题,但我们最近发现一个45MB的protobuf消息在解码时占用了超过4GB的内存。看起来是这个问题:https://github.com/google/protobuf/issues/156

这个问题在protobuf 2.6版本时就已经被发现,而修复的代码直到今年3月7日才合并到主分支上:https://github.com/google/protobuf/commit/f6d8c833845b90f61b95234cd090ec6e70058d06

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++版本肯定不会有这个问题。

撰写回答