@@ -12,17 +12,17 @@ title: "简介"
12
12
13
13
** [ coost] ( https://github.com/idealvin/coost ) ** 是一个** 兼具性能与易用性** 的跨平台 C++ 基础库,其目标是打造一把 C++ 开发神器,让 C++ 编程变得简单、轻松、愉快。
14
14
15
- coost 原名为 co,后改为 cocoyaxi,前者过短,后者过长,取中庸之道,又改为 coost。它曾被称为小型 [ boost] ( https://www.boost.org/ ) 库,与 boost 相比,coost 小而精美,在 ** linux 与 mac 上编译出来的静态库仅 1M 左右大小** ,却包含了不少强大的功能:
15
+ coost 简称为 co,曾被称为小型 [ boost] ( https://www.boost.org/ ) 库,与 boost 相比,coost 小而精美,在 ** linux 与 mac 上编译出来的静态库仅 1M 左右大小** ,却包含了不少强大的功能:
16
16
17
17
18
18
{{< columns >}}
19
19
20
20
- 命令行与配置文件解析(flag)
21
21
- ** 高性能日志库(log)**
22
- - 单元测试框架(unitest)
22
+ - 单元测试框架
23
+ - 基准测试框架
23
24
- ** go-style 协程**
24
25
- 基于协程的网络编程框架
25
- - 高效 JSON 库
26
26
- ** 基于 JSON 的 RPC 框架**
27
27
28
28
<--->
@@ -38,7 +38,7 @@ coost 原名为 co,后改为 cocoyaxi,前者过短,后者过长,取中
38
38
<--->
39
39
40
40
- ** 面向玄学编程**
41
- - LruMap
41
+ - 高效 JSON 库
42
42
- hash 库
43
43
- path 库
44
44
- 文件系统操作(fs)
@@ -93,21 +93,21 @@ xmake r co
93
93
94
94
### 使用 coost 开发 C++ 项目
95
95
96
- 最简单的,可以直接包含 [ co/all.h] ( https://github.com/idealvin/coost/blob/master/include/co/all.h ) ,使用 coost 中的所有特性。如果担心影响编译速度,也可以只包含需要用到的头文件,如包含 [ co/co.h] ( https://github.com/idealvin/coost/blob/master/include/co/co.h ) ,可以使用 co/ flag, co/ log 以及协程相关的所有特性。
96
+ 最简单的,可以直接包含 [ co/all.h] ( https://github.com/idealvin/coost/blob/master/include/co/all.h ) ,使用 coost 中的所有特性。如果担心影响编译速度,也可以只包含需要用到的头文件,如包含 [ co/co.h] ( https://github.com/idealvin/coost/blob/master/include/co/co.h ) ,可以使用 flag, log 以及协程相关的所有特性。
97
97
98
98
``` cpp
99
99
#include " co/all.h"
100
100
101
101
DEF_string (s, "nice", "");
102
102
103
103
int main(int argc, char** argv) {
104
- flag::init (argc, argv);
104
+ flag::parse (argc, argv);
105
105
LOG << FLG_s;
106
106
return 0;
107
107
}
108
108
```
109
109
110
- 上面是一个简单的例子,main 函数第一行用于解析命令行参数及配置文件。coost 中的部分组件用 flag 定义配置项,因此需要在 main 函数开头调用 `flag::init ()` 进行初始化。
110
+ 上面是一个简单的例子,main 函数第一行用于解析命令行参数及配置文件。coost 中的部分组件用 flag 定义配置项,因此需要在 main 函数开头调用 `flag::parse ()` 进行初始化。
111
111
112
112
用户也可以用宏 `DEF_main` 定义 main 函数:
113
113
@@ -122,7 +122,7 @@ DEF_main(argc, argv) {
122
122
}
123
123
```
124
124
125
- ` DEF_main ` 将 main 函数中的代码放到协程中运行,内部已经调用了 ` flag::init () ` ,用户无需手动调用。
125
+ ` DEF_main ` 将 main 函数中的代码放到协程中运行,内部已经调用了 ` flag::parse () ` ,用户无需手动调用。
126
126
127
127
128
128
@@ -131,7 +131,7 @@ DEF_main(argc, argv) {
131
131
132
132
### 内存分配器
133
133
134
- ptmalloc、jemalloc、tcmalloc 以及 mimalloc 等内存分配器,小内存释放后大概率不会归还给操作系统,这可能** 造成释放大量小内存后内存占用量却始终不降的疑似内存泄漏的现象** 。为解决此问题,coost 设计了一个专用的内存分配器(co/malloc) ,在兼顾性能的同时,会尽可能多的将释放的内存归还给系统,有利于降低程序的内存占用量,在实测中也取得了良好的效果。
134
+ ptmalloc、jemalloc、tcmalloc 以及 mimalloc 等内存分配器,小内存释放后大概率不会归还给操作系统,这可能** 造成释放大量小内存后内存占用量却始终不降的疑似内存泄漏的现象** 。为解决此问题,coost 设计了一个专用的内存分配器,在兼顾性能的同时,会尽可能多的将释放的内存归还给系统,有利于降低程序的内存占用量,在实测中也取得了良好的效果。
135
135
136
136
[ co/test] ( https://github.com/idealvin/coost/blob/master/test/mem.cc ) 中提供了简单的测试代码,可以执行如下命令编译及运行:
137
137
@@ -150,7 +150,7 @@ xmake r mem -t 4 -s
150
150
151
151
表中数据为平均耗时,单位为纳秒(ns),linux 是在 Windows WSL 中运行的 ubuntu 系统,speedup 是 coost 内存分配器相对于系统内存分配器的性能提升倍数。
152
152
153
- 可以看到,** co::alloc 在 Linux 上比 ::malloc 提升了近 99 倍** ,这其中的一个重要原因是 ptmalloc 在多线程环境中锁竞争开销较大,而 co/malloc 在设计上尽可能避免锁的使用 ,小块内存的分配、释放不需要锁,跨线程释放时连自旋锁也不用。
153
+ 可以看到,** co::alloc 在 Linux 上比 ::malloc 提升了近 99 倍** ,这其中的一个重要原因是 ptmalloc 在多线程环境中锁竞争开销较大,而 coost 内存分配器在设计上尽可能避免锁的使用 ,小块内存的分配、释放不需要锁,跨线程释放时连自旋锁也不用。
154
154
155
155
156
156
@@ -172,7 +172,7 @@ xmake r mem -t 4 -s
172
172
| 4 | 0.206712 | 4.764238 | 0.316607 | 0.743227 | 23.0/2.3 |
173
173
| 8 | 0.302088 | 3.963644 | 0.406025 | 1.417387 | 13.1/3.5 |
174
174
175
- 上表是分别[ 用 1、2、4、8 个线程打印 100 万条日志] ( https://github.com/idealvin/coost/tree/benchmark ) 的耗时,单位为秒,speedup 是 co/ log 在 linux、windows 平台相对于 spdlog 的性能提升倍数。
175
+ 上表是分别[ 用 1、2、4、8 个线程打印 100 万条日志] ( https://github.com/idealvin/coost/tree/benchmark ) 的耗时,单位为秒,speedup 是 co. log 在 linux、windows 平台相对于 spdlog 的性能提升倍数。
176
176
177
177
178
178
@@ -184,7 +184,7 @@ xmake r mem -t 4 -s
184
184
| mac | 783 | 1097 | 1289 | 1658 | 1.6/1.5 |
185
185
| linux | 468 | 764 | 1359 | 1070 | 2.9/1.4 |
186
186
187
- 上表是将 [ twitter.json] ( https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json ) 最小化后测得的 stringify 及 parse 的平均耗时,单位为微秒(us),speedup 是 co/ json 在 stringify、parse 方面相对于 rapidjson 的性能提升倍数。
187
+ 上表是将 [ twitter.json] ( https://raw.githubusercontent.com/simdjson/simdjson/master/jsonexamples/twitter.json ) 最小化后测得的 stringify 及 parse 的平均耗时,单位为微秒(us),speedup 是 co. json 在 stringify、parse 方面相对于 rapidjson 的性能提升倍数。
188
188
189
189
190
190
@@ -193,7 +193,7 @@ xmake r mem -t 4 -s
193
193
194
194
### 面向玄学编程
195
195
196
- [ co/god.h] ( https://github.com/idealvin/coost/blob/master/include/co/god.h ) 提供模板相关的一些功能。模板用到深处,代码深奥难懂 ,有些 C++ 程序员称之为面向玄学编程。
196
+ [ co/god.h] ( https://github.com/idealvin/coost/blob/master/include/co/god.h ) 提供模板相关的一些功能。模板用到深处有点玄 ,有些 C++ 程序员称之为面向玄学编程。
197
197
198
198
``` cpp
199
199
#include " co/god.h"
@@ -223,7 +223,7 @@ DEF_uint32(u, 0, "xxx");
223
223
DEF_string(s, "", "xx");
224
224
225
225
int main(int argc, char** argv) {
226
- flag::init (argc, argv);
226
+ flag::parse (argc, argv);
227
227
COUT << "x: " << FLG_x;
228
228
COUT << "y: " << FLG_y;
229
229
COUT << "debug: " << FLG_debug;
@@ -259,7 +259,7 @@ log 支持两种类型的日志:一种是 level log,分为 debug, info, warn
259
259
#include " co/log.h"
260
260
261
261
int main (int argc, char** argv) {
262
- flag::init (argc, argv);
262
+ flag::parse (argc, argv);
263
263
264
264
TLOG("xx") << "s" << 23; // topic log
265
265
DLOG << "hello " << 23; // debug
@@ -305,14 +305,14 @@ DEF_test(os) {
305
305
} // namespace test
306
306
```
307
307
308
- 上面是一个简单的例子,` DEF_test ` 宏定义了一个测试单元,实际上就是一个函数(类中的方法) 。` DEF_case ` 宏定义了测试用例,每个测试用例实际上就是一个代码块。main 函数一般只需要下面几行:
308
+ 上面是一个简单的例子,` DEF_test ` 宏定义了一个测试单元,实际上就是一个函数。` DEF_case ` 宏定义了测试用例,每个测试用例实际上就是一个代码块。main 函数一般只需要下面几行:
309
309
310
310
``` cpp
311
311
#include " co/unitest.h"
312
312
313
313
int main (int argc, char** argv) {
314
- flag::init (argc, argv);
315
- unitest::run_all_tests ();
314
+ flag::parse (argc, argv);
315
+ unitest::run_tests ();
316
316
return 0;
317
317
}
318
318
```
@@ -325,6 +325,41 @@ xmake r unitest -os # 仅运行 os 单元中的测试用例
325
325
```
326
326
327
327
328
+ ### 基准测试
329
+
330
+ [ benchmark] ( ../../co/benchmark/ ) 是一个简单易用的基准测试框架。
331
+
332
+ ``` cpp
333
+ #include " co/benchmark.h"
334
+ #include " co/mem.h"
335
+
336
+ BM_group (malloc) {
337
+ void* p;
338
+
339
+ BM_add(::malloc)(
340
+ p = ::malloc(32);
341
+ );
342
+ BM_use(p);
343
+
344
+ BM_add(co::alloc)(
345
+ p = co::alloc(32);
346
+ );
347
+ BM_use(p);
348
+ }
349
+
350
+ int main(int argc, char** argv) {
351
+ flag::parse(argc, argv);
352
+ bm::run_benchmarks();
353
+ return 0;
354
+ }
355
+ ```
356
+
357
+ 上例中,`BM_group` 定义了一个测试组,`BM_add` 添加了两个需要进行比较的测试用例,`BM_use` 防止编译器将测试代码优化掉。
358
+
359
+ 基准测试结果以 markdown table 格式输出,如下所示:
360
+ 
361
+
362
+
328
363
329
364
### JSON
330
365
@@ -371,15 +406,15 @@ coost 实现了类似 golang 中 goroutine 的协程机制,它有如下特性
371
406
- 支持多线程调度,默认线程数为系统 CPU 核数。
372
407
- 共享栈,同一线程中的协程共用若干个栈(大小默认为 1MB),内存占用低。
373
408
- 各协程之间为平级关系,可以在任何地方(包括在协程中)创建新的协程。
374
- - 支持[ 协程同步事件] ( ../../co/coroutine/#协程同步事件coevent ) 、[ 协程锁] ( ../../co/coroutine/#协程锁comutex ) 、[ channel] ( ../../co/coroutine/#channelcochan ) 、[ waitgroup] ( ../../co/coroutine/#waitgroupcowaitgroup ) 等协程同步机制。
409
+ - 支持[ 协程同步事件] ( ../../co/concurrency/ coroutine/event/ ) 、[ 协程锁] ( ../../co/concurrency/ coroutine/mutex/ ) 、[ channel] ( ../../co/concurrency/ coroutine/chan/ ) 、[ waitgroup] ( ../../co/concurrency/ coroutine/wg/ ) 等协程同步机制。
375
410
376
411
``` cpp
377
412
#include " co/co.h"
378
413
379
414
int main (int argc, char** argv) {
380
- flag::init (argc, argv);
415
+ flag::parse (argc, argv);
381
416
382
- co::WaitGroup wg;
417
+ co::wait_group wg;
383
418
wg.add(2);
384
419
385
420
go([wg](){
@@ -397,16 +432,16 @@ int main(int argc, char** argv) {
397
432
}
398
433
```
399
434
400
- 上面的代码中,`go()` 创建的协程会均匀的分配到不同的调度线程中 。用户也可以自行控制协程的调度:
435
+ 上面的代码中,`go()` 创建的协程会根据默认策略分配到不同的调度线程中 。用户也可以自行控制协程的调度:
401
436
402
437
```cpp
403
438
// run f1 and f2 in the same scheduler
404
- auto s = co::next_scheduler ();
439
+ auto s = co::next_sched ();
405
440
s->go(f1);
406
441
s->go(f2);
407
442
408
443
// run f in all schedulers
409
- for (auto& s : co::schedulers ()) {
444
+ for (auto& s : co::scheds ()) {
410
445
s->go(f);
411
446
}
412
447
```
@@ -415,11 +450,10 @@ for (auto& s : co::schedulers()) {
415
450
416
451
### 网络编程
417
452
418
- coost 提供了一套基于协程的网络编程框架,大致可以分为三个部分 :
453
+ coost 提供了一套基于协程的网络编程框架:
419
454
420
- - ** [ 协程化的 socket API] ( ../../co/coroutine/#协程化的-socket-api ) ** ,形式上与系统 socket API 类似,熟悉 socket 编程的用户,可以轻松的用同步的方式写出高性能的网络程序。
455
+ - ** [ 协程化的 socket API] ( ../../co/net/sock/ ) ** ,形式上与系统 socket API 类似,熟悉 socket 编程的用户,可以轻松的用同步的方式写出高性能的网络程序。
421
456
- [ TCP] ( ../../co/net/tcp/ ) 、[ HTTP] ( ../../co/net/http/ ) 、[ RPC] ( ../../co/net/rpc/ ) 等高层网络编程组件,兼容 IPv6,同时支持 SSL,用起来比 socket API 更方便。
422
- - ** [ 系统 API hook] ( ../../co/coroutine/#%E7%B3%BB%E7%BB%9F-api-hook ) ** ,支持在协程中使用一般的三方网络库。
423
457
424
458
425
459
** RPC server**
@@ -430,7 +464,7 @@ coost 提供了一套基于协程的网络编程框架,大致可以分为三
430
464
#include " co/time.h"
431
465
432
466
int main (int argc, char** argv) {
433
- flag::init (argc, argv);
467
+ flag::parse (argc, argv);
434
468
435
469
rpc::Server()
436
470
.add_service(new xx::HelloWorldImpl)
@@ -457,7 +491,7 @@ curl http://127.0.0.1:7788/xx --request POST --data '{"api":"ping"}'
457
491
DEF_string (d, ".", "root dir"); // docroot for the web server
458
492
459
493
int main(int argc, char** argv) {
460
- flag::init (argc, argv);
494
+ flag::parse (argc, argv);
461
495
so::easy(FLG_d.c_str()); // mum never have to worry again
462
496
return 0;
463
497
}
0 commit comments