i007.cc

i007.cc

优先队列-降维打击

看看我设计的网络组件

早就怀疑asio的性能有问题,目前初步测下来性能瓶颈在于asio的消息队列,ping/pong消息测试数据表明,使用asio消息队列的服务器qps无法超过10万,但是我自己写的消息队列能轻松达到千兆网卡的pps上限(37万)。

上面这些话不准确,这几天测试了下,asio消息队列性能还是不错的,使用asio的服务器qps在四个io线程的情况下可以超过50万,单线程能达到16万,之前是因为测试机的原因导致测试数据有误

 

最近把网络组件的接口重写了,废话少说,先放代码

客户端

#include "asyncio.h"

class MyConnection : public asyncio::Protocol, std::enable_shared_from_this<MyConnection> {
public:
    MyConnection() { m_rx_buffer.resize(1024); }
    virtual ~MyConnection() {}

    virtual std::pair<char*, size_t> GetRxBuffer() override {
        return std::make_pair(m_rx_buffer.data(), m_rx_buffer.size());
    }

    virtual void ConnectionMade(asyncio::TransportPtr transport) override {
        m_rx_buffer.clear();
        m_transport = transport;
        ASYNCIO_LOG_DEBUG("ConnectionMade");

        std::string msg("hello,world!");
        Send(msg.data(), msg.size());
    }

    virtual void ConnectionLost(asyncio::TransportPtr transport, int err_code) override {
        m_transport = nullptr;
        ASYNCIO_LOG_DEBUG("ConnectionLost, ec:%d", err_code);
    }

    virtual void DataReceived(size_t len) override {

        //
        // 没有使用解码器,这里会有黏包问题
        // 如果要解决黏包问题需要使用解码器
        //
        ASYNCIO_LOG_DEBUG("DataReceived %lld byte(s): %s", len, m_rx_buffer.data());
    }

    virtual void EofReceived() override {
        ASYNCIO_LOG_DEBUG("EofReceived");
        m_transport->WriteEof();
    }

    size_t Send(const char* data, size_t len) {
        if (m_transport == nullptr)
            return 0;
        ASYNCIO_LOG_DEBUG("Send %lld byte(s): %s", len, data);
        m_transport->Write(data, len);
        return len;
    }

    void Close() {
        if (m_transport != nullptr) {
            m_transport->Close(asyncio::EC_SHUT_DOWN);
        }
    }

private:
    asyncio::TransportPtr m_transport;

    //
    // ProActor模式使用预先分配的缓冲区接收数据
    // 如果缓冲区不够,会分成多次接收
    //
    std::string m_rx_buffer;
};

class MyConnectionFactory : public asyncio::ProtocolFactory {
public:
    virtual ~MyConnectionFactory() {}
    virtual asyncio::ProtocolPtr CreateProtocol() override { return std::make_shared<MyConnection>(); }
};

int main() {
    asyncio::EventLoop my_event_loop;
    MyConnectionFactory my_conn_factory;
    my_event_loop.CreateConnection(my_conn_factory, "127.0.0.1", 9000);
    my_event_loop.RunForever();
    return 0;
}

 

 

服务器:

#include "asyncio.h"

class MySession : public asyncio::Protocol, std::enable_shared_from_this<MySession> {
public:
    MySession() { m_rx_buffer.resize(1024); }
    virtual ~MySession() {}

    virtual std::pair<char*, size_t> GetRxBuffer() override {
        return std::make_pair(m_rx_buffer.data(), m_rx_buffer.size());
    }

    virtual void ConnectionMade(asyncio::TransportPtr transport) override {
        m_rx_buffer.clear();
        m_transport = transport;
        ASYNCIO_LOG_DEBUG("ConnectionMade");
    }

    virtual void ConnectionLost(asyncio::TransportPtr transport, int err_code) override {
        m_transport = nullptr;
        ASYNCIO_LOG_DEBUG("ConnectionLost, ec:%d", err_code);
    }

    virtual void DataReceived(size_t len) override {

        //
        // 没有使用解码器,这里会有黏包问题,如果要解决黏包问题需要使用解码器
        //
        ASYNCIO_LOG_DEBUG("DataReceived %lld byte(s): %s", len, m_rx_buffer.data());

        std::string ack("Your words: ");
        ack.append(m_rx_buffer.data(), len);
        Send(ack.data(), ack.size());
    }

    virtual void EofReceived() override {
        ASYNCIO_LOG_DEBUG("EofReceived");
        m_transport->WriteEof();
    }

    size_t Send(const char* data, size_t len) {
        if (m_transport == nullptr) {
            return 0;
        }

        ASYNCIO_LOG_DEBUG("Send %lld byte(s): %s", len, data);
        m_transport->Write(data, len);
        return len;
    }

    void Close() {
        if (m_transport != nullptr) {
            m_transport->Close(asyncio::EC_KICK);
        }
    }

private:
    asyncio::TransportPtr m_transport;

    //
    // ProActor模式使用预先分配的缓冲区接收数据
    // 如果缓冲区不够,会分成多次接收
    //
    std::string m_rx_buffer;
};

class MySessionFactory : public asyncio::ProtocolFactory {
public:
    virtual ~MySessionFactory() {}
    virtual asyncio::ProtocolPtr CreateProtocol() override { return std::make_shared<MySession>(); }
};

int main() {
    int port = 9000;
    asyncio::EventLoop my_event_loop;
    MySessionFactory my_session_factory;
    auto listener = my_event_loop.CreateServer(my_session_factory, port);
    if (listener == nullptr) {
        ASYNCIO_LOG_ERROR("listen on %d failed", port);
        return 0;
    }

    ASYNCIO_LOG_INFO("listen on %d suc", port);
    my_event_loop.RunForever();
    return 0;
}

 

仓库地址:https://github.com/williamxin/asyncio

 

用这套网络组件写出来的程序已经完全看不到asio的影子了,整个系统会很干净。

要说我的目标,先把接口设计好了,先用着asio,然后逐步替换掉asio,实现百万甚至千万并发,嘿嘿嘿~~~~~~~~~~

发表回复