当前位置: 首页 > wzjs >正文

鞍山信息网便民信息百度爱采购优化排名软件

鞍山信息网便民信息,百度爱采购优化排名软件,wordpress 去除图片,wordpress链接浏览量文章目录 前言一、生成火焰图二、protobuf标量值类型变长整形有符号整数非变长整数长度限定记录可选和重复元素打包重复字段映射 grpc2. CMakeLists.txt references 前言 protobuf: 一种将结构化数据进行序列化和反序列化的协议,提供IDL工具,生成接口代…

文章目录

  • 前言
  • 一、生成火焰图
  • 二、protobuf
    • 标量值类型
    • 变长整形
    • 有符号整数
    • 非变长整数
    • 长度限定记录
    • 可选和重复元素
    • 打包重复字段
    • 映射
  • grpc
    • 2. CMakeLists.txt
  • references


前言

protobuf: 一种将结构化数据进行序列化和反序列化的协议,提供IDL工具,生成接口代码,支持多种语言。
rpc: 类似http的请求相应模式,可跨设备提供远程接口调用功能,其接口可通过protobuf定义。

利用perf生成火焰图,分析程序性能


一、生成火焰图

perf record -F 99 -g --pid $PID -- sleep 30
  • -F 99:设置采样频率为每秒99次(可以根据需要调整)。
  • –pid $PID:指定要监控的进程ID。
  • – sleep 30:表示监控30秒。
git clone https://github.com/brendangregg/FlameGraph.git
perf script | ./FlameGraph/stackcollapse-perf.pl | ./FlameGraph/flamegraph.pl > flamegraph.svg

flamegraph.svg

二、protobuf

  1. 编译源码:
git clone https://github.com/protocolbuffers/protobuf.git
cd protobuf
git submodule update --init --recursivecmake . -DCMAKE_CXX_STANDARD=14
cmake --build .
  1. 定义.proto文件
syntax = "proto2";package tutorial;message Person {optional string name = 1;optional int32 id = 2;optional string email = 3;enum PhoneType {PHONE_TYPE_UNSPECIFIED = 0;PHONE_TYPE_MOBILE = 1;PHONE_TYPE_HOME = 2;PHONE_TYPE_WORK = 3;}message PhoneNumber {optional string number = 1;optional PhoneType type = 2 [default = PHONE_TYPE_HOME];}repeated PhoneNumber phones = 4;
}message AddressBook {repeated Person people = 1;
}
  1. 编译.proto文件生成接口代码
protoc -I=$SRC_DIR --cpp_out=$DST_DIR $SRC_DIR/addressbook.proto
  1. CMakeLists.txt
cmake_minimum_required(VERSION 3.10)project(protobuf-test)find_package(protobuf CONFIG REQUIRED)if(protobuf_VERBOSE)message(STATUS "Using Protocol Buffers ${protobuf_VERSION}")
endif()set(CMAKE_INCLUDE_CURRENT_DIR TRUE)add_executable(${PROJECT_NAME} main.cpp addressbook.pb.cc)
target_include_directories(${PROJECT_NAME} PUBLIC install/usr/local/include
)
target_link_libraries(${PROJECT_NAME}protobuf::libprotobuf
)
#include <iostream>
#include <fstream>
#include <string>
#include "addressbook.pb.h"using namespace std;void list_people(const tutorial::AddressBook& address_book)
{for (int i = 0; i< address_book.people_size(); ++i) {const tutorial::Person& person = address_book.people(i);cout << "Person ID: " << person.id() << endl;cout << " Name: " << person.name() << endl;if (person.has_email()) {cout << " E-mail address: " << person.email() << endl;}for (int j = 0; j < person.phones_size(); ++j) {const tutorial::Person::PhoneNumber& phone_number = person.phones(j);switch (phone_number.type()) {case tutorial::Person::PHONE_TYPE_MOBILE:cout << "  Mobile phone #: ";break;case tutorial::Person::PHONE_TYPE_HOME:cout << "  Home phone #: ";break;case tutorial::Person::PHONE_TYPE_WORK:cout << "  Work phone #: ";break;}cout << phone_number.number() << endl;}}
}void PromptForAddress(tutorial::Person* person)
{cout << "enter person id number: ";int id;cin >> id;person->set_id(id);cin.ignore(256, '\n');cout << "enter name: ";getline(cin, *person->mutable_name());string email;getline(cin, email);if (!email.empty()){person->set_email(email);}while (true){cout << "enter a ph num: ";string number;getline(cin, number);if (number.empty()) break;tutorial::Person::PhoneNumber* phone_number = person->add_phones();phone_number->set_number(number);cout << "is this a mobile, home, or work phone?";string type;getline(cin, type);if (type == "mobile") {phone_number->set_type(tutorial::Person::PHONE_TYPE_MOBILE);} else if (type == "home") {phone_number->set_type(tutorial::Person::PHONE_TYPE_HOME);} else if (type == "work") {phone_number->set_type(tutorial::Person::PHONE_TYPE_WORK);} else {cout << "Unknown type. using default." << endl;}}}int main(int argc, char* argv[])
{// Verify that the version of the library that we linked against is// compatible with the version of the headers we compiled against.GOOGLE_PROTOBUF_VERIFY_VERSION;if (argc != 2){cerr << "Usage: " << argv[0] << " ADDRESS_BOOK_FILE" << endl;return -1;}tutorial::AddressBook address_book;{fstream input(argv[1], ios::in | ios::binary);if (!input) {cout << argv[1] << ": File not found. Create a new file." << endl;} else if (!address_book.ParseFromIstream(&input)) {cerr << "Failed to parse address book." << endl;return -1;}}PromptForAddress(address_book.add_people());{fstream output(argv[1], ios::out | ios::trunc | ios::binary);std::stringstream ss;std::vector<char> buf;if (!address_book.SerializeToOstream(&output)) {cerr << "Failed to write address book." << endl;return -1;}string str;if (!address_book.SerializeToString(&str)){cerr << "Failed to write address book." << endl;return -1;}for (int i = 0; i < str.size(); ++i){printf("%x ", *(unsigned char*)&str[i]);}cout << "\n";}list_people(address_book);// Optional:  Delete all global objects allocated by libprotobuf.google::protobuf::ShutdownProtobufLibrary();
}

标量值类型

.proto 类型注释C++ 类型
doubledoubledouble
floatfloatfloat
int32使用可变长度编码。对编码负数效率低下——如果您的字段可能包含负值,请改用 sint32。int32
int64使用可变长度编码。对编码负数效率低下——如果您的字段可能包含负值,请改用 sint64。int64
uint32使用可变长度编码。uint32
uint64使用可变长度编码。uint64
sint32使用可变长度编码。有符号整数类型。这些类型比常规 int32 更有效地编码负数。int32
sint64使用可变长度编码。有符号整数类型。这些类型比常规 int64 更有效地编码负数。int64
fixed32始终为四个字节。如果值通常大于 228,则比 uint32 更有效。uint32
fixed64始终为八个字节。如果值通常大于 256,则比 uint64 更有效。uint64
sfixed32始终为四个字节。int32
sfixed64始终为八个字节。int64
boolbool
string 字符串必须始终包含 UTF-8 编码或 7 位 ASCII 文本,并且长度不能超过 232。string
bytes 可以包含任何任意字节序列,长度不超过 232。string

标量之类型 https://protobuf.com.cn/programming-guides/proto3/

编码 https://protobuf.com.cn/programming-guides/encoding/

变长整形

可变宽度整数,或 变长整数,是线格式的核心。它们允许使用 1 到 10 个字节对无符号 64 位整数进行编码,其中较小的值使用较少的字节。

变长整数中的每个字节都有一个 延续位,指示其后面的字节是否属于该变长整数。这是字节的 最高有效位 (MSB)(有时也称为 符号位)。较低的 7 位是有效负载;生成的整数是通过将组成字节的 7 位有效负载拼接在一起构建的。

因此,例如,以下是数字 1,编码为 01——它是一个字节,因此 MSB 未设置

0000 0001
^ msb

以下是 150,编码为

低字节    高字节
10010110 00000001
^ msb    ^ msb
10010110 00000001        // Original inputs.低字节     高字节0010110  0000001        // Drop continuation bits.p[0]      p[1]uint64 = p[0]&0x7f + p[1]&0xf7 * 128UL = 22 + 128 = 150

协议缓冲区消息是一系列键值对。消息的二进制版本仅使用字段的编号作为键——每个字段的名称和声明类型只能在解码端通过引用消息类型的定义(即 .proto 文件)来确定。Protoscope 无法访问此信息,因此它只能提供字段编号。

当消息被编码时,每个键值对都会转换为一个 记录,该记录由字段编号、线类型和有效负载组成。线类型告诉解析器后面的有效负载有多大。这允许旧解析器跳过它们不理解的新字段。这种类型的方案有时称为 标记-长度-值 或 TLV。

有六种线类型:VARINT、I64、LEN、SGROUP(已弃用)、EGROUP(已弃用) 和 I32

ID名称用于
0VARINTint32、int64、uint32、uint64、sint32、sint64、bool、enum
1I64fixed64、sfixed64、double
2LENstring、bytes、嵌入式消息、打包重复字段
5I32fixed32、sfixed32、float

记录的“标记”编码为一个变长整数,该整数由字段编号和线类型通过公式 (field_number << 3) | wire_type 形成。换句话说,在解码表示字段的变长整数后,低 3 位告诉我们线类型,其余整数告诉我们字段编号。

现在让我们再次查看我们的简单示例。您现在知道流中的第一个数字始终是变长整数键,这里它是 0x08,或者(删除 MSB)

key的值:
0000 1000000 1000^^^ ^ field_number^^^ wire_type所以 字段编号为1
类型为 VARINT

您取最后三位以获取线类型 (0),然后右移三位以获取字段编号 (1)。Protoscope 将标记表示为整数后跟冒号和线类型,因此我们可以将上述字节写为 1:VARINT。

因为线类型是 0 或 VARINT,所以我们知道我们需要解码一个变长整数以获取有效负载。如上所述,字节 0x9601 变长整数解码为 150,从而给出我们的记录。我们可以用 Protoscope 将其写成 1:VARINT 150。

布尔值和枚举都像 int32 一样编码。特别是,布尔值始终编码为 0001。在 Protoscope 中,false 和 true 是这些字节字符串的别名。

有符号整数

正如您在上一节中看到的,与线类型 0 关联的所有协议缓冲区类型都编码为变长整数。但是,变长整数是无符号的,因此不同的有符号类型,sint32 和 sint64 与 int32 或 int64 相比,对负整数的编码方式不同。

intN 类型将负数编码为二进制补码,这意味着作为无符号 64 位整数,它们设置了最高位。结果,这意味着必须使用 所有十个字节。例如,-2 由 protoscope 转换为

11111110 11111111 11111111 11111111 11111111
11111111 11111111 11111111 11111111 00000001

这是 2 的二进制补码,在无符号算术中定义为~0 - 2 + 1,其中~0 是全为 1 的 64 位整数。理解为什么这会产生这么多 1 是一项有益的练习。

sintN 使用“ZigZag”编码而不是二进制补码来编码负整数。正整数p 编码为2 * p(偶数),而负整数n 编码为2 * |n| - 1(奇数)。因此,编码在正数和负数之间“锯齿形”变化。例如

带符号原始值编码为
00
-11
12
-23
0x7fffffff0xfffffffe
-0x800000000xffffffff

“ZigZag”:

整数: 左移动一位

负数: ~(左移一位)

非变长整数

非 varint 数值类型很简单 - double 和fixed64 的线类型为I64,它告诉解析器预期一个固定的八字节数据块。我们可以通过编写5: 25.4 来指定double 记录,或通过6: 200i64 来指定fixed64 记录。在这两种情况下,省略显式线类型都意味着I64 线类型。

类似地,float 和fixed32 的线类型为I32,它告诉解析器预期四个字节。这些类型的语法包括添加i32 后缀。25.4i32 将发出四个字节,200i32 也是如此。标签类型被推断为I32。

长度限定记录

message Test2 {optional string b = 2;
}字段b 的记录是一个字符串,字符串是LEN 编码的。如果我们将b 设置为"testing",则将其编码为一个LEN 记录,字段号为 2,包含 ASCII 字符串"testing"。12 07 [74 65 73 74 69 6e 67]

可选和重复元素

message Test4 {optional string d = 4;repeated int32 e = 5;
}4: {"hello"}
5: 1
5: 2
5: 3

打包重复字段

映射

映射字段只是特殊类型的重复字段的简写。如果我们有

message Test6 {map<string, int32> g = 7;
}

这实际上与以下内容相同

message Test6 {message g_Entry {optional string key = 1;optional int32 value = 2;}repeated g_Entry g = 7;
}

因此,映射的编码方式与repeated 消息字段完全相同:作为一系列LEN 类型的记录,每个记录有两个字段。

grpc

https://grpc.io/docs/languages/cpp/basics/
https://github.com/grpc/grpc/tree/master/examples/cpp/route_guide

2. CMakeLists.txt

cmake_minimum_required(VERSION 3.8)project(RouteGuide C CXX)foreach(__prefix_path__  absl c-ares grpc protobuf re2 utf8_range)list(APPEND CMAKE_PREFIX_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../thirdparty/grpc/lib/cmake)
endforeach()include(/home/igs/Projects/grpc/examples/cpp/cmake/common.cmake)# Find absl package
find_package(absl CONFIG REQUIRED)# Proto file
get_filename_component(rg_proto "${CMAKE_CURRENT_SOURCE_DIR}/route_guide.proto" ABSOLUTE)
get_filename_component(rg_proto_path "${rg_proto}" PATH)# Generated sources
set(rg_proto_srcs "${CMAKE_CURRENT_BINARY_DIR}/route_guide.pb.cc")
set(rg_proto_hdrs "${CMAKE_CURRENT_BINARY_DIR}/route_guide.pb.h")
set(rg_grpc_srcs "${CMAKE_CURRENT_BINARY_DIR}/route_guide.grpc.pb.cc")
set(rg_grpc_hdrs "${CMAKE_CURRENT_BINARY_DIR}/route_guide.grpc.pb.h")
add_custom_command(OUTPUT "${rg_proto_srcs}" "${rg_proto_hdrs}" "${rg_grpc_srcs}" "${rg_grpc_hdrs}"COMMAND ${_PROTOBUF_PROTOC}ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}"--cpp_out "${CMAKE_CURRENT_BINARY_DIR}"-I "${rg_proto_path}"--plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}""${rg_proto}"DEPENDS "${rg_proto}")# Include generated *.pb.h files
include_directories("${CMAKE_CURRENT_BINARY_DIR}")# rg_grpc_proto
add_library(rg_grpc_proto${rg_grpc_srcs}${rg_grpc_hdrs}${rg_proto_srcs}${rg_proto_hdrs})
target_link_libraries(rg_grpc_protoabsl::absl_log${_REFLECTION}${_GRPC_GRPCPP}${_PROTOBUF_LIBPROTOBUF})# Targets route_guide_(client|server)
foreach(_target route_guide_server route_guide_client route_guide_callback_server route_guide_callback_client)add_executable(${_target}"${_target}.cc" helper.cc)target_link_libraries(${_target}rg_grpc_protoabsl::flags_parseabsl::absl_logabsl::log_initializeabsl::log_globals${_REFLECTION}${_GRPC_GRPCPP}${_PROTOBUF_LIBPROTOBUF})
endforeach()

references

https://protobuf.dev/programming-guides/proto3/

https://cloud.tencent.com/developer/article/2463651
https://grpc.io/docs/languages/cpp/basics/
https://github.com/grpc/grpc/tree/master/examples/cpp/route_guide

http://www.dtcms.com/wzjs/22588.html

相关文章:

  • 做简历的网站都有哪些内容网络营销的基本方法
  • 做网站后期维护做一个公司网站需要多少钱
  • 网站建设要什么知识南昌seo优化公司
  • 校园网站建设标书文娱热搜榜
  • 政府网站建设工作总结6seo长尾快速排名
  • 一般纳税人企业所得税怎么征收福清seo
  • 做外贸什么网站百度问答平台
  • 网站用的什么数据库手机制作网站的软件
  • 自己做视频网站会不会追究版权长春网站建设团队
  • 网站内容建设和管理百度竞价广告收费标准
  • 台州企业网站搭建厂家torrentkitty磁力天堂
  • 平度168网站建设深圳seo优化培训
  • 028网站建设工作室网站运营维护的基本工作
  • 个人网站取什么域名好网上竞价
  • 洛阳网站建设内容西藏自治区seo 标题 关键词优化
  • 做彩票网站郑州seo团队
  • 网站友情链接怎么添加商城网站建设
  • 广州网站建设定制百度app安卓版下载
  • 网络推广 公司 200个网站总排行榜总点击榜总收藏榜
  • 万网网站备案怎么分析一个网站seo
  • 网站建设怎样设置动态背景免费的客户资源怎么找
  • 做企业网站怎么收费的华与华营销策划公司
  • 外贸家具网站seo的中文含义是什么意思
  • 做淘宝banner的网站软文推广代理平台
  • 济南做网站xywlcn信阳seo推广
  • 龙岗建网站公司广州优化防控措施
  • 物联网公司排名国内跟我学seo
  • 南昌网站建设专业公司全网营销方案
  • 山东seo网站网站运营是做什么的
  • 怎样做网站的优化工作排名优化网站建设