麻豆精品无码av,欧美1区2区,久久中文字幕乱码人妻,亚洲欧美另类少妇精品,在线看黄射,69pao高清,九九九久久久国产精品,子操大逼1234区,九九爱99热精品

1
點(diǎn)贊
0
評(píng)論
0
轉(zhuǎn)載
收藏

經(jīng)驗(yàn)分享|大數(shù)據(jù)傳輸利器ProtoBuf使用指南

在大數(shù)據(jù)時(shí)代,人們每天都要面對(duì)海量數(shù)據(jù),如何存儲(chǔ)和傳輸這些數(shù)據(jù)成為了一大難題。Protocol Buffers(簡(jiǎn)稱ProtoBuf)是Google公司開(kāi)發(fā)的一種與語(yǔ)言和平臺(tái)無(wú)關(guān)的、可擴(kuò)展的、序列化結(jié)構(gòu)數(shù)據(jù)的方法,可用于(數(shù)據(jù))通信協(xié)議、數(shù)據(jù)存儲(chǔ)等。用戶可以利用ProtoBuf定義數(shù)據(jù)的結(jié)構(gòu),然后使用特殊生成的源代碼輕松地在各種數(shù)據(jù)流中使用各種語(yǔ)言來(lái)編寫和讀取結(jié)構(gòu)數(shù)據(jù),甚至還可以在不破壞由舊數(shù)據(jù)結(jié)構(gòu)編譯的已部署程序的基礎(chǔ)上更新數(shù)據(jù)結(jié)構(gòu)。ProtoBuf目前有兩個(gè)版本,分別是proto2和proto3,其中最新版本的proto3提供了對(duì)C++、C#、Dart、Go、Java、Python、Rust等多種語(yǔ)言的支持。ProtoBuf性能優(yōu)異,目前已經(jīng)被廣泛應(yīng)用于QQ、微信等主流通訊工具。

圖片

ProtoBuf的使用主要分為兩步,首先需要使用者在.proto文件中定義消息類型,然后使用protoc編譯器根據(jù).proto文件生成相應(yīng)語(yǔ)言的代碼。

圖1展示了一個(gè)簡(jiǎn)單的示例。我們定義了一個(gè)搜索請(qǐng)求消息,每一個(gè)搜索請(qǐng)求都包含了查詢字符query、搜索請(qǐng)求返回的頁(yè)面數(shù)量page_number和每頁(yè)中的結(jié)果數(shù)量result_per_page。該示例的第一行聲明了我們正在使用proto3。如果沒(méi)有該行,ProtoBuf編譯器將默認(rèn)使用proto2。需注意,該行一定要位于文件的第一非空且非注釋行。

圖片

圖1 ProtoBuf搜索請(qǐng)求消息示例

該請(qǐng)求消息示例中的SearchRequest消息定義了三個(gè)字段,每一個(gè)字段都有一個(gè)定義類型、一個(gè)字段名稱以及字段編號(hào)。ProtoBuf提供了大量標(biāo)準(zhǔn)數(shù)據(jù)類型,其中常用的有:double、float、int32、int64、bool、string、bytes等。此外,message中每個(gè)字段都可以指定一個(gè)修飾符,proto3默認(rèn)使用singular修飾符,表示可以有0個(gè)或者1個(gè)該字段,但不能超過(guò)一個(gè)。除此之外,還有一種repeated修飾符,表示對(duì)應(yīng)的字段在message中可以有任意數(shù)量個(gè),包括0個(gè)。

圖片

圖2 ProtoBuf嵌套類型字段示例

message中包含的字段類型除了默認(rèn)支持類型外,還支持嵌套類型,即字段類型為所定義的其他message類型。如圖2所示,我們?cè)赟earchResponse消息中包含了一個(gè)repeated修飾的Result類型字段。

圖片圖3 ProtoBuf多消息定義示例

在同一個(gè).proto文件中可以定義多個(gè)message類型,如圖3所示,我們?cè)谠?proto文件中定義了SearchRequest和SearchResponse兩個(gè)消息類型。與此同時(shí),ProtoBuf也可以在不同的.proto文件中定義message,然后通過(guò)import語(yǔ)法進(jìn)行引入。為了防止出現(xiàn)命名沖突的問(wèn)題,.proto文件將通過(guò)引入package語(yǔ)法解決命名沖突的問(wèn)題。

在解析消息時(shí),如果使用singular修飾符的字段不包含數(shù)據(jù),那么ProtoBuf會(huì)給對(duì)應(yīng)字段設(shè)定默認(rèn)值。對(duì)于string類型的字段,其默認(rèn)值為空字符串;對(duì)于bytes類型的字段,其默認(rèn)值為空字節(jié);對(duì)于bool類型的字段,其默認(rèn)值為false;對(duì)于數(shù)字類型的字段,其默認(rèn)值為0;對(duì)于enums類型的字段,其默認(rèn)值為第一個(gè)定義的枚舉類型。此外,對(duì)于使用repeated修飾符的字段,其默認(rèn)值為對(duì)應(yīng)語(yǔ)言的空列表。需要特別注意的是,proto2支持指定字段默認(rèn)值,但proto3已經(jīng)取消了該語(yǔ)法。

在代碼注釋上,ProtoBuf采用與C/C++相同的 // 和 /**/ 注釋格式,如圖4所示。

圖片

圖4 ProtoBuf注釋示例

最后,執(zhí)行圖5中的編譯指令后,我們就可以在相應(yīng)的目錄下找到生成的對(duì)應(yīng)語(yǔ)言的代碼文件。該文件包含了對(duì)不同message進(jìn)行定義、修改、訪問(wèn)等操作的方法。圖5中的IMPORT_PATH表示import文件的搜索目錄,--cpp_out、--java_out、--python_out、--go_out、--ruby_out、--objc_out、--csharp-out、--php_out分別表示生成的C++、Java、Python、GO、Ruby、Objective-C、C#、PHP目標(biāo)代碼存放目錄。以C++為例,執(zhí)行該編譯指令后會(huì)在目標(biāo)目錄生成file.pb.h和file.pb.cc兩個(gè)文件,file.pb.h中聲明了相關(guān)類和方法,file.pb.cc中定義了相關(guān)類和方法。

圖片

圖5 ProtoBuf編譯指令示例

俗話說(shuō)得好:“光說(shuō)不練假把式。”接下來(lái),我們就拿ProtoBuf與目前最常見(jiàn)的同類型工具JSON進(jìn)行對(duì)比,看看它到底強(qiáng)在哪里。JSON作為一種輕量級(jí)的基于文本的編碼方法,也可以用來(lái)存儲(chǔ)結(jié)構(gòu)化數(shù)據(jù),經(jīng)常被應(yīng)用于Client/Server端的通訊中。在對(duì)比實(shí)驗(yàn)中,我們選擇由騰訊公司發(fā)布的、使用性能較好的RapidJSON,基于C++編程語(yǔ)言進(jìn)行測(cè)試。

.proto文件如下

圖片

ProtoBuf測(cè)試代碼如下:

void Protobuf(int times)
{
    Person person;
    person.set_id(1000000);
    person.set_name("XIAOMING");
    person.add_phone_num(1008611);
    person.add_phone_num(1001011);

    string person_string;

    cout << "[Protobuf]" << endl << "--編碼耗時(shí)--" << endl;
    cout << "編碼次數(shù): " << times << "   數(shù)據(jù)長(zhǎng)度: " << person.SerializeAsString().size() << endl;

    auto start = chrono::steady_clock::now();
    for (size_t index = 0; index < times; ++index)
    {
        person_string = person.SerializeAsString();
    }
    auto end = chrono::steady_clock::now();
    cout << "用時(shí): " << chrono::duration<double,std::milli>(end - start).count() << " ms" << endl;

    cout << "--解碼測(cè)試--" << endl;
    cout << "解碼次數(shù): " << times << "   數(shù)據(jù)長(zhǎng)度: " << person.SerializeAsString().size() << endl;

    start = chrono::steady_clock::now();
    for (size_t index = 0; index < times; ++index)
    {
        person.ParseFromString(person_string);
    }
    end = chrono::steady_clock::now();
    cout << "用時(shí): " << chrono::duration<double,std::milli>(end - start).count() << " ms" << endl;
}

JSON測(cè)試代碼如下:

void Json(int times)
{
    Document doc;
    doc.Parse("{}");
    doc.AddMember("id", 1000000, doc.GetAllocator());
    doc.AddMember("name", "XIAOMING", doc.GetAllocator());
    Value phone_number(kArrayType);
    phone_number.PushBack(1008611, doc.GetAllocator());
    phone_number.PushBack(1001011, doc.GetAllocator());

    const char *person_string;
    StringBuffer buffer;
    Writer<StringBuffer> writer(buffer);
    doc.Accept(writer);
    
    person_string = buffer.GetString();

    cout << "[JSON]" << endl << "--編碼耗時(shí)--" << endl;
    cout << "編碼次數(shù): " << times << "   數(shù)據(jù)長(zhǎng)度: " << buffer.GetSize() << endl;

    auto start = chrono::steady_clock::now();
    for (size_t index = 0; index < times; ++index)
    {
        buffer.Clear();
        writer.Reset(buffer);
        doc.Accept(writer);
    }
    auto end = chrono::steady_clock::now();
    cout << "用時(shí): " << chrono::duration<double,std::milli>(end - start).count() << " ms" << endl;

    cout << "--解碼測(cè)試--" << endl;
    cout << "解碼次數(shù): " << times << "   數(shù)據(jù)長(zhǎng)度: " << buffer.GetSize() << endl;

    start = chrono::steady_clock::now();
    for (size_t index = 0; index < times; ++index)
    {
        doc.Parse(person_string);
    }
    end = chrono::steady_clock::now();
    cout << "用時(shí): " << chrono::duration<double,std::milli>(end - start).count() << " ms" << endl;
}

測(cè)試結(jié)果如下:

圖片

圖片

從上述測(cè)試結(jié)果可以看出,整體上ProtoBuf的編碼效率為RapidJSON的2.99倍,其解碼效率為RapidJSON的3.29倍,而且存儲(chǔ)空間僅為RapidJSON的68.75%。當(dāng)編碼和解碼頻率較低時(shí),二者耗時(shí)差異不明顯;但當(dāng)編碼和解碼頻率較高時(shí),ProtoBuf可以節(jié)省大量的時(shí)間。當(dāng)數(shù)據(jù)量較大時(shí),使用ProtoBuf可以有效降低空間需求,在網(wǎng)絡(luò)傳輸場(chǎng)景下,可以降低對(duì)網(wǎng)絡(luò)的要求,提高數(shù)據(jù)傳輸效率。

總體來(lái)說(shuō),ProtoBuf序列化和反序列的性能都比較高,編碼后的數(shù)據(jù)大小也不錯(cuò),編程模式簡(jiǎn)單易學(xué),同時(shí)擁有較為完備的文檔和示例,有需要的小伙伴放心用起來(lái)吧!

圖片

研究團(tuán)隊(duì)介紹

圖片

智能算法研究中心(原智能算法實(shí)驗(yàn)室,2018年與2020年更名)主要承擔(dān)國(guó)內(nèi)外重要智能算法類的研究課題,以算法與軟件工具包的形式,根據(jù)國(guó)內(nèi)外企業(yè)、科研與教育機(jī)構(gòu)等單位在智能信息處理方面的需求,解決相關(guān)技術(shù)難點(diǎn)問(wèn)題,并從中培養(yǎng)國(guó)際化算法研究型人才與算法工程化人才。

實(shí)驗(yàn)室必修課

實(shí)驗(yàn)室精神

圖片

-END-

總編:黃翰

責(zé)任編輯:袁中錦

文字:劉一鳴

圖片:劉一鳴

校稿:何莉怡

時(shí)間:2021年12月30日

聲明:本內(nèi)容系學(xué)者網(wǎng)用戶個(gè)人學(xué)術(shù)動(dòng)態(tài)分享,不代表平臺(tái)立場(chǎng)。

SCHOLAT.com 學(xué)者網(wǎng)
免責(zé)聲明 | 關(guān)于我們 | 聯(lián)系我們
聯(lián)系我們:
返回頂部
名山县| 武隆县| 平潭县| 梅州市| 新余市| 嫩江县| 嵊泗县| 香港| 赤峰市| 西乡县| 葫芦岛市| 中西区| 连州市| 宁晋县| 文水县| 达拉特旗| 竹溪县| 曲阳县| 许昌县| 西宁市| 稷山县| 荃湾区| 长沙市| 普安县| 蒙自县| 望奎县| 孟村| 随州市| 松阳县| 墨脱县| 中牟县| 抚远县| 盐边县| 环江| 钟祥市| 永定县| 运城市| 济源市| 墨竹工卡县| 邢台县| 浦江县|