簡體   English   中英

Python Protobuf 中高效的消息字段設置

[英]Efficient message field setting in Python Protobuf

我在我正在處理的 Python 項目中使用 Protobuf (v3.5.1)。 我的情況可以簡化為:

// Proto file

syntax = "proto3";

message Foo {
    Bar bar = 1;
}

message Bar {
    bytes lotta_bytes_here = 1;
}

# Python excerpt
def MakeFooUsingBar(bar):
    foo = Foo()
    foo.bar.CopyFrom(bar)

我擔心.CopyFrom()的內存性能(如果我是對的,它是在復制內容,而不是引用)。 現在,在 C++ 中,我可以使用類似的東西:

Foo foo;
Bar* bar = new Bar();
bar->set_lotta_bytes_here("abcd");
foo.set_allocated_bar(bar);

從生成的源來看,它看起來不需要復制任何東西:

inline void Foo::set_allocated_bar(::Bar* bar) {
  ::google::protobuf::Arena* message_arena = GetArenaNoVirtual();
  if (message_arena == NULL) {
    delete bar_;
  }
  if (bar) {
    ::google::protobuf::Arena* submessage_arena = NULL;
    if (message_arena != submessage_arena) {
      bar = ::google::protobuf::internal::GetOwnedMessage(
          message_arena, bar, submessage_arena);
    }

  } else {

  }
  bar_ = bar;
  // @@protoc_insertion_point(field_set_allocated:Foo.bar)
}

Python中有類似的東西嗎? 我查看了 Python 生成的源代碼,但沒有發現任何適用的內容。

當涉及到大stringbytes對象時,Protobuf 似乎很好地描述了這種情況。 下面的過程,這意味着在創建一個新的Bar對象時,二進制數組是通過引用復制的(Python bytes是不可變的,所以這是有道理的):

def test_copy_from_with_large_bytes_field(self):
    bar = Bar()
    bar.val = b'12345'
    foo = Foo()
    foo.bar.CopyFrom(bar)

    self.assertIsNot(bar, foo.bar)
    self.assertIs(bar.val, foo.bar.val)

這解決了我的大bytes對象問題。 但是,如果某人的問題在於嵌套或重復字段,這將無濟於事 - 這些字段是逐個字段復制的。 這確實是有道理的——如果一個人復制了一條消息,他們希望兩個人是獨立的。 如果不是,則對原始消息進行更改將修改復制的消息(反之亦然)。

如果在 Python protobuf 中有任何類似於 C++ 移動語義( https://github.com/google/protobuf/issues/2791 )或set_allocated_...() ,那就可以解決它,但是我不知道這樣一項功能。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM