2016-03-10 1 views
0

Mon serveur tcp est basé sur ce boost coroutine server example.boost coroutine avec multi-core

Il es beaucoup de demande par seconde, le serveur ont deux noyaux, mais un seul est utilisé, il ne sort jamais plus de cpu 50% dans l'onglet performance de gestionnaire de tâches, et un noyau est toujours libre: enter image description here

Comment faire pour boost :: coroutine travail avec plusieurs noyaux?

Je suis venu une solution qui ajoute un 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; 
} 

Maintenant, le code semble courir avec cpu 100% après telnet 127.0.0.1 80 deux fois.

Mais comment utiliser la coroutine avec les multi-cœurs?

+0

Pouvez-vous poster une image de votre gestionnaire de tâches? Êtes-vous sûr qu'il n'utilise qu'un seul noyau? – Ali786

+0

@ ali786, poste mis à jour avec l'image. Coroutine est mono-thread, donc je suppose qu'un thread ne peut pas fonctionner sur plusieurs cœurs. – aj3423

+0

Oui, l'idée même des coroutines est qu'un seul thread système est capable d'exécuter plusieurs fonctions _concurrently_. Si vous voulez exécuter vos fonctions _simultaneously_ (pour occuper les deux cœurs), vous aurez besoin d'au moins 2 threads système. – rodrigo

Répondre

2

Un thread s'exécute sur un seul noyau, vous devez donc créer plusieurs threads avec des coroutines séparées. asio contient déjà un certain soutien de la gestion des threads, vous avez donc la plupart du temps pour commencer des discussions:

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; 
} 

L'important est de courir io_service.run() sur chaque fil. Puis, après .async_accept, vous pouvez appeler

io_service.post(&session::go, std::make_shared<session>(std::move(socket))) 

pour exécuter la session quelque part dans la piscine.