diff --git a/.github/workflows/code-review.yml b/.github/workflows/code-review.yml index 5d94a0a712..588cee14fc 100644 --- a/.github/workflows/code-review.yml +++ b/.github/workflows/code-review.yml @@ -7,6 +7,8 @@ on: jobs: qoder-review: runs-on: ubuntu-latest + env: + QODER_PERSONAL_ACCESS_TOKEN: ${{ secrets.QODER_PERSONAL_ACCESS_TOKEN }} permissions: contents: read pull-requests: write @@ -14,14 +16,20 @@ jobs: steps: - name: Checkout repository + if: ${{ env.QODER_PERSONAL_ACCESS_TOKEN != '' }} uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run Qoder Code Review + if: ${{ env.QODER_PERSONAL_ACCESS_TOKEN != '' }} uses: QoderAI/qoder-action@v0 with: - qoder_personal_access_token: ${{ secrets.QODER_PERSONAL_ACCESS_TOKEN }} + qoder_personal_access_token: ${{ env.QODER_PERSONAL_ACCESS_TOKEN }} prompt: | /review-pr REPO:${{ github.repository }} PR_NUMBER:${{ github.event.pull_request.number }} + + - name: Skip Qoder Code Review + if: ${{ env.QODER_PERSONAL_ACCESS_TOKEN == '' }} + run: echo "Qoder review skipped because QODER_PERSONAL_ACCESS_TOKEN is unavailable." diff --git a/.gitmodules b/.gitmodules index acc910c38d..5a4998c24b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,3 +6,7 @@ path = extern/yalantinglibs url = https://github.com/alibaba/yalantinglibs.git branch = v0.5.7 +[submodule "extern/ubdiag"] + path = extern/ubdiag + url = https://atomgit.com/liusiyu60/ubdiag + branch = fix/shm-probe-fastpath diff --git a/extern/ubdiag b/extern/ubdiag new file mode 160000 index 0000000000..7deea5f897 --- /dev/null +++ b/extern/ubdiag @@ -0,0 +1 @@ +Subproject commit 7deea5f89786784a2e2aa074d315a0a8e2561963 diff --git a/mooncake-common/FindUbDiag.cmake b/mooncake-common/FindUbDiag.cmake new file mode 100644 index 0000000000..b4e7a53594 --- /dev/null +++ b/mooncake-common/FindUbDiag.cmake @@ -0,0 +1,277 @@ +# FindUbDiag.cmake Resolves UbDiag::ubdiag_lib with a three-layer fallback: 1. +# Submodule (extern/ubdiag) — add_subdirectory if present 2. System package — +# find_package(UbDiag QUIET) 3. Mock header — mooncake-common/ubdiag-mock/ +# (no-op PerfPoint) +# +# Usage: include(${CMAKE_SOURCE_DIR}/mooncake-common/FindUbDiag.cmake) +# target_link_libraries(your_target PRIVATE UbDiag::ubdiag_lib) + +if(TARGET UbDiag::ubdiag_lib) + return() +endif() + +option(MOONCAKE_UBDIAG_BUILD_CLI + "Enable UbDiag CLI integration for vendored or system UbDiag" ON) +option(MOONCAKE_UBDIAG_L1_SHARED + "Build vendored UbDiag as libubdiag.so so Mooncake and the CLI use one SDK" ON) +option(MOONCAKE_UBDIAG_ENABLE_PERCENTILE + "Enable vendored UbDiag P99/P999/P9999 percentile calculation for Mooncake PerfPoint" ON) +option(MOONCAKE_UBDIAG_ENABLE_PERFLOG + "Enable vendored UbDiag PerfLog timestamp logging for Mooncake PerfPoint" ON) +option(MOONCAKE_UBDIAG_PERFPOINT_ONLY + "Disable vendored UbDiag OB/MemPoint/CachePoint extensions; keep Mooncake PerfPoint/P99/PerfLog/CSV" ON) +option(MOONCAKE_UBDIAG_DISABLE_SYSTEM + "Skip Layer 2 system-package lookup, used only for forced mock verification" OFF) + +function(_mooncake_ubdiag_write_rpm_manifest layer cli_path library_path config_path) + set(_manifest "${CMAKE_BINARY_DIR}/mooncake_ubdiag_rpm.env") + file(WRITE "${_manifest}" "MOONCAKE_UBDIAG_LAYER=${layer}\n") + file(APPEND "${_manifest}" "MOONCAKE_UBDIAG_CLI_PATH=${cli_path}\n") + file(APPEND "${_manifest}" "MOONCAKE_UBDIAG_LIBRARY_PATH=${library_path}\n") + file(APPEND "${_manifest}" "MOONCAKE_UBDIAG_CONFIG_PATH=${config_path}\n") + set(MOONCAKE_UBDIAG_RPM_MANIFEST "${_manifest}" + CACHE FILEPATH "UbDiag RPM packaging manifest generated by Mooncake" FORCE) + set(MOONCAKE_UBDIAG_ACTIVE_LAYER "${layer}" + CACHE STRING "Active UbDiag integration layer: submodule, system, or mock" FORCE) +endfunction() + +function(_mooncake_ubdiag_get_imported_location target out_var) + set(_location_props IMPORTED_LOCATION IMPORTED_LOCATION_NOCONFIG) + get_target_property(_configs ${target} IMPORTED_CONFIGURATIONS) + if(NOT _configs OR _configs MATCHES "-NOTFOUND$") + set(_configs) + endif() + foreach(_config IN LISTS _configs) + string(TOUPPER "${_config}" _config_upper) + list(APPEND _location_props "IMPORTED_LOCATION_${_config_upper}") + endforeach() + list(APPEND _location_props + IMPORTED_LOCATION_RELEASE + IMPORTED_LOCATION_RELWITHDEBINFO + IMPORTED_LOCATION_MINSIZEREL + IMPORTED_LOCATION_DEBUG) + + foreach(_prop IN LISTS _location_props) + get_target_property(_location ${target} ${_prop}) + if(_location AND NOT _location MATCHES "-NOTFOUND$") + set(${out_var} "${_location}" PARENT_SCOPE) + return() + endif() + endforeach() + + set(${out_var} "" PARENT_SCOPE) +endfunction() + +function(_mooncake_ubdiag_require_submodule_file source_dir relative_path) + set(_required_file "${source_dir}/${relative_path}") + if(EXISTS "${_required_file}") + return() + endif() + + # A pull updates the parent gitlink but does not repair deleted files in an + # already checked-out submodule. Restore only the required tracked file and + # leave every other local UbDiag change untouched. + find_program(_MOONCAKE_UBDIAG_GIT_EXECUTABLE NAMES git) + if(_MOONCAKE_UBDIAG_GIT_EXECUTABLE AND EXISTS "${source_dir}/.git") + execute_process( + COMMAND "${_MOONCAKE_UBDIAG_GIT_EXECUTABLE}" + -C "${source_dir}" checkout -- "${relative_path}" + RESULT_VARIABLE _restore_result + OUTPUT_QUIET + ERROR_QUIET) + if(_restore_result EQUAL 0 AND EXISTS "${_required_file}") + message(STATUS "UbDiag: restored missing tracked file ${relative_path}") + return() + endif() + endif() + + message(FATAL_ERROR + "UbDiag L1 submodule is incomplete: ${_required_file} is missing.\n" + "Restore the recorded submodule contents with:\n" + " git submodule sync --recursive\n" + " git submodule update --init --checkout extern/ubdiag") +endfunction() + +# Layer 1: Submodule (same pattern as extern/pybind11). UbDiag's generic +# BUILD_TESTS / BUILD_EXAMPLES default to ON and collide with Mooncake option +# names, so temporarily narrow them only while adding the submodule. +if(EXISTS "${CMAKE_SOURCE_DIR}/extern/ubdiag/CMakeLists.txt") + file(STRINGS "${CMAKE_SOURCE_DIR}/extern/ubdiag/CMakeLists.txt" + _MOONCAKE_UBDIAG_PACKAGE_CONFIG_REFS + REGEX "UbDiagConfig\\.cmake\\.in") + if(_MOONCAKE_UBDIAG_PACKAGE_CONFIG_REFS) + _mooncake_ubdiag_require_submodule_file( + "${CMAKE_SOURCE_DIR}/extern/ubdiag" "cmake/UbDiagConfig.cmake.in") + endif() + + set(_MOONCAKE_UBDIAG_SAVED_BUILD_EXAMPLES "${BUILD_EXAMPLES}") + set(_MOONCAKE_UBDIAG_HAD_BUILD_EXAMPLES_CACHE FALSE) + if(DEFINED CACHE{BUILD_EXAMPLES}) + set(_MOONCAKE_UBDIAG_HAD_BUILD_EXAMPLES_CACHE TRUE) + get_property(_MOONCAKE_UBDIAG_BUILD_EXAMPLES_HELP CACHE BUILD_EXAMPLES PROPERTY HELPSTRING) + endif() + set(_MOONCAKE_UBDIAG_SAVED_BUILD_TESTS "${BUILD_TESTS}") + set(_MOONCAKE_UBDIAG_HAD_BUILD_TESTS_CACHE FALSE) + if(DEFINED CACHE{BUILD_TESTS}) + set(_MOONCAKE_UBDIAG_HAD_BUILD_TESTS_CACHE TRUE) + get_property(_MOONCAKE_UBDIAG_BUILD_TESTS_HELP CACHE BUILD_TESTS PROPERTY HELPSTRING) + endif() + set(BUILD_EXAMPLES OFF) + set(BUILD_EXAMPLES OFF CACHE BOOL "Disable UbDiag examples when vendored by Mooncake" FORCE) + set(BUILD_TESTS OFF) + set(BUILD_TESTS OFF CACHE BOOL "Disable UbDiag tests when vendored by Mooncake" FORCE) + if(MOONCAKE_UBDIAG_L1_SHARED) + set(UBDIAG_BUILD_SHARED ON CACHE BOOL "Build vendored UbDiag as a shared library" FORCE) + endif() + if(MOONCAKE_UBDIAG_ENABLE_PERCENTILE) + set(ENABLE_PERCENTILE ON CACHE BOOL "Enable vendored UbDiag percentile calculation" FORCE) + endif() + if(MOONCAKE_UBDIAG_ENABLE_PERFLOG) + set(ENABLE_PERFLOG ON CACHE BOOL "Enable vendored UbDiag PerfLog support" FORCE) + endif() + if(MOONCAKE_UBDIAG_PERFPOINT_ONLY) + set(ENABLE_OB_MEMORY OFF CACHE BOOL "Disable vendored UbDiag eBPF memory observation" FORCE) + set(ENABLE_OB_CACHE OFF CACHE BOOL "Disable vendored UbDiag cache observation" FORCE) + set(ENABLE_MEMPOINT OFF CACHE BOOL "Disable vendored UbDiag MemPoint observation" FORCE) + set(UBDIAG_ENABLE_CACHEPOINT OFF CACHE BOOL "Disable vendored UbDiag CachePoint observation" FORCE) + endif() + + add_subdirectory(${CMAKE_SOURCE_DIR}/extern/ubdiag + ${CMAKE_BINARY_DIR}/extern/ubdiag_build EXCLUDE_FROM_ALL) + + if(_MOONCAKE_UBDIAG_HAD_BUILD_EXAMPLES_CACHE) + set(BUILD_EXAMPLES "${_MOONCAKE_UBDIAG_SAVED_BUILD_EXAMPLES}" + CACHE BOOL "${_MOONCAKE_UBDIAG_BUILD_EXAMPLES_HELP}" FORCE) + else() + unset(BUILD_EXAMPLES CACHE) + endif() + set(BUILD_EXAMPLES "${_MOONCAKE_UBDIAG_SAVED_BUILD_EXAMPLES}") + if(_MOONCAKE_UBDIAG_HAD_BUILD_TESTS_CACHE) + set(BUILD_TESTS "${_MOONCAKE_UBDIAG_SAVED_BUILD_TESTS}" + CACHE BOOL "${_MOONCAKE_UBDIAG_BUILD_TESTS_HELP}" FORCE) + else() + unset(BUILD_TESTS CACHE) + endif() + set(BUILD_TESTS "${_MOONCAKE_UBDIAG_SAVED_BUILD_TESTS}") + + if(TARGET ubdiag_lib) + set(_MOONCAKE_UBDIAG_SOURCE_DIR "${CMAKE_SOURCE_DIR}/extern/ubdiag") + # ubdiag's CMake uses CMAKE_SOURCE_DIR instead of CMAKE_CURRENT_SOURCE_DIR + # for its include paths. When consumed via add_subdirectory from Mooncake, + # CMAKE_SOURCE_DIR points to Mooncake's root, not ubdiag's. Fix it here. + target_include_directories(ubdiag_lib PUBLIC + $ + $) + + foreach(_MOONCAKE_UBDIAG_LIB_TARGET + ubdiag_logger ubdiag_manager_lib ubdiag_runtime_lib ubdiag_bpf_loader) + if(TARGET ${_MOONCAKE_UBDIAG_LIB_TARGET}) + target_include_directories(${_MOONCAKE_UBDIAG_LIB_TARGET} PUBLIC + $ + $) + endif() + endforeach() + + if(TARGET ubdiag) + target_include_directories(ubdiag PRIVATE + ${_MOONCAKE_UBDIAG_SOURCE_DIR}/include + ${_MOONCAKE_UBDIAG_SOURCE_DIR}/src + ${_MOONCAKE_UBDIAG_SOURCE_DIR}/src/cli) + if(MOONCAKE_UBDIAG_BUILD_CLI AND NOT TARGET mooncake_ubdiag_cli) + add_custom_target(mooncake_ubdiag_cli ALL DEPENDS ubdiag) + endif() + elseif(MOONCAKE_UBDIAG_BUILD_CLI) + message(WARNING "UbDiag: extern/ubdiag does not define the ubdiag CLI target") + endif() + + add_library(UbDiag::ubdiag_lib ALIAS ubdiag_lib) + _mooncake_ubdiag_write_rpm_manifest( + "submodule" + "${CMAKE_BINARY_DIR}/extern/ubdiag_build/src/cli/ubdiag" + "${CMAKE_BINARY_DIR}/extern/ubdiag_build/src/sdk/libubdiag.so" + "${CMAKE_SOURCE_DIR}/extern/ubdiag/config/ubdiag.conf.example") + message(STATUS "UbDiag: using submodule (extern/ubdiag, CLI=${MOONCAKE_UBDIAG_BUILD_CLI})") + return() + endif() +endif() + +# Layer 2: System package — only search standard system library paths +# Using NO_DEFAULT_PATH + explicit PATHS to prevent cmake from recursively +# searching CMAKE_SYSTEM_PREFIX_PATH subdirectories (e.g., UbDiag_bak, build artifacts) +if(NOT MOONCAKE_UBDIAG_DISABLE_SYSTEM) + find_package(UbDiag QUIET + NO_DEFAULT_PATH + PATHS + /usr/lib64/cmake + /usr/local/lib64/cmake + /usr/lib/cmake + /usr/local/lib/cmake) + if(TARGET UbDiag::ubdiag_lib) + _mooncake_ubdiag_get_imported_location(UbDiag::ubdiag_lib _MOONCAKE_UBDIAG_SYSTEM_LIBRARY) + + set(_MOONCAKE_UBDIAG_CLI_HINTS) + set(_MOONCAKE_UBDIAG_CONFIG_HINTS) + if(_MOONCAKE_UBDIAG_SYSTEM_LIBRARY) + get_filename_component(_MOONCAKE_UBDIAG_SYSTEM_LIB_DIR + "${_MOONCAKE_UBDIAG_SYSTEM_LIBRARY}" DIRECTORY) + get_filename_component(_MOONCAKE_UBDIAG_SYSTEM_PREFIX + "${_MOONCAKE_UBDIAG_SYSTEM_LIB_DIR}/.." ABSOLUTE) + list(APPEND _MOONCAKE_UBDIAG_CLI_HINTS + "${_MOONCAKE_UBDIAG_SYSTEM_PREFIX}/bin") + list(APPEND _MOONCAKE_UBDIAG_CONFIG_HINTS + "${_MOONCAKE_UBDIAG_SYSTEM_PREFIX}/etc/ubdiag") + endif() + + find_program(MOONCAKE_UBDIAG_SYSTEM_CLI + NAMES ubdiag + HINTS ${_MOONCAKE_UBDIAG_CLI_HINTS} + PATHS /usr/bin /usr/local/bin + NO_DEFAULT_PATH) + if(MOONCAKE_UBDIAG_SYSTEM_CLI + AND NOT MOONCAKE_UBDIAG_SYSTEM_CLI MATCHES "-NOTFOUND$") + set(_MOONCAKE_UBDIAG_SYSTEM_CLI "${MOONCAKE_UBDIAG_SYSTEM_CLI}") + if(MOONCAKE_UBDIAG_BUILD_CLI AND NOT TARGET UbDiag::ubdiag_cli) + add_executable(UbDiag::ubdiag_cli IMPORTED GLOBAL) + set_target_properties(UbDiag::ubdiag_cli PROPERTIES + IMPORTED_LOCATION "${_MOONCAKE_UBDIAG_SYSTEM_CLI}") + endif() + if(MOONCAKE_UBDIAG_BUILD_CLI AND NOT TARGET mooncake_ubdiag_cli) + add_custom_target(mooncake_ubdiag_cli ALL + DEPENDS "${_MOONCAKE_UBDIAG_SYSTEM_CLI}") + endif() + else() + set(_MOONCAKE_UBDIAG_SYSTEM_CLI "") + if(MOONCAKE_UBDIAG_BUILD_CLI) + message(WARNING "UbDiag: system package found, but ubdiag CLI was not found under standard system paths") + endif() + endif() + + find_file(MOONCAKE_UBDIAG_SYSTEM_CONFIG + NAMES ubdiag.conf + HINTS ${_MOONCAKE_UBDIAG_CONFIG_HINTS} + PATHS /etc/ubdiag /usr/local/etc/ubdiag + NO_DEFAULT_PATH) + if(MOONCAKE_UBDIAG_SYSTEM_CONFIG + AND NOT MOONCAKE_UBDIAG_SYSTEM_CONFIG MATCHES "-NOTFOUND$") + set(_MOONCAKE_UBDIAG_SYSTEM_CONFIG "${MOONCAKE_UBDIAG_SYSTEM_CONFIG}") + else() + set(_MOONCAKE_UBDIAG_SYSTEM_CONFIG "") + endif() + + _mooncake_ubdiag_write_rpm_manifest( + "system" + "${_MOONCAKE_UBDIAG_SYSTEM_CLI}" + "${_MOONCAKE_UBDIAG_SYSTEM_LIBRARY}" + "${_MOONCAKE_UBDIAG_SYSTEM_CONFIG}") + message(STATUS "UbDiag: using system package (CLI=${_MOONCAKE_UBDIAG_SYSTEM_CLI})") + return() + endif() +endif() + +# Layer 3: Mock fallback (no-op PerfPoint, guarantees compilation) +add_library(ubdiag_mock INTERFACE) +target_include_directories( + ubdiag_mock INTERFACE ${CMAKE_SOURCE_DIR}/mooncake-common/ubdiag-mock) +add_library(UbDiag::ubdiag_lib ALIAS ubdiag_mock) +_mooncake_ubdiag_write_rpm_manifest("mock" "" "" "") +message(STATUS "UbDiag: using mock (no-op PerfPoint)") diff --git a/mooncake-common/common.cmake b/mooncake-common/common.cmake index eefa33bdb4..b2a56acc67 100644 --- a/mooncake-common/common.cmake +++ b/mooncake-common/common.cmake @@ -89,7 +89,6 @@ option(USE_UB "option for using UB protocol transport" OFF) option(USE_SUNRISE "option for enabling gpu features for Sunrise GPU with Tang runtime" OFF) if (USE_UB) - add_compile_definitions(USE_UB) message(STATUS "ub transport is enabled") include(${CMAKE_CURRENT_LIST_DIR}/FindUrma.cmake) endif() diff --git a/mooncake-common/ubdiag-mock/README.md b/mooncake-common/ubdiag-mock/README.md new file mode 100644 index 0000000000..8e98b03e00 --- /dev/null +++ b/mooncake-common/ubdiag-mock/README.md @@ -0,0 +1,158 @@ +# UbDiag Mock — Mooncake 集成说明 + +本目录是 Mooncake 项目的 UbDiag header-only mock,提供空操作的 PerfPoint, +确保在未安装 UbDiag 的情况下 Mooncake 仍可正常编译。 + +## 四种情况:用户拿到 Mooncake 后,每一步发生了什么 + +### 情况 A:`git clone --recursive` — 完整 submodule 路径 + +**Step 1 — git clone**:`--recursive` 触发 Git 读取 `.gitmodules`,自动拉取三个 submodule: +``` +extern/pybind11/ ← 已拉取 +extern/yalantinglibs/ ← 已拉取 +extern/ubdiag/ ← 已拉取,commit f0a4a13(v0.4.0-56) +``` + +**Step 2 — cmake**:CMake 执行到 `FindUbDiag.cmake`,按顺序判断: +``` +if(TARGET UbDiag::ubdiag_lib) → 否,第一次执行 +if(EXISTS "extern/ubdiag/CMakeLists.txt") → 是 → add_subdirectory(real ubdiag) +``` +输出:`UbDiag: using submodule (extern/ubdiag)`,return。 + +`EXCLUDE_FROM_ALL` 保证只编译 `ubdiag_lib` 自身,不编译它的 30+ 个单元测试和 examples。 + +**Step 3 — make**:`real_client.cpp` 中 `#include "ubdiag/auto_perf.h"` 找到真实 UbDiag,`PerfPoint::Start()/End()` 走 SHM 写入,性能数据可被 `ubdiag watch` 实时采集。 + +--- + +### 情况 B:`git clone`(无 `--recursive`)— mock 回退路径 + +**Step 1 — git clone**:只拉 Mooncake 自有代码。`extern/ubdiag/` 目录不存在。 + +**Step 2 — cmake**:`FindUbDiag.cmake` 按顺序判断: +``` +if(TARGET UbDiag::ubdiag_lib) → 否 +if(EXISTS "extern/ubdiag/CMakeLists.txt") → 否,目录不存在 +find_package(UbDiag QUIET) → 否,系统没装 +→ 走 Layer 3:创建 header-only INTERFACE library +``` +```cmake +add_library(ubdiag_mock INTERFACE) # 没有 .cpp,只暴露头文件路径 +add_library(UbDiag::ubdiag_lib ALIAS ubdiag_mock) +``` +输出:`UbDiag: using mock (no-op PerfPoint)`。 + +**Step 3 — make**:编译器展开 `PerfPoint::Start()` / `End()` 的两个空函数体: +```cpp +void Start() {} // 编译器 -O1 以上:零指令 +void End(int = 0) {} // 同上 +``` +93+ 处 `PerfPoint(...)` 调用全部优化为空操作。Mooncake 完整编译运行,无需 systemtap-sdt-dev、libbpf 等任何 UbDiag 依赖。 + +--- + +### 情况 C:已有 clone(无 submodule),后来补拉 + +**Step 1 — git submodule update**:`extern/ubdiag/` 从不存在变为存在,Git 拉取 commit `f0a4a13`。 + +```bash +git submodule update --init --recursive +``` + +**Step 2 — 重新 cmake + make**:`FindUbDiag.cmake` 再次执行时 `EXISTS "extern/ubdiag/CMakeLists.txt"` 从 false 变成 true,Layer 1 命中。mock → submodule 切换自动完成,**不需要改任何 cmake 参数。** + +```bash +cd build && cmake .. && make -j +``` + +--- + +### 情况 D:CI 环境已系统预装 UbDiag + +**Step 1 — 系统预装**:运维已通过 RPM 或 `make install` 部署 `libubdiag.so` + `UbDiagConfig.cmake`。 + +```bash +cd ubdiag && bash build.sh -r && cd build && sudo make install +``` + +**Step 2 — cmake**:`FindUbDiag.cmake` 执行时 Layer 1 未命中(submodule 不存在),但 Layer 2 `find_package(UbDiag QUIET)` 成功发现系统 .so。输出 `UbDiag: using system package`。链接系统 .so,不编译 submodule。适用于 CI/CD 等已预装环境。 + +## 用户操作指南 + +作为 Mooncake 新用户,**你不需要做任何选择**。 + +| 你的操作 | 结果 | 编译期日志 | +|---|---|---| +| `git clone --recursive` | 使用真实 UbDiag (submodule),性能诊断完整可用 | `UbDiag: using submodule` | +| `git clone`(不拉 submodule) | 使用本目录 mock,性能探针静默失效,核心功能不受影响 | `UbDiag: using mock` | +| `git clone` + `git submodule update --init` | 从 mock 切换到 submodule | `UbDiag: using submodule` | +| 系统已预装 UbDiag | 链接系统 .so,不编译 submodule | `UbDiag: using system package` | + +以上路径全自动,由 `mooncake-common/FindUbDiag.cmake` 检测路径是否存在决定,**不需要传任何 cmake 参数或环境变量**。 + +### 路径 1:全新 clone(推荐,一步到位) + +```bash +git clone --recursive +cd Mooncake && mkdir build && cd build +cmake .. && make -j +``` + +`--recursive` 自动拉取三个 submodule(pybind11 / yalantinglibs / ubdiag),CMake 自动检测编译。 + +### 路径 2:已有 clone,补拉 submodule + +```bash +cd Mooncake +git submodule update --init --recursive # 拉取 ubdiag 等 submodule +cd build && cmake .. && make -j +``` + +### 路径 3:不拉 submodule,也能编译(完全不使用 UbDiag) + +普通 `git clone`(不带 `--recursive`、不执行 `submodule update`)直接 cmake 编译即可,不需要做任何额外操作。 +CMake 自动回退至本目录的 header-only mock,编译期输出 `UbDiag: using mock`: +- 所有 `PerfPoint` 调用编译为空操作,零运行时开销 +- 不依赖任何 UbDiag 的 .so 或头文件,不需要安装 systemtap-sdt-dev、libbpf 等依赖 +- Mooncake 核心功能完整运行,仅性能探针失效 + +### 路径 4(可选):系统预装 UbDiag + +```bash +cd ubdiag && bash build.sh -r && cd build && sudo make install +cd Mooncake && mkdir build && cd build +cmake .. && make -j +``` + +CMake 通过 `find_package(UbDiag)` 自动发现系统已安装的库。适用于 CI/CD 等已预装环境。 + +## 三层优先级 + +``` +submodule (extern/ubdiag) > system package (find_package QUIET) > mock fallback (本目录) +``` + +每个 `include(FindUbDiag.cmake)` 开头有 `if(TARGET ...) return()`,多次 include 幂等。 + +## 文件说明 + +| 文件 | 用途 | +|---|---| +| `ubdiag/auto_perf.h` | Header-only mock,提供空操作 PerfPoint 和 PerfKey/PerfLevel 定义 | + +## PerfLevel 对齐 + +本 mock 的 PerfLevel 枚举值与真实 UbDiag v0.4.0 保持一致: + +```cpp +#include + +enum class PerfLevel : uint8_t { + SUB_SYSTEM = 1, + KEY_MODULE = 2, + MODULE = 3, + DEBUG = 4, +}; +``` diff --git a/mooncake-common/ubdiag-mock/ubdiag/auto_perf.h b/mooncake-common/ubdiag-mock/ubdiag/auto_perf.h new file mode 100644 index 0000000000..9a3f883729 --- /dev/null +++ b/mooncake-common/ubdiag-mock/ubdiag/auto_perf.h @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2024-present Mooncake contributors +// +// Header-only mock for UbDiag. Provides no-op PerfPoint and PerfKey +// definitions so the codebase compiles without the UbDiag library. +// All perf instrumentation becomes a no-op. +// +// Differences from the real extern/ubdiag/include/ubdiag/auto_perf.h: +// - PerfKey values are all 0 (mock doesn't need unique slot indices). +// - No auto-init static initializer (mock has no SHM, no PerfManager). +// - PerfLevel / PerfPoint are no-ops (no SHM writes). + +#pragma once + +#include +#include + +// Process the perf-key definition file to populate the PerfKey enum. +// UBDIAG_PERF_DEF_FILE must be defined by the includer before this header. +enum class PerfKey : int { +// All keys map to 0 — mock PerfPoint ignores the key entirely. +#define PERF_KEY_DEF(name, file, label) name = 0, +#include UBDIAG_PERF_DEF_FILE +#undef PERF_KEY_DEF +}; + +namespace UbDiag { + +enum class PerfLevel : uint8_t { + SUB_SYSTEM = 1, + KEY_MODULE = 2, + MODULE = 3, + DEBUG = 4, +}; + +class PerfPoint { + public: + explicit PerfPoint(uint32_t slotIndex, PerfLevel level) { + (void)slotIndex; + (void)level; + } + + // Template constructor: accepts any enum type (zero-overhead in real + // UbDiag). Mock forwards to the no-op core constructor. + template >> + explicit PerfPoint(E key, PerfLevel level = PerfLevel::SUB_SYSTEM) + : PerfPoint(static_cast(key), level) {} + + ~PerfPoint() {} + + void Start() {} + void End(int /*rc*/ = 0) {} + void Abandon() {} +}; + +} // namespace UbDiag diff --git a/mooncake-integration/CMakeLists.txt b/mooncake-integration/CMakeLists.txt index 42e3d1d97c..5bd064941b 100644 --- a/mooncake-integration/CMakeLists.txt +++ b/mooncake-integration/CMakeLists.txt @@ -107,7 +107,7 @@ if(WITH_STORE) store/engram_store_py.cpp integration_utils.h) set_target_properties(store PROPERTIES INSTALL_RPATH "$ORIGIN") - find_package(UbDiag REQUIRED) + include(${CMAKE_SOURCE_DIR}/mooncake-common/FindUbDiag.cmake) target_include_directories(store PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/store) target_link_libraries(store PRIVATE UbDiag::ubdiag_lib) diff --git a/mooncake-p2p-store/CMakeLists.txt b/mooncake-p2p-store/CMakeLists.txt index 5b9980de90..03efd1884a 100644 --- a/mooncake-p2p-store/CMakeLists.txt +++ b/mooncake-p2p-store/CMakeLists.txt @@ -2,7 +2,15 @@ add_custom_target(build_p2p_store DEPENDS transfer_engine) add_custom_command( TARGET build_p2p_store - COMMAND bash build.sh ${CMAKE_CURRENT_BINARY_DIR} ${USE_ETCD} ${USE_REDIS} ${USE_HTTP} ${USE_ETCD_LEGACY} ${CMAKE_BINARY_DIR} + COMMAND bash build.sh + ${CMAKE_CURRENT_BINARY_DIR} + ${USE_ETCD} + ${USE_REDIS} + ${USE_HTTP} + ${USE_ETCD_LEGACY} + ${CMAKE_BINARY_DIR} + ${MOONCAKE_UBDIAG_ACTIVE_LAYER} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + VERBATIM ) set_property(TARGET build_p2p_store PROPERTY EXCLUDE_FROM_ALL FALSE) diff --git a/mooncake-p2p-store/build.sh b/mooncake-p2p-store/build.sh index 520227b0c2..2fe3029e2d 100644 --- a/mooncake-p2p-store/build.sh +++ b/mooncake-p2p-store/build.sh @@ -13,8 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -if [ "$#" -ne 6 ]; then - echo "Usage: $0 TARGET_PATH USE_ETCD USE_REDIS USE_HTTP USE_ETCD_LEGACY BUILD_DIR" +if [ "$#" -ne 7 ]; then + echo "Usage: $0 TARGET_PATH USE_ETCD USE_REDIS USE_HTTP USE_ETCD_LEGACY BUILD_DIR UBDIAG_LAYER" exit 1 fi @@ -24,6 +24,7 @@ USE_REDIS=$3 USE_HTTP=$4 USE_ETCD_LEGACY=$5 BUILD_DIR=$6 +UBDIAG_LAYER=$7 cd "src/p2pstore" if [ $? -ne 0 ]; then @@ -35,7 +36,26 @@ EXT_LDFLAGS="-L$BUILD_DIR/mooncake-transfer-engine/src" EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-transfer-engine/src/common/base" EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-common" EXT_LDFLAGS+=" -L$BUILD_DIR/mooncake-common/src" -EXT_LDFLAGS+=" -ltransfer_engine -lubdiag -lbase -lasio -lstdc++ -lnuma -lglog -libverbs -lmlx5 -ljsoncpp -lmooncake_common -lm" +EXT_LDFLAGS+=" -ltransfer_engine" + +case "$UBDIAG_LAYER" in + submodule) + UBDIAG_LIB_DIR="$BUILD_DIR/extern/ubdiag_build/src/sdk" + EXT_LDFLAGS+=" -L$UBDIAG_LIB_DIR -lubdiag" + ;; + system) + EXT_LDFLAGS+=" -lubdiag" + ;; + mock) + echo "P2P Store: using UbDiag mock; skipping -lubdiag" + ;; + *) + echo "Error: Unknown UbDiag layer: $UBDIAG_LAYER" + exit 1 + ;; +esac + +EXT_LDFLAGS+=" -lbase -lasio -lstdc++ -lnuma -lglog -libverbs -lmlx5 -ljsoncpp -lmooncake_common -lm" if [ -d "/usr/local/cuda/lib64/stubs" ]; then EXT_LDFLAGS+=" -L/usr/local/cuda/lib64/stubs" diff --git a/mooncake-store/src/CMakeLists.txt b/mooncake-store/src/CMakeLists.txt index c6328b703e..e184329eb7 100644 --- a/mooncake-store/src/CMakeLists.txt +++ b/mooncake-store/src/CMakeLists.txt @@ -250,8 +250,8 @@ target_link_libraries( ${EXTRA_LIBS} ${SPDK_STATIC_LIBS} asio_shared mooncake_common PRIVATE transfer_engine) -# UbDiag instrumentation -find_package(UbDiag REQUIRED) +# UbDiag instrumentation (resolved by FindUbDiag.cmake: submodule > system > mock) +include(${CMAKE_SOURCE_DIR}/mooncake-common/FindUbDiag.cmake) target_link_libraries(mooncake_store PRIVATE UbDiag::ubdiag_lib) target_include_directories(mooncake_store PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../mooncake-integration/store) diff --git a/mooncake-transfer-engine/src/CMakeLists.txt b/mooncake-transfer-engine/src/CMakeLists.txt index 80c1cd0a3b..8704ed1533 100644 --- a/mooncake-transfer-engine/src/CMakeLists.txt +++ b/mooncake-transfer-engine/src/CMakeLists.txt @@ -1,5 +1,5 @@ file(GLOB ENGINE_SOURCES "*.cpp") -find_package(UbDiag REQUIRED) +include(${CMAKE_SOURCE_DIR}/mooncake-common/FindUbDiag.cmake) add_subdirectory(common) add_subdirectory(transport) @@ -164,6 +164,9 @@ if(USE_EFA) target_link_libraries(transfer_engine PUBLIC fabric efa_transport) endif() if(USE_UB) + target_compile_definitions(transfer_engine PUBLIC USE_UB) message(STATUS "Enabled USE_UB protocol support") target_link_libraries(transfer_engine PUBLIC ub_transport) + target_compile_definitions(transfer_engine PUBLIC USE_UB) + target_compile_definitions(ub_transport PRIVATE USE_UB) endif() diff --git a/scripts/build_rpm.sh b/scripts/build_rpm.sh index e41b241d26..08dd397637 100755 --- a/scripts/build_rpm.sh +++ b/scripts/build_rpm.sh @@ -10,10 +10,19 @@ set -x # Get build directory from environment variable or argument BUILD_DIR="${BUILD_DIR:-${1:-build}}" -BUILD_DIR_ABS="$(pwd)/${BUILD_DIR}" +if [[ "${BUILD_DIR}" = /* ]]; then + BUILD_DIR_ABS="${BUILD_DIR}" +else + BUILD_DIR_ABS="$(pwd)/${BUILD_DIR}" +fi # Get output directory from environment variable or argument OUTPUT_DIR="${OUTPUT_DIR:-${2:-rpm-output}}" +if [[ "${OUTPUT_DIR}" = /* ]]; then + OUTPUT_DIR_ABS="${OUTPUT_DIR}" +else + OUTPUT_DIR_ABS="$(pwd)/${OUTPUT_DIR}" +fi # Detect current host architecture HOST_ARCH=$(uname -m) @@ -44,12 +53,13 @@ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${BUILD_DIR_ABS}/mooncake-common:/usr/lo # Clean previous build echo "Cleaning previous RPM build..." rm -rf rpmbuild/ -rm -rf ${OUTPUT_DIR}/ +rm -rf ${OUTPUT_DIR_ABS}/ # Function to build RPM for a specific platform build_rpm_for_platform() { local PLATFORM=$1 local LIB_DIR="lib64" + local UBDIAG_RPM_FILES="" echo "Building RPM for platform: ${PLATFORM}" @@ -68,7 +78,7 @@ build_rpm_for_platform() { mkdir -p rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM} # Create target directories in BUILDROOT - mkdir -p rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/{usr/{bin,${LIB_DIR},include},etc/mooncake} + mkdir -p rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/{usr/{bin,${LIB_DIR},include},etc/{mooncake,ubdiag}} # ------------------------------------------------------------------------- # Copy executables @@ -170,6 +180,109 @@ build_rpm_for_platform() { else echo "Warning: store.so not found in ${PLATFORM_BUILD_DIR}, skipping..." fi + + # UbDiag runtime artifacts. L1 packages the vendored build output. L2 packages + # the customer-provided system UbDiag selected by FindUbDiag.cmake. The CLI + # and libubdiag must come from the same layer so feature flags and shared + # memory layout stay in sync. Do not package UbDiag headers or CMake package + # metadata here: Layer 2 must remain a customer-provided system package. + local UBDIAG_BUILD_DIR="${PLATFORM_BUILD_DIR}/extern/ubdiag_build" + local UBDIAG_RPM_MANIFEST="${PLATFORM_BUILD_DIR}/mooncake_ubdiag_rpm.env" + local MOONCAKE_UBDIAG_LAYER="" + local MOONCAKE_UBDIAG_CLI_PATH="" + local MOONCAKE_UBDIAG_LIBRARY_PATH="" + local MOONCAKE_UBDIAG_CONFIG_PATH="" + + if [ -f "${UBDIAG_RPM_MANIFEST}" ]; then + echo "Reading UbDiag RPM manifest: ${UBDIAG_RPM_MANIFEST}" + . "${UBDIAG_RPM_MANIFEST}" + fi + + if { [ -z "${MOONCAKE_UBDIAG_LAYER}" ] || [ "${MOONCAKE_UBDIAG_LAYER}" = "submodule" ]; } && [ -d "${UBDIAG_BUILD_DIR}" ]; then + echo "Copying vendored UbDiag CLI and SDK runtime library..." + + if [ -f "${UBDIAG_BUILD_DIR}/src/cli/ubdiag" ]; then + cp "${UBDIAG_BUILD_DIR}/src/cli/ubdiag" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/bin/ + chmod 755 rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/bin/ubdiag + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +/usr/bin/ubdiag" + else + echo "Error: vendored UbDiag build found, but ${UBDIAG_BUILD_DIR}/src/cli/ubdiag is missing" + return 1 + fi + + if compgen -G "${UBDIAG_BUILD_DIR}/src/sdk/libubdiag.so*" >/dev/null; then + for ubdiag_lib in "${UBDIAG_BUILD_DIR}"/src/sdk/libubdiag.so*; do + cp "${ubdiag_lib}" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/${LIB_DIR}/ + done + chmod 755 rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/${LIB_DIR}/libubdiag.so* 2>/dev/null || true + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +/usr/${LIB_DIR}/libubdiag.so*" + elif [ -f "${UBDIAG_BUILD_DIR}/src/sdk/libubdiag.a" ]; then + cp "${UBDIAG_BUILD_DIR}/src/sdk/libubdiag.a" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/${LIB_DIR}/ + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +/usr/${LIB_DIR}/libubdiag.a" + else + echo "Error: vendored UbDiag build found, but libubdiag was not built under ${UBDIAG_BUILD_DIR}/src/sdk" + return 1 + fi + + if [ -f extern/ubdiag/config/ubdiag.conf.example ]; then + cp extern/ubdiag/config/ubdiag.conf.example rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/etc/ubdiag/ubdiag.conf + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +%config(noreplace) /etc/ubdiag/ubdiag.conf" + else + echo "Warning: extern/ubdiag/config/ubdiag.conf.example not found, skipping UbDiag config..." + fi + elif [ "${MOONCAKE_UBDIAG_LAYER}" = "system" ]; then + echo "Copying system UbDiag CLI and SDK runtime library selected by Layer 2..." + + if [ -z "${MOONCAKE_UBDIAG_CLI_PATH}" ] || [ ! -f "${MOONCAKE_UBDIAG_CLI_PATH}" ]; then + echo "Error: Layer 2 selected system UbDiag, but ubdiag CLI was not found" + echo " Expected CLI path from manifest: ${MOONCAKE_UBDIAG_CLI_PATH}" + return 1 + fi + + cp "${MOONCAKE_UBDIAG_CLI_PATH}" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/bin/ubdiag + chmod 755 rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/bin/ubdiag + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +/usr/bin/ubdiag" + + local UBDIAG_SYSTEM_LIB_DIR="" + if [ -n "${MOONCAKE_UBDIAG_LIBRARY_PATH}" ] && [ -e "${MOONCAKE_UBDIAG_LIBRARY_PATH}" ]; then + UBDIAG_SYSTEM_LIB_DIR="$(dirname "${MOONCAKE_UBDIAG_LIBRARY_PATH}")" + fi + if [ -z "${UBDIAG_SYSTEM_LIB_DIR}" ] || ! compgen -G "${UBDIAG_SYSTEM_LIB_DIR}/libubdiag.so*" >/dev/null; then + for ubdiag_lib_dir in /usr/lib64 /usr/local/lib64 /usr/lib /usr/local/lib; do + if compgen -G "${ubdiag_lib_dir}/libubdiag.so*" >/dev/null; then + UBDIAG_SYSTEM_LIB_DIR="${ubdiag_lib_dir}" + break + fi + done + fi + if [ -z "${UBDIAG_SYSTEM_LIB_DIR}" ] || ! compgen -G "${UBDIAG_SYSTEM_LIB_DIR}/libubdiag.so*" >/dev/null; then + echo "Error: Layer 2 selected system UbDiag, but libubdiag.so* was not found" + echo " Expected library path from manifest: ${MOONCAKE_UBDIAG_LIBRARY_PATH}" + return 1 + fi + + for ubdiag_lib in "${UBDIAG_SYSTEM_LIB_DIR}"/libubdiag.so*; do + cp -P "${ubdiag_lib}" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/${LIB_DIR}/ + done + chmod 755 rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/usr/${LIB_DIR}/libubdiag.so* 2>/dev/null || true + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +/usr/${LIB_DIR}/libubdiag.so*" + + if [ -n "${MOONCAKE_UBDIAG_CONFIG_PATH}" ] && [ -f "${MOONCAKE_UBDIAG_CONFIG_PATH}" ]; then + cp "${MOONCAKE_UBDIAG_CONFIG_PATH}" rpmbuild/BUILDROOT/${PACKAGE_NAME}-${PACKAGE_VERSION}-${PACKAGE_RELEASE}.${PLATFORM}/etc/ubdiag/ubdiag.conf + UBDIAG_RPM_FILES="${UBDIAG_RPM_FILES} +%config(noreplace) /etc/ubdiag/ubdiag.conf" + else + echo "Warning: Layer 2 system UbDiag config not found, skipping UbDiag config..." + fi + else + echo "UbDiag layer is '${MOONCAKE_UBDIAG_LAYER:-unknown}', skipping UbDiag CLI packaging..." + fi # ------------------------------------------------------------------------- # Copy header files (only core headers for real_client and dummy_client) @@ -324,6 +437,7 @@ ${PACKAGE_DESCRIPTION} /usr/${LIB_DIR}/libetcd_wrapper.so /usr/${LIB_DIR}/libmooncake_engine.so /usr/${LIB_DIR}/libmooncake_store_python.so +${UBDIAG_RPM_FILES} /usr/include/mooncake/*.h /usr/include/mooncake/*.hpp /etc/mooncake/master.yaml @@ -352,16 +466,16 @@ EOF fi # Create platform-specific output directory - mkdir -p ${OUTPUT_DIR}/${PLATFORM} + mkdir -p ${OUTPUT_DIR_ABS}/${PLATFORM} # Build the RPM rpmbuild -bb \ --define "_topdir $(pwd)/rpmbuild" \ - --define "_rpmdir $(pwd)/${OUTPUT_DIR}" \ + --define "_rpmdir ${OUTPUT_DIR_ABS}" \ rpmbuild/SPECS/${PACKAGE_NAME}-${PLATFORM}.spec # Move RPM to platform-specific directory - mv ${OUTPUT_DIR}/${PLATFORM}/*.rpm ${OUTPUT_DIR}/ 2>/dev/null || true + mv ${OUTPUT_DIR_ABS}/${PLATFORM}/*.rpm ${OUTPUT_DIR_ABS}/ 2>/dev/null || true # Cleanup BUILDROOT for next platform rm -rf rpmbuild/BUILDROOT/ @@ -395,7 +509,7 @@ fi # List created RPM files echo "RPM packages built successfully!" echo "Created RPM files:" -ls -la ${OUTPUT_DIR}/*.rpm 2>/dev/null || echo "No RPM files created" +ls -la ${OUTPUT_DIR_ABS}/*.rpm 2>/dev/null || echo "No RPM files created" # Cleanup -rm -rf rpmbuild/ \ No newline at end of file +rm -rf rpmbuild/