看看我设计的网络组件
早就怀疑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,实现百万甚至千万并发,嘿嘿嘿~~~~~~~~~~
