Английский | 简体中文
Небольшая библиотека для ускорения разработки на C++11.
Coost — элегантная и эффективная кроссплатформенная базовая библиотека C++. Её цель — создать инструмент, который сделает разработку на C++ простой и приятной.
Coost, или co для краткости, похожа на boost, но более легковесна. Статическая библиотека, созданная на Linux или Mac, имеет размер всего около 1 МБ. Тем не менее она предоставляет достаточно мощные функции:
Парсер командной строки и конфигурационного файла (flag) | Библиотека высокопроизводительного логирования (log) |
Фреймворк модульного тестирования | Фреймворк бенчмаркинга |
Go-style сопрограммы | Сопрограммная сетевая библиотека |
JSON RPC фреймворк | Атомарные операции (atomic) |
| Эффективный поток (fastream) | Эффективная строка (fastring) | | Строковые утилиты (str) | Библиотека времени (time) | | Библиотека потоков (thread) | Планировщик задач с таймером |
| Ориентированное на классы программирование | Эффективная библиотека JSON | | Хеш-библиотека | Библиотека путей | | Файловые утилиты (fs) | Системные операции (os) | | Быстрый распределитель памяти |
Coost нуждается в вашей помощи. Если вы используете её или она вам нравится, вы можете стать спонсором. Большое спасибо!
— Github Sponsors
— A cup of coffee
co/god.h предоставляет некоторые функции, основанные на шаблонах.
#include "co/god.h"
void f() {
god::bless_no_bugs();
god::is_same<T, int, bool>(); // T is int or bool?
}
Flag — это парсер командной строки и файла конфигурации. Он похож на gflags, но более мощный:
#include "co/flag.h"
#include "co/cout.h"
DEF_bool(x, false, "x");
DEF_bool(y, true, "y");
DEF_bool(debug, false, "dbg", d);
DEF_uint32(u, 0, "xxx");
DEF_string(s, "", "xx");
int main(int argc, char** argv) {
flag::parse(argc, argv);
cout << "x: " << FLG_x << '\n';
cout << "y: " << FLG_y << '\n';
cout << "debug: " << FLG_debug << '\n';
cout << "u: " << FLG_u << '\n';
cout << FLG_s << "|" << FLG_s.size() << '\n';
return 0;
}
В приведённом выше примере макросы, начинающиеся с DEF_, определяют 4 флага. Каждый флаг соответствует глобальной переменной, имя которой FLG_ плюс имя флага. Флаг debug имеет псевдоним d. После сборки приведённый выше код можно запустить следующим образом:
./xx # Run with default configs
./xx -x -s good # x -> true, s -> "good"
./xx -debug # debug -> true
./xx -xd # x -> true, debug -> true
./xx -u 8k ### u -> 8192
./xx -mkconf # Автоматически создать конфигурационный файл: xx.conf
./xx xx.conf # запустить с конфигурационным файлом
./xx -conf xx.conf # То же, что и выше
log — это высокопроизводительная библиотека журналов, некоторые компоненты в coost используют её для печати журналов.
log поддерживает два типа журналов: один — журнал уровня, который делится на 5 уровней: отладка, информация, предупреждение, ошибка и фатальный, печать фатального журнала приведёт к завершению программы; другой — тематический журнал, журналы группируются по темам, а журналы разных тем записываются в разные файлы.
#include "co/log.h"
int main(int argc, char** argv) {
flag::parse(argc, argv);
TLOG("xx") << "s" << 23; // тематический журнал
DLOG << "hello " << 23; // отладка
LOG << "hello " << 23; // информация
WLOG << "hello " << 23; // предупреждение
ELOG << "hello " << 23; // ошибка
FLOG << "hello " << 23; // фатальный
return 0;
}
co/log также предоставляет ряд макросов CHECK
, которые являются улучшенной версией assert
, и они не будут очищены в режиме отладки.
void* p = malloc(32);
CHECK(p != NULL) << "malloc failed..";
CHECK_NE(p, NULL) << "malloc failed..";
log работает очень быстро, вот некоторые результаты тестов:
платформа | glog | co/log | speedup |
---|---|---|---|
win2012 HHD | 1,6 МБ/с | 180 МБ/с | 112,5 |
win10 SSD | 3,7 МБ/с | 560 МБ/с | 151,3 |
mac SSD | 17 МБ/с | 450 МБ/с | 26,4 |
linux SSD | 54 МБ/с | 1023 МБ/с | 18,9 |
Выше приведена скорость записи co/log и glog (один поток, 1 миллион журналов). Видно, что co/log почти на два порядка быстрее, чем glog.
потоки | linux co/log | linux spdlog | win co/log | win spdlog | speedup |
---|---|---|---|---|---|
1 | 0,087235 | 2,076172 | 0,117704 | 0,461156 | 23,8/3,9 |
2 | 0,183160 | 3,729386 | 0,158122 | 0,511769 | 20,3/3,2 |
4 | 0,206712 | 4,764238 | 0,316607 | 0,743227 | 23,0/2,3 |
8 | 0,302088 | 3,963644 | 0,406025 | 1,417387 | 13,1/3,5 |
Приведённое выше время печати 1 миллиона журналов с 1, 2, 4 и 8 потоками, в секундах. Speedup — это улучшение производительности co/log по сравнению с spdlog на платформах Linux и Windows.
unitest — это простой и удобный в использовании фреймворк модульного тестирования. Многие компоненты в coost используют его для написания кода модульных тестов, что гарантирует стабильность coost.
#include "co/unitest.h"
#include "co/os.h"
DEF_test(os) {
DEF_case(homedir) {
EXPECT_NE(os::homedir(), "");
}
DEF_case(cpunum) {
EXPECT_GT(os::cpunum(), 0);
}
}
int main(int argc, char** argv) {
flag::parse(argc, argv);
unitest::run_tests();
return 0;
}
Приведенный выше пример является простым примером. Макрос DEF_test
определяет тестовый модуль, который фактически является функцией (методом класса). Макрос DEF_case
определяет тестовые случаи, и каждый тестовый случай фактически представляет собой блок кода.
В каталоге unitest находится код модульных тестов в coost. Пользователи могут запускать unitest с помощью следующих команд:
xmake r unitest # Запустить все тестовые примеры
xmake r unitest -os # Запустить тестовые примеры в модуле os
В coost v3.0 Json предоставляет fluent API, что более удобно в использовании.
// {"a":23,"b":false,"s":"123","v":[1,2,3],"o":{"xx":0}}
co::Json x = {
{ "a", 23 },
{ "b", false },
{ "s", "123" },
{ "v", {1,2,3} },
{ "o", {
{"xx", 0}
}},
};
// equal to x
co::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**
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 |
The above is the average time of stringifying and parsing minimized twitter.json, in microseconds (us), speedup is the performance improvement of co/json compared to rapidjson.
coost has implemented a go-style coroutine, which has the following features:
#include "co/co.h"
int main(int argc, char** argv) {
flag::parse(argc, argv);
co::wait_group wg;
wg.add(2);
go([wg](){
LOG << "hello world";
wg.done();
});
go([wg](){
LOG << "hello again";
wg.done();
});
wg.wait();
return 0;
}
В приведённом выше коде сопрограммы, созданные с помощью go()
, будут распределены по различным планирующим потокам. Пользователи также могут самостоятельно контролировать планирование сопрограмм:
// запустить f1 и f2 в одном планировщике
auto s = co::next_sched();
s->go(f1);
s->go(f2);
// запустить f во всех планировщиках
for (auto& s : co::scheds()) {
s->go(f);
}
coost предоставляет основанную на сопрограммах структуру сетевого программирования:
Сервер RPC
#include "co/co.h"
#include "co/rpc.h"
#include "co/time.h"
int main(int argc, char** argv) {
flag::parse(argc, argv);
rpc::Server()
.add_service(new xx::HelloWorldImpl)
.start("127.0.0.1", 7788, "/xx");
for (;;) sleep::sec(80000);
return 0;
}
rpc::Server
также поддерживает протокол HTTP, вы можете использовать метод POST для вызова службы RPC:
curl http://127.0.0.1:7788/xx --request POST --data '{"api":"ping"}'
Статический веб-сервер
#include "co/flag.h"
#include "co/http.h"
DEF_string(d, ".", "root dir"); // docroot for the web server
int main(int argc, char** argv) {
flag::parse(argc, argv);
so::easy(FLG_d.c_str()); // mum never have to worry again
return 0;
}
HTTP-сервер
void cb(const http::Req& req, http::Res& res) {
if (req.is_method_get()) {
if (req.url() == "/hello") {
res.set_status(200);
res.set_body("hello world");
} else {
res.set_status(404);
}
} else {
res.set_status(405); // method not allowed
}
}
// http
http::Server().on_req(cb).start("0.0.0.0", 80);
// https
http::Server().on_req(cb).start(
"0.0.0.0", 443, "privkey.pem", "certificate.pem"
);
Клиент HTTP
void f() {
http::Client c("https://github.com");
c.get("/");
LOG << "response code: "<< c.status();
LOG << "body size: "<< c.body().size();
LOG << "Content-Length: "<< c.header("Content-Length");
LOG << c.header();
``` **Код композиции**
- include — заголовочные файлы coost.
- src — исходные файлы coost, собранные как libco.
- test — тестовый код, каждый файл .cc будет скомпилирован в отдельную тестовую программу.
- unitest — код модульного теста, каждый файл .cc соответствует отдельному тестовому блоку, и весь код будет скомпилирован в одну тестовую программу.
- gen — генератор кода для RPC-фреймворка.
**Сборка**
5.1. Необходимые компиляторы
Для сборки coost нужен компилятор, поддерживающий C++11:
* Linux: gcc 4.8+.
* Mac: clang 3.3+.
* Windows: vs2015+.
5.2. Сборка с помощью xmake
coost рекомендует использовать xmake в качестве инструмента сборки.
5.2.1 Быстрый старт
```sh
# Все команды выполняются в корневом каталоге coost (то же самое ниже)
xmake # по умолчанию сборка libco
xmake -a # сборка всех проектов (libco, gen, test, unitest)
5.2.2 Сборка разделяемой библиотеки
xmake f -k shared
xmake -v
5.2.3 Сборка с mingw
xmake f -p mingw
xmake -v
5.2.4 Включение функций HTTP/SSL
xmake f --with_libcurl=true --with_openssl=true
xmake -v
5.2.5 Установка libco
# По умолчанию устанавливаются файлы заголовков и libco.
xmake install -o pkg # упаковать связанные файлы в каталог pkg
xmake i -o pkg # то же, что и выше
xmake install -o /usr/local # установить в каталог /usr/local
5.2.6 Установка libco из xrepo
xrepo install -f "openssl=true,libcurl=true" coost
5.3. Сборка с cmake
izhengfan помог предоставить поддержку cmake, SpaceIm улучшил её и довёл до совершенства.
5.3.1 Сборка libco
mkdir build && cd build
cmake ..
make -j8
5.3.2 Сборка всех проектов
mkdir build && cd build
cmake .. -DBUILD_ALL=ON
make -j8
5.3.3 Включение функций HTTP/SSL
mkdir build && cd build
cmake .. -DWITH_LIBCURL=ON -DWITH_OPENSSL=ON
make -j8
5.3.4 Сборка разделяемой библиотеки
cmake .. -DBUILD_SHARED_LIBS=ON
make -j8
5.3.5 Поиск coost в Cmake
find_package(coost REQUIRED CONFIG)
target_link_libraries(userTarget coost::co)
5.3.6 vcpkg & conan
vcpkg install coost:x64-windows
# Поддержка HTTP & SSL
vcpkg install coost[libcurl,openssl]:x64-windows
conan install coost
Лицензия MIT. coost содержит коды из некоторых других проектов, которые имеют собственные лицензии, подробности см. в LICENSE.md.
— Код co/context взят из tbox от ruki, особая благодарность! — Ранние английские документы co переведены Leedehai и daidai21, особая благодарность! — ruki помог улучшить сценарии сборки xmake, спасибо! — izhengfan предоставил сценарии сборки cmake, большое спасибо! — SpaceIm улучшил сценарии сборки cmake и предоставил поддержку find_package. Действительно большая помощь, спасибо!
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )