使用多核提升协程
boost coroutine with multi core
我的tcp服务器是基于这个boost coroutine server example.
每秒有很多请求,服务器有两个内核但只使用一个,在任务管理器的性能选项卡中它永远不会超过 50% cpu,并且一个内核始终空闲:
如何使 boost::coroutine 与多核一起工作?
我刚刚想出了一个解决方案,添加了 thread_pool:
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include "thread_pool.h"
#include <iostream>
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this<session>
{
public:
explicit session(tcp::socket socket) { }
void go()
{
std::cout << "dead loop" << std::endl;
while(1) {} // causes 100% cpu usage, just for test
}
};
int main()
{
try
{
boost::asio::io_service io_service;
thread_pool pool(1000); // maximum 1000 threads
boost::asio::spawn(io_service,
[&](boost::asio::yield_context yield)
{
tcp::acceptor acceptor(io_service,
tcp::endpoint(tcp::v4(), 80));
for (;;)
{
boost::system::error_code ec;
tcp::socket socket(io_service);
acceptor.async_accept(socket, yield[ec]);
if (!ec) {
pool.enqueue([&] { // add this to pool
std::make_shared<session>(std::move(socket))->go();
});
}
}
});
io_service.run();
}
catch (std::exception& e)
{}
return 0;
}
现在代码似乎 运行 100% cpu 在 telnet 127.0.0.1 80 两次之后。
但是多核协程的常用方式是什么?
一个线程在一个核心上只有 运行 个,因此您必须使用单独的协程创建多个线程。 asio 已经包含了一些线程管理支持,所以你大多必须启动一些线程:
int main() {
std::vector<std::thread> pool;
try {
boost::asio::io_service io_service;
{
for(auto threadCount = std::thread::hardware_concurrency();
threadCount;--threadCount)
pool.emplace_back([](auto io_s) {return io_s->run(); }, &io_service);
}
// Normal code
} catch(std::exception &e) {}
for(auto &thread : pool)
thread.join();
return 0;
}
重要的是在每个线程上 运行 io_service.run()
。然后,在.async_accept
之后,你可以调用
io_service.post(&session::go, std::make_shared<session>(std::move(socket)))
到运行 池中某处的会话。
我的tcp服务器是基于这个boost coroutine server example.
每秒有很多请求,服务器有两个内核但只使用一个,在任务管理器的性能选项卡中它永远不会超过 50% cpu,并且一个内核始终空闲:
如何使 boost::coroutine 与多核一起工作?
我刚刚想出了一个解决方案,添加了 thread_pool:
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include "thread_pool.h"
#include <iostream>
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this<session>
{
public:
explicit session(tcp::socket socket) { }
void go()
{
std::cout << "dead loop" << std::endl;
while(1) {} // causes 100% cpu usage, just for test
}
};
int main()
{
try
{
boost::asio::io_service io_service;
thread_pool pool(1000); // maximum 1000 threads
boost::asio::spawn(io_service,
[&](boost::asio::yield_context yield)
{
tcp::acceptor acceptor(io_service,
tcp::endpoint(tcp::v4(), 80));
for (;;)
{
boost::system::error_code ec;
tcp::socket socket(io_service);
acceptor.async_accept(socket, yield[ec]);
if (!ec) {
pool.enqueue([&] { // add this to pool
std::make_shared<session>(std::move(socket))->go();
});
}
}
});
io_service.run();
}
catch (std::exception& e)
{}
return 0;
}
现在代码似乎 运行 100% cpu 在 telnet 127.0.0.1 80 两次之后。
但是多核协程的常用方式是什么?
一个线程在一个核心上只有 运行 个,因此您必须使用单独的协程创建多个线程。 asio 已经包含了一些线程管理支持,所以你大多必须启动一些线程:
int main() {
std::vector<std::thread> pool;
try {
boost::asio::io_service io_service;
{
for(auto threadCount = std::thread::hardware_concurrency();
threadCount;--threadCount)
pool.emplace_back([](auto io_s) {return io_s->run(); }, &io_service);
}
// Normal code
} catch(std::exception &e) {}
for(auto &thread : pool)
thread.join();
return 0;
}
重要的是在每个线程上 运行 io_service.run()
。然后,在.async_accept
之后,你可以调用
io_service.post(&session::go, std::make_shared<session>(std::move(socket)))
到运行 池中某处的会话。