简体   繁体   中英

boost coroutine with multi core

My tcp server is based on this boost coroutine server example .

There're lots of request per second, the server have two cores but only one is used, it never goes over than 50% cpu in task manager's performance tab, and one core is always free: 在此处输入图片说明

How to make boost::coroutine work with multiple cores?

I just came up a solution that add a 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;
}

Now the code seems running with 100% cpu after telnet 127.0.0.1 80 twice.

But what's the common way of using coroutine with multi cores?

One thread only runs on one core, so you have to create multiple threads with separate coroutines. asio already contains some thread management support, so you mostly have to start some threads:

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

The important thing is to run io_service.run() on every thread. Then, after .async_accept , you can call

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

to run the session somewhere in the pool.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM