내 서버는 boost spawn echo server을 기반으로합니다.io_service-per-CPU를 사용하여 boost :: asio :: spawn을 수행하는 방법은 무엇입니까?
서버가 단일 코어 컴퓨터에서 제대로 실행되며 몇 달 동안 하나의 충돌이 발생하지 않습니다. 100 % CPU를 사용하는 경우에도 여전히 잘 작동합니다.
하지만 이제는 더 많은 클라이언트 요청을 처리해야합니다. 이제는 멀티 코어 시스템을 사용합니다. 이런 내가 여러 스레드에서 io_service
를 실행하는 모든 CPU를 사용하려면 :
#include <boost/asio/io_service.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/thread/thread.hpp>
#include <iostream>
#include <memory>
#include <thread>
using namespace std;
using boost::asio::ip::tcp;
class session : public std::enable_shared_from_this<session>{
public:
explicit session(tcp::socket socket)
: socket_(std::move(socket)),
timer_(socket_.get_io_service()),
strand_(socket_.get_io_service())
{}
void go()
{
auto self(shared_from_this());
boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield)
{
try {
char data[1024] = {'3'};
for(; ;) {
timer_.expires_from_now(std::chrono::seconds(10));
std::size_t n = socket_.async_read_some(boost::asio::buffer(data, sizeof(data)), yield);
// do something with data
// write back something
boost::asio::async_write(socket_, boost::asio::buffer(data, sizeof(data)), yield);
}
} catch(...) {
socket_.close();
timer_.cancel();
}
});
boost::asio::spawn(strand_, [this, self](boost::asio::yield_context yield)
{
while(socket_.is_open()) {
boost::system::error_code ignored_ec;
timer_.async_wait(yield[ignored_ec]);
if(timer_.expires_from_now() <= std::chrono::seconds(0))
socket_.close();
}
});
}
private:
tcp::socket socket_;
boost::asio::steady_timer timer_;
boost::asio::io_service::strand strand_;
};
int main(int argc, char* argv[]) {
try {
boost::asio::io_service io_service;
boost::asio::spawn(io_service, [&](boost::asio::yield_context yield)
{
tcp::acceptor acceptor(io_service,
#define PORT "7788"
tcp::endpoint(tcp::v4(), std::atoi(PORT)));
for(; ;) {
boost::system::error_code ec;
tcp::socket socket(io_service);
acceptor.async_accept(socket, yield[ec]);
if(!ec)
// std::make_shared<session>(std::move(socket))->go();
io_service.post(boost::bind(&session::go, std::make_shared<session>(std::move(socket))));
}
});
// ----------- this works fine on single-core machine ------------
{
// io_service.run();
}
// ----------- this crashes (with multi core) ----------
{
auto thread_count = std::thread::hardware_concurrency(); // for multi core
boost::thread_group threads;
for(auto i = 0; i < thread_count; ++i)
threads.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
threads.join_all();
}
} catch(std::exception& e) {
std::cerr << "Exception: " << e.what() << "\n";
}
return 0;
}
코드는 싱글 코어 maching에 잘 작동하지만 2 코어/4 코어/8 코어 시스템의 모든 시간을 충돌
. 크래시 덤프에서 나는 내 코드와 관련된 것을 보지 못했다. boost :: spawn과 무작위로 명명 된 람다에 관한 것이다.
그래서 이것을 시도하고 싶습니다. CPU 당 io_service
을 실행하십시오.
void server::start_accept()
{
new_connection_.reset(new connection(
io_service_pool_.get_io_service(), request_handler_));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&server::handle_accept, this,
boost::asio::placeholders::error));
}
void server::handle_accept(const boost::system::error_code& e)
{
if (!e)
{
new_connection_->start();
}
start_accept();
}
io_service_pool_.get_io_service()
무작위로 픽업 io_service
,하지만 내 코드는 임의 io_service
와 spawn
boost::asio::spawn(io_service, ...
방법 spawn
사용을?
여러 개의 스레드에서 실행되는 하나의'io_service'가 있어야한다고 생각합니다. 스레드 당'io_service'를 가지고 있다면 왜'strand'를 가질 수 있습니까? –
부스트의 예제에서 코드를 복사했는데 실제로'spawn'을 이해하지 못했습니다.'strand '함수를 사용하여'go' 함수에서 두 개의'spawn'이 순서대로 실행되는지 확인합니다. – aj3423
Strand는 함수가 동시에 실행되지 않도록 io_service 대기열의 함수 래퍼입니다. 비 차단 뮤텍스와 비슷합니다. io_service와 strand에 대해 조금 읽으십시오. 이 충고에 대해 저에게 감사드립니다. –