2016-03-10 6 views
0

Мой tcp-сервер основан на этом boost coroutine server example.boost coroutine с несколькими ядрами

Там уже много запросов в секунду, сервер имеет два ядра, но используется только одна, она никогда не переходит, чем 50% CPU в закладке производительности менеджер задач, и одно ядро ​​всегда бесплатно: enter image description here

Как сделать 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 после телнет 127.0.0.1 80 дважды.

Но какой общий способ использования сопрограммы с несколькими ядрами?

+0

Можете ли вы разместить изображение своего диспетчера задач? вы уверены, что использует только одно ядро? – Ali786

+0

@ ali786, сообщение обновлено с изображением. Coroutine является однопоточным, поэтому я думаю, что один поток не может работать на нескольких ядрах. – aj3423

+0

Да, сама идея сопрограмм заключается в том, что только один системный поток способен запускать несколько функций _concurrently_. Если вы хотите запускать свои функции _simultaneously_ (чтобы занять оба ядра), вам понадобится как минимум 2 системных потока. – rodrigo

ответ

2

Один поток работает только на одном ядре, поэтому вам нужно создать несколько потоков с отдельными сопрограммами. 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))) 

запустить сессию где-то в бассейне.

Смежные вопросы