From 5ccaad0a3d6ede226016346515315d17984aafbd Mon Sep 17 00:00:00 2001 From: Nagendra S Tomar Date: Thu, 4 Dec 2025 07:48:43 +0000 Subject: [PATCH 1/5] Changes to facilitate Linux build for KVService --- CMakeLists.txt | 1 + KVPlayground/CMakeLists.txt | 5 +++++ KVService/CMakeLists.txt | 19 ++++++++++++++----- KVService/QUICKSTART.md | 2 +- KVService/README.md | 2 +- README.md | 8 ++++---- build-linux.sh | 10 ++++++++++ run-kvserver.sh | 3 +++ 8 files changed, 39 insertions(+), 11 deletions(-) create mode 100755 build-linux.sh create mode 100755 run-kvserver.sh diff --git a/CMakeLists.txt b/CMakeLists.txt index 788f7d5..39a264b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,7 @@ if(UNIX) message(STATUS "Building for Linux: KVClient + KVPlayground") add_subdirectory(KVClient) add_subdirectory(KVPlayground) + add_subdirectory(KVService) elseif(WIN32) message(WARNING "For Windows builds, use KVService/build_with_local_sdk.ps1") message(WARNING "This root CMakeLists.txt is for Linux builds only") diff --git a/KVPlayground/CMakeLists.txt b/KVPlayground/CMakeLists.txt index 21b095b..6092394 100644 --- a/KVPlayground/CMakeLists.txt +++ b/KVPlayground/CMakeLists.txt @@ -38,8 +38,13 @@ set_target_properties(KVPlayground PROPERTIES CXX_EXTENSIONS NO ) +find_package(Python3 REQUIRED) + # Copy chunk.bin and conversation_tokens.json to output directory after build add_custom_command(TARGET KVPlayground POST_BUILD + COMMAND ${Python3_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/precompute_tokens.py + ${CMAKE_CURRENT_LIST_DIR}/conversation_template.txt + ${CMAKE_CURRENT_LIST_DIR}/conversation_tokens.json COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/chunk.bin $/chunk.bin diff --git a/KVService/CMakeLists.txt b/KVService/CMakeLists.txt index 986fbce..6eb5b34 100644 --- a/KVService/CMakeLists.txt +++ b/KVService/CMakeLists.txt @@ -3,7 +3,11 @@ cmake_minimum_required(VERSION 3.15) # Option to use local Azure SDK build (for multi-NIC support) # NOTE: Local SDK must be built first with custom multi-NIC features # Set to ON to use local Azure SDK with multi-NIC support -option(USE_LOCAL_AZURE_SDK "Use local Azure SDK build instead of vcpkg" ON) +if(WIN32) + option(USE_LOCAL_AZURE_SDK "Use local Azure SDK build instead of vcpkg" ON) +else() + option(USE_LOCAL_AZURE_SDK "Use local Azure SDK build instead of vcpkg" OFF) +endif() # Configure local Azure SDK if enabled (BEFORE vcpkg toolchain) if(USE_LOCAL_AZURE_SDK) @@ -147,11 +151,16 @@ else() Azure::azure-storage-blobs Azure::azure-identity Azure::azure-core - # Windows system libraries - winhttp - bcrypt - crypt32 ) + + if(WIN32) + target_link_libraries(AzureStorageKVStoreLibV2 PUBLIC + # Windows system libraries + winhttp + bcrypt + crypt32 + ) + endif() endif() # KVStoreService library diff --git a/KVService/QUICKSTART.md b/KVService/QUICKSTART.md index c739516..8abacfd 100644 --- a/KVService/QUICKSTART.md +++ b/KVService/QUICKSTART.md @@ -42,7 +42,7 @@ cmake --build build --config Release ```bash # Navigate to your kvStore directory -cd ~/kvStore +cd ~/kvStoreV2 # Configure CMake cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake diff --git a/KVService/README.md b/KVService/README.md index 83ad912..1e6971a 100644 --- a/KVService/README.md +++ b/KVService/README.md @@ -267,7 +267,7 @@ Managed via vcpkg.json: ## Related Documentation - [ARCHITECTURE.md](../docs/ARCHITECTURE.md) - System architecture and deployment -- [QUICKSTART.md](../docs/QUICKSTART.md) - Detailed setup guide +- [QUICKSTART.md](QUICKSTART.md) - Detailed setup guide - [KVClient README](../KVClient/README.md) - Linux client library ## License diff --git a/README.md b/README.md index 319af5d..199a364 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ export KVSTORE_GRPC_SERVER="your-windows-server:8085" ```bash sudo apt-get update sudo apt-get install -y build-essential cmake git pkg-config \ - libssl-dev autoconf libtool curl unzip + libssl-dev autoconf libtool curl zip unzip python3-tiktoken ``` 2. **Install vcpkg**: @@ -152,15 +152,15 @@ cd vcpkg ./vcpkg integrate install ``` -3. **Install gRPC and Protobuf**: +3. **Install gRPC, Protobuf, Azure SDK and other important packages**: ```bash -./vcpkg install grpc protobuf nlohmann-json +./vcpkg install grpc protobuf nlohmann-json zlib azure-storage-blobs-cpp azure-identity-cpp ``` ### Build Steps ```bash -cd KVStoreV2 +cd kvStoreV2 mkdir build && cd build cmake .. -DCMAKE_TOOLCHAIN_FILE=/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake make -j$(nproc) diff --git a/build-linux.sh b/build-linux.sh new file mode 100755 index 0000000..51d745b --- /dev/null +++ b/build-linux.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Navigate to your kvStore directory +cd ~/kvStoreV2/ + +# Configure CMake +cmake -B build -S . -DCMAKE_TOOLCHAIN_FILE=/home/azureuser/vcpkg/scripts/buildsystems/vcpkg.cmake + +# Build +cmake --build build --config Release diff --git a/run-kvserver.sh b/run-kvserver.sh new file mode 100755 index 0000000..ce4e1eb --- /dev/null +++ b/run-kvserver.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +./build/KVService/KVStoreServer --port 8085 --log-level error --disable-metrics --disable-multi-nic From 172407b93c9e2ae2e0013e2cf4f90fe7e9dc3f9c Mon Sep 17 00:00:00 2001 From: Nagendra S Tomar Date: Fri, 5 Dec 2025 07:44:51 +0000 Subject: [PATCH 2/5] Save a buffer copy. --- KVService/src/AzureStorageKVStoreLibV2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/KVService/src/AzureStorageKVStoreLibV2.cpp b/KVService/src/AzureStorageKVStoreLibV2.cpp index 41704b6..0bf4423 100644 --- a/KVService/src/AzureStorageKVStoreLibV2.cpp +++ b/KVService/src/AzureStorageKVStoreLibV2.cpp @@ -661,8 +661,8 @@ std::future> AzureStorageKVStoreLibV2::ReadAsync(co chunk.partitionKey = partitionKey; chunk.parentHash = parentHash; chunk.hash = hash; - chunk.buffer = buffer; chunk.bufferSize = buffer.size(); + chunk.buffer = std::move(buffer); auto endTime = std::chrono::high_resolution_clock::now(); auto duration = std::chrono::duration_cast(endTime - startTime).count(); From dd8e1b0c9e7e0262d177866a6be00e032d5b192f Mon Sep 17 00:00:00 2001 From: Nagendra S Tomar Date: Fri, 5 Dec 2025 14:37:14 +0000 Subject: [PATCH 3/5] start kvserver on both ports --- run-kvserver.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/run-kvserver.sh b/run-kvserver.sh index ce4e1eb..e6c430e 100755 --- a/run-kvserver.sh +++ b/run-kvserver.sh @@ -1,3 +1,6 @@ #!/bin/bash -./build/KVService/KVStoreServer --port 8085 --log-level error --disable-metrics --disable-multi-nic +numactl --cpunodebind=0 --membind=0 ./build/KVService/KVStoreServer --port 8085 --log-level error --disable-metrics --disable-multi-nic & +numactl --cpunodebind=1 --membind=1 ./build/KVService/KVStoreServer --port 8086 --log-level error --disable-metrics --disable-multi-nic & + +wait From d0d657e8a300563915d7ab7441cd52e9dff24893 Mon Sep 17 00:00:00 2001 From: Nagendra S Tomar Date: Sun, 7 Dec 2025 02:18:50 +0000 Subject: [PATCH 4/5] Add support for tcmalloc and jemalloc tcmalloc performs well for rapid allocations done by multiple threads. That should help us. jemalloc is added for comparison. --- KVService/CMakeLists.txt | 75 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/KVService/CMakeLists.txt b/KVService/CMakeLists.txt index 6eb5b34..f3de850 100644 --- a/KVService/CMakeLists.txt +++ b/KVService/CMakeLists.txt @@ -7,6 +7,52 @@ if(WIN32) option(USE_LOCAL_AZURE_SDK "Use local Azure SDK build instead of vcpkg" ON) else() option(USE_LOCAL_AZURE_SDK "Use local Azure SDK build instead of vcpkg" OFF) + # These are currently only tested for Linux builds. + # Set only one of tcmalloc or jemalloc. + option(USE_TCMALLOC "Use tcmalloc for malloc/free/new/delete" ON) + option(USE_JEMALLOC "Use jemalloc for malloc/free/new/delete" OFF) +endif() + +if(USE_JEMALLOC) + find_package(PkgConfig REQUIRED) + pkg_search_module(JEMALLOC QUIET jemalloc) + + if(NOT JEMALLOC_FOUND) + message(STATUS "jemalloc not found, trying to install libjemalloc-dev!") + execute_process(COMMAND sudo apt install -y libjemalloc-dev + RESULT_VARIABLE JEMALLOC_INSTALL_RESULT) + if(NOT JEMALLOC_INSTALL_RESULT EQUAL "0") + message(FATAL_ERROR "apt install libjemalloc-dev failed with ${JEMALLOC_INSTALL_RESULT}, try installing libjemalloc-dev manually and then run cmake again") + else() + # Call once more to ensure above install completed fine and also + # will set JEMALLOC_LIBRARY_DIRS variable. + pkg_search_module(JEMALLOC REQUIRED jemalloc) + endif() + endif() + + # We want to link against the static jemalloc lib. + message(STATUS "Using jemalloc static lib ${JEMALLOC_LIBRARY_DIRS}/libjemalloc.a") +endif() + +if(USE_TCMALLOC) + find_package(PkgConfig REQUIRED) + pkg_check_modules(TCMALLOC QUIET libtcmalloc) + + if(NOT TCMALLOC_FOUND) + message(STATUS "tcmalloc not found, trying to install libgoogle-perftools-dev!") + execute_process(COMMAND sudo apt install -y libgoogle-perftools-dev + RESULT_VARIABLE TCMALLOC_INSTALL_RESULT) + if(NOT TCMALLOC_INSTALL_RESULT EQUAL "0") + message(FATAL_ERROR "apt install libgoogle-perftools-dev failed with ${TCMALLOC_INSTALL_RESULT}, try installing libgoogle-perftools-dev manually and then run cmake again") + else() + # Call once more to ensure above install completed fine and also + # will set tcmalloc_INCLUDE_DIR and TCMALLOC_LIBRARIES variables. + pkg_check_modules(TCMALLOC REQUIRED libtcmalloc) + endif() + else() + message(STATUS "Using tcmalloc lib ${TCMALLOC_LIBRARIES}") + message(STATUS "Using tcmalloc include dir ${TCMALLOC_INCLUDE_DIRS}") + endif() endif() # Configure local Azure SDK if enabled (BEFORE vcpkg toolchain) @@ -153,6 +199,16 @@ else() Azure::azure-core ) + if(USE_JEMALLOC) + target_link_libraries(AzureStorageKVStoreLibV2 PUBLIC + ${JEMALLOC_LIBRARY_DIRS}/libjemalloc.a) + endif() + + if(USE_TCMALLOC) + target_link_libraries(AzureStorageKVStoreLibV2 PUBLIC + ${TCMALLOC_LIBRARIES}) + endif() + if(WIN32) target_link_libraries(AzureStorageKVStoreLibV2 PUBLIC # Windows system libraries @@ -191,6 +247,16 @@ target_link_libraries(KVStoreServiceLib PUBLIC protobuf::libprotobuf ) +if(USE_JEMALLOC) +target_link_libraries(KVStoreServiceLib PUBLIC + ${JEMALLOC_LIBRARY_DIRS}/libjemalloc.a) +endif() + +if(USE_TCMALLOC) +target_link_libraries(KVStoreServiceLib PUBLIC + ${TCMALLOC_LIBRARIES}) +endif() + # Force static runtime to match vcpkg libraries target_compile_options(KVStoreServiceLib PRIVATE $<$:/MT> @@ -206,6 +272,15 @@ target_link_libraries(KVStoreServer PRIVATE KVStoreServiceLib ) +if(USE_JEMALLOC) + target_link_libraries(KVStoreServer PRIVATE + ${JEMALLOC_LIBRARY_DIRS}/libjemalloc.a) +endif() + +if(USE_TCMALLOC) + target_link_libraries(KVStoreServer PRIVATE + ${TCMALLOC_LIBRARIES}) +endif() # Force static runtime to match vcpkg libraries target_compile_options(KVStoreServer PRIVATE $<$:/MT> From 4d61fb88f529e4ffc31334beca771f82d4bc6262 Mon Sep 17 00:00:00 2001 From: Nagendra S Tomar Date: Sun, 7 Dec 2025 02:25:09 +0000 Subject: [PATCH 5/5] Run both servers on numa node 1 where the nic is bound. We can do this for large VMs where one numa node is not fully sturated. For smaller VMs or higher load, put servers on differen numa nodes. --- run-kvserver.sh | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/run-kvserver.sh b/run-kvserver.sh index e6c430e..596290b 100755 --- a/run-kvserver.sh +++ b/run-kvserver.sh @@ -1,6 +1,14 @@ #!/bin/bash -numactl --cpunodebind=0 --membind=0 ./build/KVService/KVStoreServer --port 8085 --log-level error --disable-metrics --disable-multi-nic & -numactl --cpunodebind=1 --membind=1 ./build/KVService/KVStoreServer --port 8086 --log-level error --disable-metrics --disable-multi-nic & +# +# On my VM the nic is bound to numa node 1, also one numa node is sufficient +# to process the current load. +# If one numa node is not sufficient then run one server process on each numa +# node. +# +while :; do + numactl --cpunodebind=1 --membind=1 ./build/KVService/KVStoreServer --port 8085 --log-level error --disable-metrics --disable-multi-nic & + numactl --cpunodebind=1 --membind=1 ./build/KVService/KVStoreServer --port 8086 --log-level error --disable-metrics --disable-multi-nic & -wait + wait +done