2011-08-08 42 views
14

Tôi bắt đầu sử dụng thư viện bộ đệm giao thức, nhưng nhận thấy rằng nó đang sử dụng lượng bộ nhớ khổng lồ. pympler.asizeof chỉ ra rằng một đối tượng duy nhất của tôi là khoảng 76k! Về cơ bản, nó chứa một vài chuỗi, một số số, và một số enums, và một số danh sách tùy chọn giống nhau. Nếu tôi viết cùng một thứ như C-struct, tôi mong đợi nó dưới một vài trăm byte, và thực sự phương thức ByteSize trả về 121 (kích thước của chuỗi được tuần tự hóa).Bộ đệm giao thức của Google rất lớn trong python

Đó có phải là bạn mong đợi từ thư viện không? Tôi đã nghe nó rất chậm, nhưng điều này không thể sử dụng được và khiến tôi có xu hướng tin rằng tôi đang lạm dụng nó.

Sửa

Dưới đây là một ví dụ tôi xây dựng. Đây là một tập tin pb tương tự, nhưng đơn giản hơn những gì tôi đã sử dụng

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; 
} 

Và ở đây tôi đang sử dụng nó

>>> 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 

Tôi có phiên bản 2.2.0 của protobuf (một chút cũ tại đây điểm), và trăn 2.6.4.

+1

Một số code demo tái tạo hành vi sẽ được tốt đẹp. – phihag

+1

@phihag Đây là một cái gì đó tương tự như tái tạo hành vi. –

Trả lời

5

Các cá thể đối tượng có dấu chân bộ nhớ lớn hơn trong python so với các ngôn ngữ được biên dịch. Ví dụ, đoạn mã sau, mà tạo ra các lớp học rất đơn giản bắt chước màn proto của bạn 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) 

tôi không ngạc nhiên rằng protobuf là tạo các lớp học mất nhiều bộ nhớ hơn 20 lần, vì chúng thêm rất nhiều tấm nồi hơi.

Phiên bản C++ chắc chắn không bị ảnh hưởng bởi điều này.

+0

Tôi đã không mong đợi nó được nhỏ, nhưng như bạn có thể thấy trong ví dụ này, một đối tượng thực sự cơ bản là 20k! Tăng gấp 500 lần kích thước cần thiết để giữ thông tin cần thiết. Một hệ số 10 có thể là ok, nhưng 500 có nghĩa là bạn không thể chứa nhiều hơn một (tương đối) số lượng nhỏ các đối tượng này trong bộ nhớ. Theo hợp đồng, pympler cho thấy kích thước của một int là 24, mà có lẽ là một sự gia tăng 6 lần kích thước đi từ C++ đến python. –

+1

nếu điều này quan trọng bạn có thể thử giảm kích thước bằng cách sử dụng thuộc tính lớp '__slots__'. –

+0

Tôi không biết bất kỳ lý do cơ bản nào tại sao 'pb_pb2.D' cần phải lưu trữ các đối tượng Python thực tế. Nếu không, logic này không cần thiết. Nếu nó không cần và không, nó có vẻ như nó có thể được viết kém. –

0

Chỉnh sửa: Đây không phải là vấn đề thực tế của bạn ở đây, nhưng chúng tôi vừa trải qua một tin nhắn protobuf 45MB lấy> ram 4GB khi giải mã. Nó dường như là điều này: https://github.com/google/protobuf/issues/156

được biết về trong protobuf 2.6 và cách khắc phục chỉ sáp nhập vào tháng ba bậc thầy 7 năm nay: https://github.com/google/protobuf/commit/f6d8c833845b90f61b95234cd090ec6e70058d06

+0

Hóa ra rò rỉ bộ nhớ không khắc phục được sự cố của chúng tôi. –

Các vấn đề liên quan