Commit 199f45de authored by Mathieu Stefani's avatar Mathieu Stefani

Added workers CPU pinning

parent bddf6aae
...@@ -454,7 +454,14 @@ Endpoint::serve() ...@@ -454,7 +454,14 @@ Endpoint::serve()
if (!handler_) if (!handler_)
throw std::runtime_error("Must call setHandler() prior to serve()"); throw std::runtime_error("Must call setHandler() prior to serve()");
listener.init(24, Tcp::Options::InstallSignalHandler); listener.init(4, Tcp::Options::InstallSignalHandler);
#if 1
listener.pinWorker(0, CpuSet { 0 } );
listener.pinWorker(1, CpuSet { 1 } );
listener.pinWorker(2, CpuSet { 2 } );
listener.pinWorker(3, CpuSet { 3 } );
#endif
listener.setHandler(handler_); listener.setHandler(handler_);
if (listener.bind()) { if (listener.bind()) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netdb.h> #include <netdb.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <pthread.h>
#include <signal.h> #include <signal.h>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
...@@ -98,6 +99,23 @@ IoWorker::start(const std::shared_ptr<Handler>& handler, Flags<Options> options) ...@@ -98,6 +99,23 @@ IoWorker::start(const std::shared_ptr<Handler>& handler, Flags<Options> options)
thread.reset(new std::thread([this]() { thread.reset(new std::thread([this]() {
this->run(); this->run();
})); }));
if (pins.count() > 0) {
auto cpuset = pins.toPosix();
auto handle = thread->native_handle();
pthread_setaffinity_np(handle, sizeof (cpuset), &cpuset);
}
}
void
IoWorker::pin(const CpuSet& set) {
pins = set;
if (thread) {
auto cpuset = set.toPosix();
auto handle = thread->native_handle();
pthread_setaffinity_np(handle, sizeof (cpuset), &cpuset);
}
} }
std::shared_ptr<Peer> std::shared_ptr<Peer>
...@@ -182,6 +200,9 @@ IoWorker::handleNewPeer(const std::shared_ptr<Peer>& peer) ...@@ -182,6 +200,9 @@ IoWorker::handleNewPeer(const std::shared_ptr<Peer>& peer)
void void
IoWorker::run() { IoWorker::run() {
if (pins.count() > 0) {
}
mailbox.bind(poller); mailbox.bind(poller);
std::chrono::milliseconds timeout(-1); std::chrono::milliseconds timeout(-1);
...@@ -271,6 +292,20 @@ Listener::setHandler(const std::shared_ptr<Handler>& handler) ...@@ -271,6 +292,20 @@ Listener::setHandler(const std::shared_ptr<Handler>& handler)
handler_ = handler; handler_ = handler;
} }
void
Listener::pinWorker(size_t worker, const CpuSet& set)
{
if (ioGroup.empty()) {
throw std::domain_error("Invalid operation, did you call init() before ?");
}
if (worker > ioGroup.size()) {
throw std::invalid_argument("Trying to pin invalid worker");
}
auto &wrk = ioGroup[worker];
wrk->pin(set);
}
bool bool
Listener::bind() { Listener::bind() {
return bind(addr_); return bind(addr_);
......
...@@ -49,6 +49,8 @@ public: ...@@ -49,6 +49,8 @@ public:
void start(const std::shared_ptr<Handler> &handler, Flags<Options> options); void start(const std::shared_ptr<Handler> &handler, Flags<Options> options);
void handleNewPeer(const std::shared_ptr<Peer>& peer); void handleNewPeer(const std::shared_ptr<Peer>& peer);
void pin(const CpuSet& set);
private: private:
Polling::Epoll poller; Polling::Epoll poller;
std::unique_ptr<std::thread> thread; std::unique_ptr<std::thread> thread;
...@@ -57,6 +59,8 @@ private: ...@@ -57,6 +59,8 @@ private:
std::shared_ptr<Handler> handler_; std::shared_ptr<Handler> handler_;
Flags<Options> options_; Flags<Options> options_;
CpuSet pins;
std::shared_ptr<Peer> getPeer(Fd fd) const; std::shared_ptr<Peer> getPeer(Fd fd) const;
std::shared_ptr<Peer> getPeer(Polling::Tag tag) const; std::shared_ptr<Peer> getPeer(Polling::Tag tag) const;
...@@ -87,6 +91,8 @@ public: ...@@ -87,6 +91,8 @@ public:
Options options() const; Options options() const;
Address address() const; Address address() const;
void pinWorker(size_t worker, const CpuSet& set);
private: private:
Address addr_; Address addr_;
int listen_fd; int listen_fd;
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
#include <algorithm> #include <algorithm>
#include <sys/epoll.h> #include <sys/epoll.h>
using namespace std;
int hardware_concurrency() { int hardware_concurrency() {
std::ifstream cpuinfo("/proc/cpuinfo"); std::ifstream cpuinfo("/proc/cpuinfo");
if (cpuinfo) { if (cpuinfo) {
...@@ -36,6 +38,104 @@ bool make_non_blocking(int sfd) ...@@ -36,6 +38,104 @@ bool make_non_blocking(int sfd)
return true; return true;
} }
CpuSet::CpuSet() {
bits.reset();
}
CpuSet::CpuSet(std::initializer_list<size_t> cpus) {
set(cpus);
}
void
CpuSet::clear() {
bits.reset();
}
CpuSet&
CpuSet::set(size_t cpu) {
if (cpu >= Size) {
throw std::invalid_argument("Trying to set invalid cpu number");
}
bits.set(cpu);
return *this;
}
CpuSet&
CpuSet::unset(size_t cpu) {
if (cpu >= Size) {
throw std::invalid_argument("Trying to unset invalid cpu number");
}
bits.set(cpu, false);
return *this;
}
CpuSet&
CpuSet::set(std::initializer_list<size_t> cpus) {
for (auto cpu: cpus) set(cpu);
return *this;
}
CpuSet&
CpuSet::unset(std::initializer_list<size_t> cpus) {
for (auto cpu: cpus) unset(cpu);
return *this;
}
CpuSet&
CpuSet::setRange(size_t begin, size_t end) {
if (begin > end) {
throw std::range_error("Invalid range, begin > end");
}
for (size_t cpu = begin; cpu < end; ++cpu) {
set(cpu);
}
return *this;
}
CpuSet&
CpuSet::unsetRange(size_t begin, size_t end) {
if (begin > end) {
throw std::range_error("Invalid range, begin > end");
}
for (size_t cpu = begin; cpu < end; ++cpu) {
unset(cpu);
}
return *this;
}
bool
CpuSet::isset(size_t cpu) const {
if (cpu >= Size) {
throw std::invalid_argument("Trying to test invalid cpu number");
}
return bits.test(cpu);
}
size_t
CpuSet::count() const {
return bits.count();
}
cpu_set_t
CpuSet::toPosix() const {
cpu_set_t cpu_set;
CPU_ZERO(&cpu_set);
for (size_t cpu = 0; cpu < Size; ++cpu) {
if (bits.test(cpu))
CPU_SET(cpu, &cpu_set);
}
return cpu_set;
};
namespace Polling { namespace Polling {
Epoll::Epoll(size_t max) { Epoll::Epoll(size_t max) {
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#include <chrono> #include <chrono>
#include <vector> #include <vector>
#include <bitset>
#include <sched.h>
#include "flags.h" #include "flags.h"
#include "common.h" #include "common.h"
...@@ -16,6 +18,32 @@ typedef int Fd; ...@@ -16,6 +18,32 @@ typedef int Fd;
int hardware_concurrency(); int hardware_concurrency();
bool make_non_blocking(int fd); bool make_non_blocking(int fd);
class CpuSet {
public:
static constexpr size_t Size = 1024;
CpuSet();
explicit CpuSet(std::initializer_list<size_t> cpus);
void clear();
CpuSet& set(size_t cpu);
CpuSet& unset(size_t cpu);
CpuSet& set(std::initializer_list<size_t> cpus);
CpuSet& unset(std::initializer_list<size_t> cpus);
CpuSet& setRange(size_t begin, size_t end);
CpuSet& unsetRange(size_t begin, size_t end);
bool isset(size_t cpu) const;
size_t count() const;
cpu_set_t toPosix() const;
private:
std::bitset<Size> bits;
};
namespace Polling { namespace Polling {
enum class Mode { enum class Mode {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment