coost v3.0.0 (微型 boost 库)发布


coost-A tiny boost library in C++11​

coost 是一个兼具性能与易用性的跨平台 C++ 基础库,原名为 co,后改为 cocoyaxi,前者过短,后者过长,取中庸之道,又改为 coost。

为什么叫 coost 呢?以前有朋友称之为小型 boost 库,比 boost 小一点,那就叫 coost 好了。它有多小呢?在 linux 与 mac 上编译出来的静态库仅 1M 左右大小。虽然小,却提供了足够强大的功能:

  • 命令行参数与配置文件解析库(flag)
  • 高性能日志库(log)
  • 单元测试框架(unitest)
  • go-style 协程
  • 基于协程的网络编程框架
  • 高效 JSON 库
  • 基于 JSON 的 RPC 框架
  • 面向玄学编程
  • 原子操作(atomic)
  • 随机数生成器(random)
  • 高效字符流(fastream)
  • 高效字符串(fastring)
  • 字符串操作(str)
  • 时间库(time)
  • 线程库(thread)
  • 定时任务调度器
  • 高性能内存分配器
  • LruMap
  • hash 库
  • path 库
  • 文件系统操作(fs)
  • 系统操作(os)

本次发布的版本,直接从 v2.0.3 跳到了 v3.0.0,跨度非常之大,它在性能易用性稳定性等方面均有全面的提升。

性能优化

内存分配器

v3.0 中实现了一个新的内存分配器(co/malloc),它不是通用的内存分配器,在 free realloc 时,需要额外带上原内存块的 size 信息,这在使用时可能有一点点不便,但可以简化设计,提升内存分配器的性能。

通用的内存分配器,像 ptmalloc, jemalloc, tcmalloc 以及 mimalloc 等,小内存释放后大概率会被它们缓存住,而并没有归还给操作系统,这可能造成释放大量小内存后内存占用量却始终不降的疑似内存泄漏的现象。co/malloc 对此做了优化,在兼顾性能的同时,会尽可能多的将释放的内存归还给操作系统,有利于降低程序的内存占用量,在实测中也取得了良好的效果。

co/malloc 还提供了 co::stl_allocator,可以替换 STL 容器中默认的分配器 std::allocator。co/stl.h 中提供了一些常用的替换 allocator 后的容器,与 std 版本相比有着性能上的优势。

co/malloc 已经成为 coost 内部使用的默认内存分配器,像 fastring、fastream、Json 等均基于 co/malloc 实现。co/test 中提供了简单的测试代码,可以执行如下命令编译及运行:

xmake b mem
xmake r mem -t 4 -s

-t 指定线程数量,-s 表示与系统的内存分配器进行对比。下面是在不同系统中的测试结果(4线程):

os/cpu co::alloc co::free ::malloc ::free speedup
win/AMD 3.2G 7.32 6.83 86.05 105.06 11.7/15.3
mac/i7 2.4G 9.91 9.86 55.64 60.20 5.6/6.1
linux/i7 2.2G 10.80 7.51 1070.5 21.17 99.1/2.8

上表中,时间单位为纳秒(ns),linux 是在 Windows WSL 中运行的 ubuntu 系统,speedup 是 co/malloc 相对于系统内存分配器的性能提升倍数。可以看到 co::alloc 在 Linux 上比 ::malloc 提升了近 99 倍,这其中的一个重要原因是 ptmalloc 在多线程环境中锁竞争开销较大,而 co/malloc 在设计上尽可能避免了锁的使用,小块内存的分配、释放不需要锁,甚至在跨线程释放时连自旋锁也不用。

原子操作

v3.0 中,原子操作支持 memory order,以满足一些高性能应用场景的需求。co/atomic.h 中定义了 6 种 memory order,与 C++11 标准中保持一致:

mo_relaxedmo_consumemo_acquire 
mo_releasemo_acq_relmo_seq_cst
  • 代码示例
int i = 0;
uint64 u = 0;
atomic_inc(&i, mo_relaxed);
atomic_load(&i, mo_relaxed);
atomic_add(&u, 3); // mo_seq_cst
atomic_add(&u, 7, mo_acquire);

易用性提升

简化初始化过程

v2.0.3 中,main 函数可能得像下面这样写:

#include "co/flag.h"
#include "co/log.h"
#include "co/co.h"

int main(int argc, char** argv) {
flag::init(argc, argv);
log::init();
co::init();
// do something here...
co::exit();
return 0;
}

为了提升用户的使用体验,v3.0 中移除了 log::init()co::init()co::exit() 等 API,现在 main 函数可以写成下面这样:

#include "co/flag.h"

int main(int argc, char** argv) {
flag::init(argc, argv);
// do something here...
return 0;
}

v3.0 中,整个 coost 库唯一需要调用的初始化接口就是 flag::init(),该接口用于解析命令行参数及配置文件。

flag

co/flag 是一个简单易用的命令行参数与配置文件解析库,coost 中的日志、协程、RPC框架等组件会用它定义配置项。

v3.0 中,对一些细节处进行了改进,如 --help 只显示用户自己定义的 flag,而不会显示 coost 内部定义的 flag。

v3.0 还新增了 flag 别名功能,在定义 flag 时,可以指定任意数量的别名:

DEF_bool(debug, false, ""); // no alias
DEF_bool(debug, false, "", d);// d is an alias of debug
DEF_bool(debug, false, "", d, dbg); // 2 aliases

日志

v2.0.3 中,co/log 提供类似 google glog 的日志功能,将日志分成 debug、info、warning、error、fatal等级别。v3.0 中,新增 TLOG,即按 topic 分类的日志,不同 topic 的日志输出到不同的文件。

v3.0 中,co/log 不需要用户手动初始化,包含 co/log.h 即可使用,不需要特别的设置。

#include "co/log.h"

int main(int argc, char** argv) {
flag::init(argc, argv);

DLOG << "hello " << 23; // debug
LOG << "hello " << 23;// info
WLOG << "hello " << 23; // warning
ELOG << "hello " << 23; // error
FLOG << "hello " << 23; // fatal
TLOG("rpc") << "hello " << 23;
TLOG("xxx") << "hello " << 23;

return 0;
}

JSON

v2.0.3 中,JSON 对象构建在连续内存上,可以减少内存分配、提升性能,但易用性会降低。v3.0 中有了 co/malloc,JSON 采用了更加灵活的实现方式,在保持高性能的同时,易用性方面也有了质的提升。

co/json 与 rapidjson 的性能比较

os co/json stringify co/json parse rapidjson stringify rapidjson parse speedup
win 569 924 2089 2495 3.6/2.7
mac 783 1097 1289 1658 1.6/1.5
linux 468 764 1359 1070 2.9/1.4

上表是将 twitter.json 最小化后的测试结果,耗时单位为微秒(us),speedup 是 co/json 相对于 rapidjson 的性能提升倍数。

v3.0 中实现了 Json 类,它采用流畅(fluent)接口设计,用起来更加方便。

// {"a":23,"b":false,"s":"123","v":[1,2,3],"o":{"xx":0}}
Json x = {
{ "a", 23 },
{ "b", false },
{ "s", "123" },
{ "v", {1,2,3} },
{ "o", {
{"xx", 0}
}},
};

// equal to x
Json y = Json()
.add_member("a", 23)
.add_member("b", false)
.add_member("s", "123")
.add_member("v", Json().push_back(1).push_back(2).push_back(3))
.add_member("o", Json().add_member("xx", 0));

x.get("a").as_int(); // 23
x.get("s").as_string();// "123"
x.get("s").as_int(); // 123, string -> int
x.get("v", 0).as_int();// 1
x.get("v", 2).as_int();// 3
x.get("o", "xx").as_int(); // 0

x["a"] == 23;// true
x["s"] == "123"; // true
x.get("o", "xx") != 0; // false

RPC

v3.0 中,RPC 框架新增对 HTTP 协议的支持,将 RPC 服务与 HTTP 服务融为一体

#include "co/all.h"

int main(int argc, char** argv) {
flag::init(argc, argv);

rpc::Server()
.add_service(new xx::HelloWorldImpl)
.start("127.0.0.1", 7788, "/xx");

for (;;) sleep::sec(80000);
return 0;
}

rpc::Server 可以添加多个 service,调用 start() 方法即可启动 RPC 服务,该方法的第 3 个参数指定 HTTP 服务的 URL。用户可以通过 rpc::Client 调用其服务,也可以通过 HTTP 的方式调用其服务,如:

curl http://127.0.0.1:7788/xx --request POST --data '{"api":"ping"}'
curl http://127.0.0.1:7788/xx --request POST --data '{"api":"HelloWorld.hello"}'

RPC 请求或 HTTP 请求的 body 部分是 JSON 字符串,需要用 api 字段指明调用的方法,该字段的值一般为 service.method 形式。ping 则是 coost RPC 框架内置的特殊 service,可用于发送心跳或测试。

稳定性提升

coost 提供了一套简单易用的单元测试框架,并且在 unitest 目录下提供了大量的单元测试代码,几乎覆盖了 coost 内部的所有组件,为 coost 的稳定性提供了重要的保障。

v3.0 中又新增了不少单元测试代码,进一步提高了单元测试覆盖率。另外,针对一些不便编写单元测试的功能,coost 在 test 目录下单独提供了大量的测试代码。


相關推薦

2023-09-10

新增功能 基准测试框架。 #include "co/benchmark.h" #include "co/mem.h"   BM_group(malloc) { void* p;   BM_add(::malloc)( p = ::malloc(32); ); BM_use(p);   BM_add(co::alloc)( p = co::alloc(32); ); BM_use(p); }   int main(int argc, char** argv) { flag::parse(argc,

2023-10-27

当前版本为“最新版”,生产环境推荐使用“稳定版”,参考这里获取版本信息 获取更多信息,请阅读FISCO BCOS 3.x文档 新增 新增rPBFT共识算法 支持交易同步、区块同步的树状广播 交易池按时间顺序打包交易 新增Paillier

2024-06-29

动态代理转发,可以通过API直接切换后端的集群,为蓝绿发布提供了另外的技术途径。至此, 结合"动态表达式location"实现灰度引流测试,在测试完成后,通过动态代理转发实现蓝绿切换,NJet为企业急需的关键业务无中断的滚动

2022-08-13

Boost 是一套用于 C++ 编程语言的库,为线性代数、伪随机数生成、多线程、图像处理、正则表达式和单元测试等任务和结构提供支持。它包含了 164 个单独的库(截至 1.76 版)。 已知问题 这些是库的作者提出的补丁,由于发现

2022-12-17

Boost 是一套用于 C++ 编程语言的库,为线性代数、伪随机数生成、多线程、图像处理、正则表达式和单元测试等任务和结构提供支持。它包含了 164 个单独的库(截至 1.76 版)。 新的库: URL:一个仅使用 C++11 解析、修改和打

2023-01-09

go-mir v3.0.0 发布了,v3版本带来全新的RESTful API开发方式,提供媲美gRPC服务开发的体验,方便快捷,欢迎参考使用。 ​Mir 是一套提供类似gRPC服务开发体验的快速开发RESTful API后端开发脚手架,适配多种HTTP框架,包括Gin, Chi, Hert

2022-08-12

序言 在重构 Furion 的定时任务模块时发现 Hangfire 开源的 Cron 解析工具类不够强大:不支持星期,不支持完整的 Cron 表达式解析。翻遍了 Github 和 Nuget 没找到一个完完整整支持 Cron 的 .NET 库。 所以,机会来了。😊 TimeCrontab &n

2024-06-28

OpenNJet v3.0.0 已经发布,这是一个云原生应用引擎。 此版本更新内容包括: 新功能 动态证书吊销列表更新 http2mqtt 消息代理 http2kafka 消息代理 数据消隐(access日志隐藏敏感信息) 集群动态桥接 集群间文件同步 大

2022-10-27

RePlugin v3.0.0 现已发布。RePlugin 是一套完整的、稳定的、适合全面使用的,占坑类插件化方案,由 360 手机卫士的 RePlugin Team 研发,也是业内首个提出” 全面插件化 “(全面特性、全面兼容、全面使用)的方案。 此版本更新内

2023-05-04

【基础版】    🚨 Breaking Changes 重构 SearchBar 组件 重构接口请求,统一管理接口请求模块 移除 BatchActionBar 组件    🐞 Bug Fixes 修复主页无法引入请求 api 并使用的问题

2023-03-31

更多伙伴一期加入维护。 版本介绍 UEditorPlus v3.0.0 已经发布。 新增:Markdown标题快捷模式(输入多个#+空格自动格式化为标题) 新增:当内容最末尾为非字符时,比较难以在最后插入字符问题 新增:beforesubmit事件,

2023-09-28

本地和远程的 Java 进程。 官方文档:www.yuque.com/jarboot 3.0.0-beta3(9,2023) 新特性:集群模式 支持定时任务类型 修复目录中文连接超时bug 服务重启和删除功能 上下键历史命令功能 新版 UI 视频展示:https://www.bilibili

2024-09-25

本来没有,难得弱小生来。借华为的话,“我们敢于非凡”。七年时间,我们不断变强!越来越强!还会更强! Solon 框架! Java “新式”应用开发框架。开放原子开源基金会,孵化项目。从零开始构建(非 java-ee 架构),有灵

2023-12-13

Jarboot 是一个强大的 Java 进程管理、诊断的平台,可以在线管理、监控及诊断本地和远程的 Java 进程。 官方文档:www.yuque.com/jarboot 3.0.0(12,2023) 3.0.0跨越式升级,新增暗黑主题,支持主题跟随系统变化,集群模式支持,多个