Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ option(JOIN_ENABLE_CRYPTO "Enable crypto." ON)
option(JOIN_ENABLE_DATA "Enable data." ON)
option(JOIN_ENABLE_FABRIC "Enable fabric." ON)
option(JOIN_ENABLE_SERVICES "Enable services." ON)
option(JOIN_ENABLE_NUMA "Enable NUMA support." OFF)
option(JOIN_ENABLE_SAMPLES "Build samples" OFF)
option(JOIN_ENABLE_TESTS "Enable tests." OFF)
option(JOIN_ENABLE_COVERAGE "Enable coverage." OFF)
Expand Down Expand Up @@ -71,6 +72,7 @@ if(JOIN_ENABLE_COVERAGE)
endif()
endif()

find_package(PkgConfig REQUIRED)
find_package(Threads REQUIRED)
find_package(OpenSSL REQUIRED)

Expand Down
3 changes: 2 additions & 1 deletion CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"cacheVariables": {
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_VERBOSE_MAKEFILE": "ON",
"JOIN_ENABLE_NUMA": "ON",
"JOIN_ENABLE_SAMPLES": "ON",
"JOIN_ENABLE_TESTS": "ON"
}
Expand Down Expand Up @@ -119,4 +120,4 @@
}
}
]
}
}
36 changes: 34 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,23 @@ sudo apt install gcc g++ clang clang-tools libclang-rt-dev cmake ninja-build gdb

Install required libraries and test dependencies:
```bash
sudo apt install libssl-dev libnuma-dev zlib1g-dev libgtest-dev libgmock-dev
sudo apt install libssl-dev zlib1g-dev libgtest-dev libgmock-dev
```

> **Compilers:** Both GCC and Clang are supported. Clang requires `libclang-rt-dev` for coverage instrumentation (`--coverage`).
> **libnuma** is required for memory pinning and NUMA affinity in `join-core`.
> **OpenSSL** provides the core TLS runtime.

### Optional Dependencies

| Option | Library | Default | Description |
| :--- | :--- | :---: | :--- |
| `JOIN_ENABLE_NUMA` | `libnuma-dev` | `OFF` | Enables NUMA aware memory binding for `LocalMem` and `ShmMem`. |

Install as needed:
```bash
sudo apt install libnuma-dev # for JOIN_ENABLE_NUMA
```

### Build from Source
```bash
git clone https://github.com/joinframework/join.git
Expand All @@ -95,6 +105,28 @@ cmake -B build -DCMAKE_BUILD_TYPE=Release -DJOIN_ENABLE_TESTS=ON
cmake --build build
```

With optional backends:
```bash
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DJOIN_ENABLE_NUMA=ON \
-DJOIN_ENABLE_TESTS=ON
cmake --build build
```

### Build Options

| Option | Default | Description |
| :--- | :---: | :--- |
| `BUILD_SHARED_LIBS` | `ON` | Build as shared libraries. |
| `JOIN_ENABLE_CRYPTO` | `ON` | Build the crypto module. |
| `JOIN_ENABLE_DATA` | `ON` | Build the data module. |
| `JOIN_ENABLE_FABRIC` | `ON` | Build the fabric module. |
| `JOIN_ENABLE_SERVICES` | `ON` | Build the services module (requires crypto, data, fabric). |
| `JOIN_ENABLE_NUMA` | `OFF` | Enable NUMA support (requires `libnuma-dev`). |
| `JOIN_ENABLE_SAMPLES` | `OFF` | Build sample programs. |
| `JOIN_ENABLE_TESTS` | `OFF` | Build the test suite. |
| `JOIN_ENABLE_COVERAGE` | `OFF` | Enable code coverage instrumentation (requires Debug build). |

### Run Tests
```bash
ctest --test-dir build --output-on-failure
Expand Down
13 changes: 9 additions & 4 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
cmake_minimum_required(VERSION 3.22.1)

find_package(PkgConfig REQUIRED)
pkg_check_modules(NUMA REQUIRED numa)
if(JOIN_ENABLE_NUMA)
pkg_check_modules(NUMA REQUIRED numa)
endif()

set(PUBLIC_HEADERS
include/join/version.hpp
Expand Down Expand Up @@ -62,7 +63,7 @@ target_include_directories(${JOIN_CORE}
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
${NUMA_INCLUDE_DIRS}
$<$<BOOL:${JOIN_ENABLE_NUMA}>:${NUMA_INCLUDE_DIRS}>
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
)
Expand All @@ -72,9 +73,13 @@ target_link_libraries(${JOIN_CORE}
OpenSSL::SSL
OpenSSL::Crypto
Threads::Threads
${NUMA_LIBRARIES}
$<$<BOOL:${JOIN_ENABLE_NUMA}>:${NUMA_LIBRARIES}>
)

if(JOIN_ENABLE_NUMA)
target_compile_definitions(${JOIN_CORE} PUBLIC JOIN_HAS_NUMA)
endif()

install(TARGETS ${JOIN_CORE}
EXPORT joinTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
Expand Down
2 changes: 2 additions & 0 deletions core/include/join/allocator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,7 @@ namespace join
deallocateImplem<0> (p);
}

#ifdef JOIN_HAS_NUMA
/**
* @brief bind memory to a NUMA node.
* @param numa NUMA node ID.
Expand All @@ -426,6 +427,7 @@ namespace join
{
return _backend.mbind (numa);
}
#endif

/**
* @brief lock memory in RAM.
Expand Down
8 changes: 8 additions & 0 deletions core/include/join/memory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,10 @@
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef JOIN_HAS_NUMA
#include <numaif.h>
#include <numa.h>
#endif
#include <fcntl.h>
#include <cstdint>

Expand All @@ -63,6 +65,7 @@ namespace join
template <typename, typename>
struct Mpmc;

#ifdef JOIN_HAS_NUMA
/**
* @brief bind memory to a NUMA node.
* @param ptr memory pointer.
Expand All @@ -87,6 +90,7 @@ namespace join

return 0;
}
#endif

/**
* @brief lock memory in RAM.
Expand Down Expand Up @@ -233,6 +237,7 @@ namespace join
return static_cast<char*> (_ptr) + offset;
}

#ifdef JOIN_HAS_NUMA
/**
* @brief bind memory to a NUMA node.
* @param numa NUMA node ID.
Expand All @@ -242,6 +247,7 @@ namespace join
{
return join::mbind (_ptr, _size, numa);
}
#endif

/**
* @brief lock memory in RAM.
Expand Down Expand Up @@ -432,6 +438,7 @@ namespace join
return static_cast<char*> (_ptr) + offset;
}

#ifdef JOIN_HAS_NUMA
/**
* @brief bind memory to a NUMA node.
* @param numa NUMA node ID.
Expand All @@ -441,6 +448,7 @@ namespace join
{
return join::mbind (_ptr, _size, numa);
}
#endif

/**
* @brief lock memory in RAM.
Expand Down
2 changes: 2 additions & 0 deletions core/include/join/queue.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ namespace join
return pending () == 0;
}

#ifdef JOIN_HAS_NUMA
/**
* @brief bind memory to a NUMA node.
* @param numa NUMA node ID.
Expand All @@ -429,6 +430,7 @@ namespace join
{
return _backend.mbind (numa);
}
#endif

/**
* @brief lock memory in RAM.
Expand Down
4 changes: 4 additions & 0 deletions core/include/join/reactor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,12 +183,14 @@ namespace join
*/
void stop (bool sync = true) noexcept;

#ifdef JOIN_HAS_NUMA
/**
* @brief bind command queue memory to a NUMA node.
* @param numa NUMA node ID.
* @return 0 on success, -1 on failure.
*/
int mbind (int numa) const noexcept;
#endif

/**
* @brief lock command queue memory in RAM.
Expand Down Expand Up @@ -351,12 +353,14 @@ namespace join
*/
static pthread_t handle ();

#ifdef JOIN_HAS_NUMA
/**
* @brief bind command queue memory to a NUMA node.
* @param numa NUMA node ID.
* @return 0 on success, -1 on failure.
*/
static int mbind (int numa);
#endif

/**
* @brief lock command queue memory in RAM.
Expand Down
50 changes: 26 additions & 24 deletions core/include/join/statistics.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,13 @@ namespace join
/**
* @brief destroy instance.
*/
~BasicStats () noexcept = default;
~BasicStats () noexcept
{
for (int i = 0; i < _countsLen; ++i)
{
_counts[i].~atomic<uint64_t> ();
}
}

/**
* @brief get metric name.
Expand Down Expand Up @@ -125,9 +131,21 @@ namespace join
const uint64_t ns =
static_cast<uint64_t> (std::chrono::duration_cast<Duration> (ClockPolicy::now () - startTime).count ());

record (ns);
_sum.fetch_add (ns, std::memory_order_relaxed);
_last.store (ns, std::memory_order_relaxed);

auto prev = _min.load (std::memory_order_relaxed);
while (ns < prev &&
!_min.compare_exchange_weak (prev, ns, std::memory_order_relaxed, std::memory_order_relaxed))
;

prev = _max.load (std::memory_order_relaxed);
while (ns > prev &&
!_max.compare_exchange_weak (prev, ns, std::memory_order_relaxed, std::memory_order_relaxed))
;

_counts[countsIndex (ns)].fetch_add (1, std::memory_order_relaxed);
_count.fetch_add (1, std::memory_order_release);
}

/**
Expand Down Expand Up @@ -161,6 +179,10 @@ namespace join
*/
Duration last () const noexcept
{
if (_count.load (std::memory_order_acquire) == 0)
{
return Duration (0);
}
return Duration (_last.load (std::memory_order_relaxed));
}

Expand Down Expand Up @@ -251,6 +273,7 @@ namespace join
return Duration (static_cast<typename Duration::rep> (_maxTrackableValue));
}

#ifdef JOIN_HAS_NUMA
/**
* @brief bind histogram memory to a NUMA node.
* @param numa NUMA node ID.
Expand All @@ -260,6 +283,7 @@ namespace join
{
return _countsMem.mbind (numa);
}
#endif

/**
* @brief lock histogram memory in RAM.
Expand All @@ -271,28 +295,6 @@ namespace join
}

private:
/**
* @brief atomically update all accumulators with a new sample.
* @param ns elapsed duration in nanoseconds to record.
*/
void record (uint64_t ns) noexcept
{
_sum.fetch_add (ns, std::memory_order_relaxed);
_last.store (ns, std::memory_order_relaxed);

auto prev = _min.load (std::memory_order_relaxed);
while (ns < prev &&
!_min.compare_exchange_weak (prev, ns, std::memory_order_relaxed, std::memory_order_relaxed))
;

prev = _max.load (std::memory_order_relaxed);
while (ns > prev &&
!_max.compare_exchange_weak (prev, ns, std::memory_order_relaxed, std::memory_order_relaxed))
;

_count.fetch_add (1, std::memory_order_release);
}

/**
* @brief compute the HDR power-of-2 bucket index for a value.
* @param v value in nanoseconds.
Expand Down
4 changes: 4 additions & 0 deletions core/src/reactor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ void Reactor::stop (bool sync) noexcept
}
}

#ifdef JOIN_HAS_NUMA
// =========================================================================
// CLASS : Reactor
// METHOD : mbind
Expand All @@ -240,6 +241,7 @@ int Reactor::mbind (int numa) const noexcept
{
return _commands.mbind (numa);
}
#endif

// =========================================================================
// CLASS : Reactor
Expand Down Expand Up @@ -494,6 +496,7 @@ pthread_t ReactorThread::handle ()
return instance ()._dispatcher.handle ();
}

#ifdef JOIN_HAS_NUMA
// =========================================================================
// CLASS : ReactorThread
// METHOD : mbind
Expand All @@ -502,6 +505,7 @@ int ReactorThread::mbind (int numa)
{
return instance ()._reactor.mbind (numa);
}
#endif

// =========================================================================
// CLASS : ReactorThread
Expand Down
Loading
Loading