Skip to content
Open
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
101 changes: 101 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# SPDX-License-Identifier: MIT
# Copyright (c) Huawei Technologies Co., Ltd. 2021-2025. All rights reserved.

cmake_minimum_required(VERSION 3.10)
project(ub_bench C)

set(CMAKE_C_STANDARD 99)
set(CMAKE_SKIP_RPATH TRUE)

if(CROSS_COMPILE)
set(CMAKE_C_COMPILER "${CROSS_COMPILE}")
message(STATUS "CMAKE_C_COMPILER: ${CROSS_COMPILE}")
endif()

set(UB_BENCH_C_FLAGS " -Wall -Werror -Wformat -Wfloat-equal -Wtrampolines -g -O2 \
-fno-strict-aliasing -fstack-protector-strong -D_FORTIFY_SOURCE=2 -fPIE -fPIC")

set(UB_BENCH_FLAGS_ARM64 " -march=armv8-a+crc -DUB_ARCH_ARM64")
set(UB_BENCH_FLAGS_x86_64 " -msse4.2 -DUB_ARCH_X86_64")
if("${X86_CROSS_COMPILATION}" STREQUAL "enable")
set(UB_BENCH_FLAGS_x86_64 " -DUB_ARCH_X86_64")
message(STATUS "x86 cross compilation, disabling msse4.2!")
endif()

if("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "aarch64")
set(CMAKE_C_FLAGS "${UB_BENCH_C_FLAGS} ${UB_BENCH_FLAGS_ARM64}")
else()
set(CMAKE_C_FLAGS "${UB_BENCH_C_FLAGS} ${UB_BENCH_FLAGS_x86_64}")
endif()

set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -rdynamic -pie \
-Wl,-z,noexecstack,-z,relro,-z,now")

if("${ASAN}" STREQUAL "enable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address -fsanitize-recover=address \
-fsanitize=leak -fsanitize=undefined -fno-omit-frame-pointer")
message(STATUS "ASAN enabled")
endif()

if("${PERF_CYCLE}" STREQUAL "enable")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DPERF_CYCLE_FLAG")
message(STATUS "PERF_CYCLE enabled")
endif()

message(STATUS "CMAKE_C_FLAGS = ${CMAKE_C_FLAGS}")

find_library(URMA_LIB NAMES urma)
if(NOT URMA_LIB)
message(FATAL_ERROR
"liburma not found. Please install UMDK first.")
endif()
message(STATUS "Found urma: ${URMA_LIB}")

find_library(URMA_COMMON_LIB NAMES urma_common)
if(NOT URMA_COMMON_LIB)
message(FATAL_ERROR
"liburma_common not found. Please install UMDK first.")
endif()
message(STATUS "Found urma_common: ${URMA_COMMON_LIB}")

find_path(URMA_INCLUDE_DIR urma_api.h
PATHS /usr/include/ub/umdk/urma
NO_DEFAULT_PATH
)
if(NOT URMA_INCLUDE_DIR)
message(FATAL_ERROR
"urma headers not found. Please install UMDK first.")
endif()
message(STATUS "Found urma headers: ${URMA_INCLUDE_DIR}")

add_executable(ub_bench
src/ub_bench.c
src/ub_bench_hist.c
src/ub_bench_run.c
src/ub_bench_log.c
src/ub_bench_mgmt.c
src/ub_bench_mgmt_tcp.c
src/ub_bench_mgmt_ub.c
src/ub_bench_parameters.c
src/ub_bench_resources.c
src/ub_bench_run_test.c
)

target_include_directories(ub_bench
PRIVATE
${URMA_INCLUDE_DIR}
${CMAKE_SOURCE_DIR}/include/ub
${CMAKE_SOURCE_DIR}/src
)

target_link_libraries(ub_bench
PRIVATE
${URMA_LIB}
${URMA_COMMON_LIB}
pthread
m
)

install(TARGETS ub_bench
DESTINATION /usr/bin
)
169 changes: 169 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1 +1,170 @@
# UBBench

URMA 性能基准测试工具,基于 urma_perftest 演进,新增带宽与时延同时采集、QPS 限速、QPS 扫描等特性。

## 1. 功能概述

涵盖收发(SEND)、读(READ)、写(WRITE)、原子操作(ATOMIC)四类语义,每种语义支持时延和带宽测试。区分 server 端和 client 端分别起 ub_bench 进程开展测试并输出测试结果。

### 与 urma_perftest 的关系

- 完全兼容 urma_perftest 的所有命令和参数
- LAT 模式(write_lat/read_lat/send_lat/atomic_lat)代码与 urma_perftest 一致
- BW 模式新增两种发包方式:
- **顺序模式(sequential,默认)**:post 一个 → 等完成 → QPS 间隔 → post 下一个,逐包精确采集时延
- **流水线模式(pipeline)**:post 满队列 → 批量 poll → 重复,最大带宽吞吐

### 新增特性

| 特性 | 参数 | 说明 |
|------|------|------|
| 带宽+时延同时采集 | 默认行为 | 顺序模式逐包采集时延(histogram),同时输出带宽 |
| QPS 限速 | `--qps` | 每线程限速,总 QPS = threads × qps |
| QPS 扫描 | `--sweep` | 线性扫描 QPS,自动找到带宽时延拐点 |
| 多线程 | `--threads` | 每线程独立 jetty + CQ,无锁并行 |
| 纯带宽模式 | `--bw-only` | 跳过时延采集,最大化带宽 |

## 2. 命令格式

```
Usage: ub_bench command [command options]
ub_bench URMA benchmark tool
Command syntax:
read_lat Test for read latency.
write_lat Test for write latency.
send_lat Test for send latency.
atomic_lat Test for atomic latency.
read_bw Test for read bandwidth.
write_bw Test for write bandwidth.
send_bw Test for send bandwidth.
atomic_bw Test for atomic bandwidth.
```

## 3. 使用示例

### 时延测试

```bash
# server 端
ub_bench write_lat -d <DEV_NAME> -s [SIZE] -n [ITERATIONS]

# client 端
ub_bench write_lat -d <DEV_NAME> -s [SIZE] -n [ITERATIONS] -S <SERVER_IP>
```

### 带宽测试(pipeline 模式,对标 urma_perftest)

```bash
# server 端
ub_bench write_bw -d <DEV_NAME> -s [SIZE] --mode pipeline --bw-only

# client 端
ub_bench write_bw -d <DEV_NAME> -s [SIZE] -S <SERVER_IP> --mode pipeline --bw-only
```

### 带宽 + 时延同时采集(sequential 模式)

```bash
# server 端
ub_bench write_bw -d <DEV_NAME> -s [SIZE]

# client 端
ub_bench write_bw -d <DEV_NAME> -s [SIZE] -S <SERVER_IP>
```

输出示例:
```
---- ub_bench Report ----
actual_QPS target_QPS BW_avg[MiB/s] MsgRate[Mpps] t_min[us] t_median[us] t_avg[us] P99[us] P99.9[us] P99.99[us] P99.999[us] Pmax[us]
769160 0 48073 0.769160 3.25 12.56 12.74 20.02 22.76 25.44 34.32 297.03
```

### 多线程带宽测试

```bash
# 10 线程,CTP 模式
numactl --cpunodebind=0 --membind=0 ub_bench write_bw -d <DEV_NAME> --ctp -S <SERVER_IP> -s 1048576 --threads 10
```

### QPS 限速测试

```bash
# 每线程 100K QPS,10 线程,总 1M QPS
ub_bench write_bw -d <DEV_NAME> --ctp -S <SERVER_IP> -s 65536 --threads 10 --qps 100000
```

### QPS 扫描(找带宽时延拐点)

```bash
# 从 100K 到 1.5M QPS,步长 100K,每步 10 秒
ub_bench write_bw -d <DEV_NAME> --ctp -S <SERVER_IP> -s 65536 --threads 10 \
--sweep 100000:1500000:100000 --sweep-duration 10
```

### CTP 传输层

```bash
# 加 --ctp 使用 CTP 传输层(bonding 设备)
ub_bench write_bw -d bonding_dev_0 --ctp -S <SERVER_IP> -s 65536
```

## 4. 新增参数说明

| 参数 | 类型 | 说明 | 默认值 |
|------|------|------|--------|
| `--mode <mode>` | string | BW 测试模式:sequential(默认)或 pipeline | sequential |
| `--threads <N>` | uint32 | 工作线程数,每线程独立 jetty + CQ | 1 |
| `--qps <Q>` | uint64 | 每线程 QPS 限速(0=不限速),仅 BW sequential 模式 | 0 |
| `--sweep <start:end:step>` | string | 线性 QPS 扫描,每步增加 step,仅 sequential 模式 | - |
| `--sweep-duration <sec>` | uint32 | 每个 sweep 步骤持续时间 | 10 |
| `--bw-only` | bool | 跳过时延采集,纯带宽测试 | false |

### 参数约束

- `--mode pipeline` 仅用于 BW 测试
- `--qps` 仅用于 BW sequential 模式
- `--sweep` 仅用于 BW sequential 模式,不支持 bidirection 和 send_bw
- `--mode sequential` 不支持 `--infinite`、`--bidirection`、`--all`
- `--threads` 不支持 `--infinite`
- `--bidirection` 不支持 sequential 模式、多线程、pipeline + 时延采集

## 5. 两种模式对比

| | 顺序模式(sequential) | 流水线模式(pipeline) |
|---|---|---|
| **发包方式** | post 1 个 → poll 1 个 → post 下一个 | post 满队列(128) → 批量 poll |
| **jfs_depth** | 1 | 128 |
| **cq_mod** | 1(每 WR 生成 CQE) | 100(100 WR 生成 1 个 CQE) |
| **时延采集** | 逐包精确(tcompleted - tposted) | user_ctx 携带时间戳,CQE 带回 |
| **--qps** | 支持 | 不支持 |
| **--sweep** | 支持 | 不支持 |
| **--bw-only** | 可关闭时延采集 | 可关闭时延采集 |
| **带宽** | 大包接近 link,小包需多线程 | 接近 link |
| **时延含义** | 真实单包完成时间 | 含排队等待(系统时延) |

## 6. 编译

### 依赖

- UMDK 用户态库(urmacore 等)
- cmake >= 3.10
- gcc / g++

### 编译步骤

```bash
cd UBBench
mkdir build && cd build
cmake ..
make -j$(nproc)
```

编译产物:`build/ub_bench`

## 7. 原有参数

ub_bench 保留了 urma_perftest 的全部参数,包括但不限于:

`-d/--dev` `-S/--server` `-s/--size` `-n/--iters` `-D/--duration` `-J/--jettys` `-T/--jfs_depth` `-Q/--cq_mod` `-a/--all` `-B/--bidirection` `-b/--simplex_mode` `--ctp` `--ctp` `--rate_limit` `--burst_size` `--enable_credit` `--enable_imm` `--enable_notify` `--use_jfce` `--use_flat_api` `--lock_free` `--trans_mode` `--inline_size` `--jfr_depth` `--jfs_post_list` `--sge_num` `--pair_num` `--bond_mode` `--bond_level` 等。

执行 `ub_bench -h` 查看完整参数列表。
53 changes: 53 additions & 0 deletions include/ub/ub_get_clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* SPDX-License-Identifier: MIT
* Copyright (c) Huawei Technologies Co., Ltd. 2022-2025. All rights reserved.
* Description: clock for ub_bench
* Author: Qian Guoxin
* Create: 2022-04-03
* Note:
* History: 2022-04-03 create file
*/

#ifndef UB_GET_CLOCK_H
#define UB_GET_CLOCK_H

#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C"
{
#endif

#define CLOCK_SIZE_OF_INT (32)

#if defined(__x86_64__)
static inline uint64_t get_cycles(void)
{
uint32_t low, high;
uint64_t val;
asm volatile ("rdtsc" : "=a" (low), "=d" (high));
val = high;
val = (val << CLOCK_SIZE_OF_INT) | low;
return val;
}
#elif defined(__aarch64__)
static inline uint64_t get_cycles(void)
{
uint64_t freq;
asm volatile("isb" : : : "memory");
asm volatile("mrs %0, cntvct_el0" : "=r" (freq));
return freq;
}
#else
#warning get_cycles not implemented
#endif

/* Warning: Function takes more than 200 ms to run. */
extern double get_cpu_mhz(bool cpu_freq_warn);

#ifdef __cplusplus
}
#endif

#endif
Loading