Skip to content
/ Lane Public

C++网络协程库:实现gmp协程调度,通过hook重写网络API,性能高效,本地测试表现已超过golang原生net/http

Notifications You must be signed in to change notification settings

Oncelane/Lane

Repository files navigation

Lane

本项目基于 sylar 和 lunar 的协程服务器框架,以体验优化技术为主要目标,重点优化协程模块

已实现

  • gmp 调度,worksteal 调度模式
  • boost.fcontext 协程切换
  • 协程互斥锁
  • 协程信号量
  • channel(无缓冲/有缓冲)
  • waitGroup
  • 协程池

协程切换压测

一千万次协程切换耗时

项目 耗时 切换性能
lane 876 ms 87 ns
golang 662 ms 66 ns
lunar/sylar 5904.5 ms 590 ns
switch[1000]: lane: 10000000 switches in 876.759 ms, 11405639 switches per second
switch[1000]: go: 10000000 switches in 662 ms, 15105740 switches per second
switch[1000]: lunar: 10000000 switches in 5904.5 ms, 1693624 switches per second

服务器压测

项目 QPS
lane 8.71W
golang 7.00W

测试页面:

oncelane@ServerTest:~/workspace/Lane$ curl -i -X GET http://127.0.0.1:8020/
HTTP/1.1 404 Not Found
Content-Type: text/html
Server: lane/1.0.0
connection: close
content-length: 135

<html><head><title>404 Not Found</title></head><body><center><h1>404 Not Found</h1></center><hr><center>lane/1.0</center></body></html>

压测相同内容,均为 135 bytes:

压测

lane 压测页面内容不变为 135 bytes,golang 压测页面内容减少,为 36 bytes

压测

在另一配置较差笔记本上的压测数据:

项目 QPS
lane O0 编译 3.39W
golang 3.97W
lane O2 编译 5.96W

使用

  1. 创建使用两个线程的协程调度器iom
  2. 简单的使用co开启协程
  3. defer注册延迟执行函数,此函数会在协程 panic 或 return 后执行
  4. panic发起一个中断,中止协程运行
  5. 在 defer 代码块中使用recovery处理错误并恢复协程
void TestMain() {
    co[]() {

        defer[]() {
            info() << "defer1";
        };
        defer[]() {
            info() << "defer2";
        };
        defer[]() {
            info() << "defer3";
            auto e = recovery();
            if (e.has_value()) {
                info() << "recovery this error:" << e.value().what();
            }
        };

        info() << "throw panic";

        panic("panic");

        info() << "safe return";
    };
}


int main() {
    lane::IOManager iom(2, "hello", false);
    iom.addTask(TestMain);
}

执行结果

tests/.cc:26            throw panic
tests/test_defer.cc:19  defer3
tests/test_defer.cc:22  recovery this error:std::exception
tests/test_defer.cc:30  safe return
tests/test_defer.cc:16  defer2
tests/test_defer.cc:13  defer1

缺陷是 e.what()丢失了原始值,可以通过模板解决,后续再弄

协程同步方法

waitGroup

waitGroup与 golang 的 sync.WaitGroup 语义一致 方法: add(int) done() wait()

示例代码

void TestWaitGroup() {
    info() << "start runing";
    auto wait = new lane::WaitGroup;

    for (int i = 0; i < 5; ++i) {
        wait->add(1);
        co[=]() {
            defer[&]() {
                wait->done();
            };
            sleep(1);
            info() << " fast finish";
        };
    }
    wait->add(1);
    co[=]() {
        defer[&]() {
            wait->done();
        };
        sleep(2);
        info() << " slow finish";
    };

    wait->wait();
    info() << "end";
}

void TestMain() {
    lane::IOManager iom(2, "waitgroup", false);
    iom.addTask(TestWaitGroup);
}

输出

2024-10-09 16:35:26     205332  waitgroup0      3       [INFO]  [root]  tests/test_waitGroup.cc:12      start runing
2024-10-09 16:35:27     205333  waitgroup1      9       [INFO]  [root]  tests/test_waitGroup.cc:22       fast finish
2024-10-09 16:35:27     205333  waitgroup1      8       [INFO]  [root]  tests/test_waitGroup.cc:22       fast finish
2024-10-09 16:35:27     205333  waitgroup1      7       [INFO]  [root]  tests/test_waitGroup.cc:22       fast finish
2024-10-09 16:35:27     205332  waitgroup0      6       [INFO]  [root]  tests/test_waitGroup.cc:22       fast finish
2024-10-09 16:35:27     205333  waitgroup1      10      [INFO]  [root]  tests/test_waitGroup.cc:22       fast finish
2024-10-09 16:35:28     205332  waitgroup0      11      [INFO]  [root]  tests/test_waitGroup.cc:31       slow finish
2024-10-09 16:35:28     205332  waitgroup0      3       [INFO]  [root]  tests/test_waitGroup.cc:35      end

Channel

channel语义与 golang 的 channel 保持一致

示例代码: 经典两个协程交替打印数字和字母

void TestPrint() {
    auto wg = new lane::WaitGroup;

    // 创建两个 无缓冲channel,分别用于控制字母和数字的打印
    auto letters = lane::Channel<bool>(0);
    auto numbers = lane::Channel<bool>(0);

    // 字母打印协程
    wg->add(1);
    co[&]() {
        defer[&]() {
            wg->done();
        };
        for (char ch = 'A'; ch <= 'C'; ch++) {
            info() << ch;  // 打印字母
            letters.input(true);  // 发送信号,通知数字打印协程可以打印
            numbers.output();  // 等待数字打印协程的信号
        }
        letters.close();  // 关闭字母 channel
    };


    // 数字打印协程
    wg->add(1);
    co[&]() {
        defer[&]() {
            wg->done();
        };
        for (int num = 1; num <= 3; num++) {
            letters.output();  // 等待字母打印协程的信号
            info() << num;     // 打印数字
            numbers.input(true);
        }
        numbers.close();  // 关闭数字 channel
    };

    wg->wait();  // 等待所有协程完成
}


int main() {
    lane::IOManager iom(2, "channel", false);
    iom.addTask(TestPrint);
    return 0;
}

输出

[INFO]  [root]  tests/test_channel.cc:84        A
[INFO]  [root]  tests/test_channel.cc:100       1
[INFO]  [root]  tests/test_channel.cc:84        B
[INFO]  [root]  tests/test_channel.cc:100       2
[INFO]  [root]  tests/test_channel.cc:84        C
[INFO]  [root]  tests/test_channel.cc:100       3

项目依赖

# boost
sudo apt install libboost-all-dev

# json
sudo apt install libjsoncpp-dev

# ragel
sudo apt install ragel

# yaml-cpp.git
git clone https://github.com/jbeder/yaml-cpp.git
cd yaml-cpp
mkdir build
cd build
cmake ..
make -j8
sudo make install

项目启动

  1. 拉取仓库
git clone https://github.com/Oncelane/Lane.git
cd Lane
  1. 编译
mkdir build
cd build
cmake ..
make -j8
  1. 运行、压测
webbench 下载

#1.1 安装依赖 exuberant-ctags
sudo apt-get install exuberant-ctags
#1.2 下载源码并安装
wget http://blog.s135.com/soft/linux/webbench/webbench-1.5.tar.gz
tar zxvf webbench-1.5.tar.gz
cd webbench-1.5
make && sudo make install
# 如果出现 <rpc/types.h> 头文件错误
# 打开 webbench.c 编辑
# vim webbench.c
# 修改头文件#include <rpc/types.h> 为#include <sys/types.h>
../bin/test_httpserver
webbench -c 1000 -t 30 http://127.0.0.1:8020//
  1. valgrind

安装

sudo apt-get install valgrind

运行

../bin/test_httpserver

压测

 webbench -c 8000 -t 30 http://127.0.0.1:8020/

开发环境

https://blog.csdn.net/m0_72743841/article/details/139465617

clangd-17

About

C++网络协程库:实现gmp协程调度,通过hook重写网络API,性能高效,本地测试表现已超过golang原生net/http

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published