添加 6 条数组消息时出现 Protobuf 内存错误

Posted

技术标签:

【中文标题】添加 6 条数组消息时出现 Protobuf 内存错误【英文标题】:Protobuf memory error when adding 6 array messages 【发布时间】:2021-07-29 18:31:12 【问题描述】:

我收到此错误:Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 67112960 bytes) in C:\xampp\htdocs\... 当我在我的 proto 文件中添加 6 个数组消息时。我正在使用 php protobuf 协议缓冲区进行序列化。

syntax = "proto3";

message data 
    .data_step_one test = 2;


message data_step_one 
    .data_step_two test1 = 1;


message data_step_two 
    .data_step_three test2 = 2;


message data_step_three 
    .data_step_four test3 = 2;


message data_step_four 
    .data_step_five test4 = 14;


message data_step_five 
    .data_step_six test5 = 1;


message data_step_six 
    string something = 1;

当我从最后六个数组中删除字符串 (string something = 1;) 时

消息数据_step_six

它的工作没有那个错误。当我在六条消息中添加一些内容时,我得到了那个错误。我是这个 protobuf 消息的新手,所以不明白问题出在哪里以及我将如何解决它。

更新更多:

这是我的 post 方法的原始数据(我按照这个创建原始消息):

1 
  1: 1
  2: 58480067980758310
  4: 0

2 
  1 
    1: 112
    2 
      1: id:a-7769307577821621420
      2 
        14 
          1 
            1: mid:b-6430467773153509964
            2 
              1: 1
              2: mcacc.com
              3: Emma Ava
              10: mcacc.com
            
            3 
              1: 1
              2: scssd.com
            
            7: 1627577996674
            8: Test
            9 
              2 
                1: 0
                2: <div dir='auto'>This is test.</div>
              
              7: 1
            
            11: ^a
            11: ^all
            11: ^f_bt
            11: ^f_cl
            11: ^f_btns
            11: ^pfg
            18: 1627577996674
            36 
              6: 0
            
            37 
              4: 0
            
            42: 0
            52: s:23cbdb9f4cd2713a|#mid:b-6430467773153509964|0
          
          3: 1
        
      
    
  

3 
  1: 4
  2: 518600
  5 
    1: 30
    2: 0
  
  7: 1
  8 
    1: ^wa_ready
    1: ^f
    1: ^t_z
    2: ^r
  

4 
  2: 1
  3: 1627577996728
  4: 1
  5: 57

5: 2

这是我创建的原始消息:

syntax = "proto3";

message rs_request 
    .unknown_int_data unknown_int = 1;
    .unknown_int_data1 unknown_int1 = 2;
    .unknown_int_data2 unknown_int2 = 3;
    .unknown_int_data3 unknown_int3 = 4;
    bool unknown_int4 = 5;


message unknown_int_data 
    bool unint = 1;
    fixed32 unknown = 2;
    bool unknown1 = 4;


message unknown_int_data1 
    .unknown_int_datas unknown2 = 1;


message unknown_int_datas 
    int32 unknown3 = 1;
    .unknown_int_datas1 unknown4 = 2;


message unknown_int_datas1 
    string threadaId = 1;
    .unknown_int_datass unknowns = 2;


message unknown_int_datass 
    .unknown_int_datas2 unknown5 = 14;


message unknown_int_datas2 
    .unknown_int_datas3 unknown6 = 1;
    bool unknown7 = 3;


message unknown_int_datas3 
    string msgaId = 1;
    .unknown_int_datas4 unknown9 = 2;
    .unknown_int_datas5 unknown10 = 3;
    fixed32 unknown11 = 7;
    string subject = 8;
    .unknown_int_datas6 unknown12 = 9;
    string unknown13 = 11;
    fixed32 unknown14 = 18;
    .unknown_int_datas7 unknown15 = 36;
    .unknown_int_datas8 unknown16 = 37;
    int32 unknown17 = 42;
    string unknown18 = 52;


message unknown_int_datas4 
    bool unknown19 = 1;
    string from_domain = 2;
    string from_name = 3;
    string from_domain_again = 10;


message unknown_int_datas5 
    bool unknown20 = 1;
    string to_domain = 2;


message unknown_int_datas6 
    .unknown_int_datas9 unknown21 = 2;
    bool unknown22 = 7;


message unknown_int_datas9 
    bool unknown23 = 1;
    string msg = 2;


message unknown_int_datas7 
    bool unknown24 = 6;


message unknown_int_datas8 
    bool unknown25 = 4;


message unknown_int_data2 
    bool unknowsthree = 1;
    uint32 unknowsthree1 = 2;
    .unknowsthree_data unknowsthree2 = 5;
    bool unknowsthree3 = 7;
    .unknowsthree_datas unknowsthree4 = 8;


message unknowsthree_data 
    int32 unknowsthree5 = 1;
    bool unknowsthree6 = 2;


message unknowsthree_datas 
    string unknowsthree7 = 1;
    string unknowsthree8 = 2;


message unknown_int_data3 
    bool unknown26 = 2;
    fixed32 unknown27 = 3;
    bool unknown28 = 4;
    int32 unknown29 = 5;

这是post的请求模型json(mcRequestModel.php):

      "unknown_int1" => [
            "unknown2" => [
                "unknown4" => [
                    "unknowns" => [
                        "unknown5" => [
                            "unknown6" => [
                                "unknown9" => [
                                    "from_domain" => "mcacc.com",
                                    "from_name" => "Emma Ava",
                                    "from_domain_again" => "mcacc.com"
                                ],
                                "unknown10" => [
                                    "to_domain" => "scssd.com"
                                ],
                                "subject" => "Test",
                                "unknown12" => [
                                    "unknown21" => [
                                        "msg" => "<div dir='auto'>This is test.</div>"
                                    ]
                                ]
                            ]
                        ]
                    ]
                ]
            ]
        ]

尝试使用 php-protobuf 获取缓冲区编译器:

$mcRequest = new mcRequestModel();
$class = new \rs_request();
$class->parseFromJsonStream($mcRequest);
var_dump($class);

当我从数组unknown_int_datas3 中删除所有数据时,我得到了缓冲区编译器数组更大的输出,但当不从unknown_int_datas3 中删除数据时,我没有得到编译器输出,而只是得到Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 67112960 bytes) in C:\xampp\htdocs\...

【问题讨论】:

【参考方案1】:

编译器可能会受到消息中嵌套级别的挑战。

我不使用 PHP,但我将您的原型粘贴到 Marc Gravell 的 protogen 工具中,选择 PHP 并且它能够编译。

您的消息中的嵌套异常,我无法理解您为什么要这样做。您的问题中的一些上下文来解释您想要实现的目标可能会有用。

使用您当前的结构,在 JSON 中,data 消息将是:


  test: 
    test1: 
      test2: 
        test3: 
          test4: 
            test5: 
              something: "...."
            
          
        
      
    
  

Google 的style guide 推荐PascalCase 消息名称(即DataStepTwo)和snake_case 字段名称(您正在使用test

您的消息可能应该始终使用1 作为字段编号。您的每条消息只有 1 个字段,因此,除非您有意避免冲突,否则您可能希望避免使用 214

【讨论】:

我无法避免 214 它所需的 bcz json 数据有它。请检查我的帖子,我更新了它。谢谢 我不明白这些更新。您所说的“原始数据”具有不寻常的结构。这个结构对我来说完全陌生。您是否使用某些 3rd-party 服务将这些数据发布到?还是你写的东西?据我所知,您最好将该数据重新格式化为更传统的格式,然后根据该格式生成 protobuf。

以上是关于添加 6 条数组消息时出现 Protobuf 内存错误的主要内容,如果未能解决你的问题,请参考以下文章

使用管理 API 将 Protobuf 消息发布到 Pulsar 模式注册表时出现 500 错误

读取视频帧 iPhone 时出现内存问题

Protobuf-net 使用嵌套数据反序列化时出现无效的线型异常(C++ 到 C#)

对大型数组进行排序时出现快速排序错误

向 kafka 主题发送消息时出现 TimeoutException

创建大型 Access 报告时出现内存问题