Skip to content

Commit 8564a25

Browse files
committed
Implement NUMA binding support for PosixShmSegment
1 parent a26e225 commit 8564a25

File tree

2 files changed

+45
-0
lines changed

2 files changed

+45
-0
lines changed

cachelib/shm/PosixShmSegment.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#include <sys/mman.h>
2222
#include <sys/stat.h>
2323
#include <sys/types.h>
24+
#include <numa.h>
25+
#include <numaif.h>
2426

2527
#include "cachelib/common/Utils.h"
2628

@@ -312,13 +314,54 @@ void* PosixShmSegment::mapAddress(void* addr) const {
312314
util::throwSystemError(EINVAL, "Address already mapped");
313315
}
314316
XDCHECK(retAddr == addr || addr == nullptr);
317+
memBind(addr);
315318
return retAddr;
316319
}
317320

318321
void PosixShmSegment::unMap(void* addr) const {
319322
detail::munmapImpl(addr, getSize());
320323
}
321324

325+
static void forcePageAllocation(void* addr, size_t size, size_t pageSize) {
326+
char* startAddr = reinterpret_cast<char*>(addr);
327+
char* endAddr = startAddr + size;
328+
for(volatile char* curAddr = startAddr; curAddr < endAddr; curAddr += pageSize) {
329+
*curAddr = *curAddr;
330+
}
331+
}
332+
333+
void PosixShmSegment::memBind(void* addr) const {
334+
if(opts_.memBindNumaNodes.empty()) return;
335+
336+
struct bitmask *oldNodeMask = numa_allocate_nodemask();
337+
int oldMode = 0;
338+
struct bitmask *nodesMask = numa_allocate_nodemask();
339+
auto guard = folly::makeGuard([&] { numa_bitmask_free(nodesMask); numa_bitmask_free(oldNodeMask); });
340+
341+
for(auto node : opts_.memBindNumaNodes) {
342+
numa_bitmask_setbit(nodesMask, node);
343+
}
344+
345+
// mbind() cannot be used because mmap was called with MAP_SHARED flag
346+
// But we can set memory policy for current thread and force page allcoation.
347+
// The following logic is used:
348+
// 1. Remember current memory policy for the current thread
349+
// 2. Set new memory policy as specifiec by config
350+
// 3. Force page allocation by touching every page in the segment
351+
// 4. Restore memory policy
352+
353+
// Remember current memory policy
354+
get_mempolicy(&oldMode, oldNodeMask->maskp, oldNodeMask->size, nullptr, 0);
355+
356+
// Set memory bindings
357+
set_mempolicy(MPOL_BIND, nodesMask->maskp, nodesMask->size);
358+
359+
forcePageAllocation(addr, getSize(), detail::getPageSize(opts_.pageSize));
360+
361+
// Restore memory policy for the thread
362+
set_mempolicy(oldMode, nodesMask->maskp, nodesMask->size);
363+
}
364+
322365
std::string PosixShmSegment::createKeyForName(
323366
const std::string& name) noexcept {
324367
// ensure that the slash is always there in the head. repetitive

cachelib/shm/PosixShmSegment.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ class PosixShmSegment : public ShmBase {
110110
void createReferenceMapping();
111111
void deleteReferenceMapping() const;
112112

113+
void memBind(void* addr) const;
114+
113115
// file descriptor associated with the shm. This has FD_CLOEXEC set
114116
// and once opened, we close this only on destruction of this object
115117
int fd_{kInvalidFD};

0 commit comments

Comments
 (0)