- 快召唤伙伴们来围观吧
- 微博 QQ QQ空间 贴吧
- 文档嵌入链接
- 复制
- 微信扫一扫分享
- 已成功复制到剪贴板
祁宇-基于C++20+协程的C++20+高性能基础库--雅兰亭库助力开发者构建高性能应用
展开查看详情
1 .C++20 基础库--雅兰亭库助 力开发者构建高性能应用 祁宇 chufeng.qy@alibaba-inc.com
2 .主要内容 • 雅兰亭库简介 • 雅兰亭库序列化库 • 雅兰亭库rpc 库 • 雅兰亭库http 库
3 .C++20 基础库(雅兰亭库) C++20/23 新特性 阿里云编译器
4 .Alibaba Cloud Compiler(LLVM) Alibaba Cloud Compiler(ACC) LLVM编译器,相比GCC,或其他Clang/LLVM版本在编译、构建速 度上有很大的提升; 利用ACCThinLTO、AutoFDO和Bolt等技术可以在不同程度上优化程序性能。 通过编译器切换升级到ACC,可以在不用大幅修改代码的情况下获得性能提升和编译速度大幅提 升。 ACC与C++基础库,为龙蜥社区开发者提供了C++开发的一站式解决方案,快速构建高性能的 C++应用。
5 .雅兰亭库简介 • C++ 20 雅兰亭库 yaLanTingLibs • https://github.com/alibaba/yalantinglibs.git • 雅兰亭库是一个高性能易用的C++20 库合集,包括这些子库 • 序列化库(struct_pack, struct_pb, struct_json) • 基于协程的rpc 库 coro_rpc • 基于协程的http库 coro_http_client • 协程库async_simple
6 .高性能易用的序列化库—struct_pack • 序列化一个简单对象 struct person { protobuf序列化这样一个对象 int64_t id; std::string name; // person.proto void serialize_person() { int age; message person { person res; double salary; int32 id = 1; res.set_id(1); }; string name = 2; res.set_name("hello"); int32 age = 3; res.set_age(20); double salary = 4; res.set_salary(1024); } std::string buf; res.SerializeToString(&buf); }
7 .高性能易用的序列化库—struct_pack boost序列化库序列化person,one by one的去序列化字段 namespace boost::serialization { template<class Archive> void serialize(Archive & ar, person & p, const unsigned int){ ar & p.id; ar & p.name; ar & p.age; ar & p.salary; } } // namespace boost::serialization std::stringstream stream; boost::archive::binary_oarchive archive(stream); person p{}; archive << p; std::string buf = stream.str();
8 .高性能易用的序列化库—struct_pack • struct_pack: 一行代码完成对象序列化/反序列化 struct person { int64_t id; std::string name; int age; double salary; }; person p{.id = 1, .name = "tom", .age = 32}; // 一行代码序列化 auto buffer = struct_pack::serialize(p); // 一行代码反序列化 person res = struct_pack::deserialize<person>(buffer);
9 .enum Color : uint8_t { Red, Green, Blue }; struct Vec3 { float x; float y; float z; }; struct Weapon { std::string name; //一行代码序列化 int16_t damage; auto buffer = struct_pack::serialize(monster); }; //一行代码反序列化 struct Monster { auto monster2 = struct_pack::deserialize(buffer); Vec3 pos; int16_t mana; 不管对象多少字段,一行代码搞定,没有宏,没有DSL,没 int16_t hp; 有任何多余的代码 std::string name; std::vector<uint8_t> inventory; Color color; std::vector<Weapon> weapons; Weapon equipped; std::vector<Vec3> path; };
10 .高性能易用的序列化子库—struct_pack 性能比目前广泛使用的protobuf 高一个数量级 https://github.com/alibaba/yalant inglibs/blob/main/src/struct_pack /benchmark/benchmark.cpp
11 .struct_pb • protobuf C++17 的实现 • 比google protobuf 更高效 • 可以无缝迁移
12 .struct_pb • 通过protoc 生成protobuf序列化代码
13 .monster 场景struct_pb 的性能是google protobuf 的2 倍 https://github.com/alibaba/yalantinglibs/tree/main/src/struc t_pack/benchmark
14 .struct_json • 无需手写json代码,一行代码实现对象到json
15 .coro_rpc • coro_rpc server example std::string echo(std::string str); // rpc_service.h std::string echo(std::string str) { return str; } // rpc_service.cpp #include <coro_rpc/coro_rpc_server.hpp> #include "rpc_service.h" int main() { register_handler<echo>(); // register rpc function coro_rpc_server server(/*thread_num =*/10, 8801); server.start(); } https://github.com/alibaba/yalantinglibs.git
16 .coro_rpc # include "rpc_service.h" # include <coro_rpc/coro_rpc_client.hpp> Lazy<void> test_client() { coro_rpc_client client; co_await client.connect("localhost", /*port =*/9000); auto r = co_await client.call<echo>("hello coro_rpc"); //调用rpc函数 std::cout << r.result.value() << "\n"; //will print "hello coro_rpc" } int main() { syncAwait(test_client()); } api调用很安全,有类型和参数检查; Client只依赖rpc函数的头文件,rpc的实现不会暴露给client;
17 .coro_rpc的特色 • 易用 • 就像定义普通函数一样定义rpc函数 • 就像调用本地函数一样调用远程rpc函数 • 几行代码就可以完成一个rpc服务 • 用户只需要关注业务逻辑,不用关心底层细节(序列化、路由由框架完成, 用户无感知) • 免安装,包含头文件就可以用 • 安全 • client调用rpc,会在编译期检查做类型和参数的检查 • client只依赖rpc函数的头文件,rpc的实现不会暴露给client • 高性能(详见benchmark部分)
18 .支持任意个数参数 int get_value(int a, int b){return a + b;} person get_person(person p, int id) { return p;} struct dummy { std::string echo(std::string str) { return str; } }; 参数的序列化由struct_pack自动完成,用户无感知 int main() { register_handler<get_value, get_person>();//注册任意参数类型的普通函数 dummy d{}; register_handler<&dummy::echo>(&d); //注册成员函数 coro_rpc_server server(/*thread_num =*/10, /*port =*/9000); server.start(); }
19 .支持协程rpc函数 Lazy<int> get_coro_value(int val) { co_return val; } int main() { register_handler<get_coro_value>();//注册协程函数 coro_rpc_server server(/*thread_num =*/10, /*port =*/9000); server.start(); } auto client = create_client(); auto ret = client.call<get_coro_value>(42); CHECK(ret.value() == 42);
20 .coro_rpc benchmark • 环境 Intel(R) Xeon(R) Platinum 8163 CPU @ 2.50GHz 96核 OS: Linux version 4.9.151-015.ali3000.alios7.x86_64 编译器:Alibaba Cloud Compiler(Clang-13)、C++20 编译选项:Release –O3
21 .Benchmark 说明 • 测试case • 客户端和服务端都在同一台机器上,使用不同连接数发送请求做echo测试 • Pipeline 模式下极限qps 测试 • Ping-pong模式下的qps和时延测试 • 测试备注 • brpc由于采用了连接复用,实际上的socket连接数并没有那么多(实际连接数为96), coro_rpc的连接数是实际的连接数。 • 测试客户端统一用coro_rpc的压测客户端测试,压测效果较好,基本能把cpu打满。没 有使用brpc测试客户端原因是:如果用brpc客户端压测,brpc qps会降低一倍; • grpc的qps始终不会超过10万,故没有放进来做性能比较; • 目前测试场景仅仅是echo测试,没有测试更多更复杂的场景,测试数据仅供参考;
22 .极限qps 最大压力性能测试(QPS) 25000000 20228649 20000000 15000000 12809662 QPS 10399775 10000000 4987564 4530545 4137420 5000000 2186932 1029137 1918217 963124 1 0 4B 500B 1KB 5KB 10KB MESSAGE SIZE brpc coro_rpc
23 .ping-pong qps ping-pong QPS测试 5000000 4507942 4500000 4049234 4223495 4037650 4000000 3721739 3456991 3500000 3000000 2523798 QPS 2500000 1889515 2000000 1220241 1500000 1015568 1000000 500000 1 0 5 500 1000 5000 10000 PAYLOAD(BYTE) CORO_RPC QPS BRPC QPS
24 .ping-pong 时延 ping-pong测试(负载4B) 1.2 1 中位延迟时间(毫秒) 0.8 0.6 0.4 0.2 0 0 192 384 576 768 960 1152 1344 1536 1728 1920 客户端连接数量 CORO_RPC BRPC
25 .长尾测试 qps 长尾测试 平均 QPS 3500000 3000000 2500000 2000000 QPS 1500000 1000000 500000 0 96 192 288 384 480 576 672 768 864 960 1056115212481344144015361632172818241920 客户端数量 CORO RPC BRPC
26 .长尾测试时延 长尾测试 90% 延迟时间 1.2 1 延迟时间(毫秒) 0.8 0.6 0.4 0.2 0 0 192 384 576 768 960 1152 1344 1536 1728 1920 客户端数量 CORO RPC BRPC
27 .coro_http_client • 基于C++20 协程的http(https) client,包含了常用的get/post, websocket, multipart 文件上传, chunked/ranges 下载, redirect, proxy 等常用功能。
28 .coro_http_client • 以同步方式写异步http请求
29 .https://github.com/alibaba/yalantinglibs.git 雅兰亭库可以帮助用户轻松构建高性能C++ 应用! 未来还会增加越来越多的高性能易用的基础库,敬请期待!