UBRing is a high-performance RPC implementation in brpc that leverages shared memory for inter-process communication (IPC). It supports both local shared memory (POSIX IPC) and remote shared memory (ubs-mem), providing ultra-low latency communication between processes.
Traditional RPC frameworks typically use network sockets for communication, which introduces significant overhead due to kernel involvement, context switches, and data copying. UBRing addresses this by using shared memory as the communication medium, allowing direct memory access between processes with minimal kernel intervention.
Key advantages of UBRing:
UBRing supports two types of shared memory backends, controlled by the ub_shm_type flag:
This is the default mode, using standard POSIX shared memory for local IPC. Processes on the same machine can communicate directly through shared memory regions.
This mode uses ubs-mem (Unified Block Storage Memory), an open-source remote shared memory framework from openEuler. It enables shared memory communication across nodes in a rack, similar to RDMA but with simpler deployment requirements.
UBS-Mem Open Source: https://atomgit.com/openeuler/ubs-mem
Required Libraries:
libubsm_sdk.so - UBS-Mem SDK library (installed at /usr/local/ubs_mem/lib/libubsm_sdk.so)dlopen() and uses functions like ubsmem_initialize(), ubsmem_create_region(), ubsmem_shmem_allocate(), ubsmem_shmem_map(), etc.UBS-Mem Key Functions:
ubsmem_init_attributes() - Initialize UBS-Mem attributesubsmem_initialize() - Initialize UBS-Mem libraryubsmem_finalize() - Finalize UBS-Mem libraryubsmem_create_region() - Create a shared memory regionubsmem_shmem_allocate() - Allocate shared memoryubsmem_shmem_map() - Map shared memory to local address spaceubsmem_shmem_unmap() - Unmap shared memoryubsmem_shmem_deallocate() - Deallocate shared memoryubsmem_destroy_region() - Destroy a shared memory regionThe architecture is designed to support CXL (Compute Express Link) based remote shared memory in the future, enabling even more flexible distributed memory sharing.
To build brpc with UBRing support, use the following commands:
# Build brpc with UBRing support cd /path/to/brpc cmake -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DWITH_UBRING:BOOL=ON cmake --build build -j 8 # Build the ubring_performance example cd /path/to/brpc/example/ubring_performance cmake -B build cmake --build build -j 8
To build brpc with UBRing support using Bazel:
# Build brpc with UBRing support cd /path/to/brpc bazel build //... --define=with_ubring=true # Build the ubring_performance example bazel build //example/ubring_performance/...
The shared memory backend is controlled by the --ub_shm_type flag:
# Use POSIX IPC (default) ./your_program --ub_shm_type=1 # Use UBS-Mem ./your_program --ub_shm_type=2
brpc provides a performance test example at example/ubring_performance/.
cd example/ubring_performance mkdir -p build && cd build cmake .. make
# Run with POSIX IPC ./ubring_performance_server --ub_shm_type=1 # Run with UBS-Mem ./ubring_performance_server --ub_shm_type=2
# Run with POSIX IPC ./ubring_performance_client --ub_shm_type=1 --server=127.0.0.1:8000 # Run with UBS-Mem ./ubring_performance_client --ub_shm_type=2 --server=<remote_ip>:8000
| Option | Description | Default |
|---|---|---|
--ub_shm_type | Shared memory type (1=IPC, 2=UBS-Mem) | 1 |
--server | Server address | 127.0.0.1:8000 |
--thread_num | Number of client threads | 1 |
--request_num | Total requests per thread | 1000000 |
--timeout_ms | Request timeout in milliseconds | 1000 |
graph TD subgraph Client Process A[Client] end subgraph Server Process B[Server] end subgraph Shared Memory C[SHM Manager] D[IPC Backend] E[UBS-Mem Backend] end A -->|Direct Memory Access| C B -->|Direct Memory Access| C C --> D C --> E style A fill:#636,color:#fff,stroke:#333,stroke-width:2px style B fill:#369,color:#fff,stroke:#333,stroke-width:2px style C fill:#396,color:#fff,stroke:#333,stroke-width:2px
The UBRing architecture consists of:
shm_mgr.cpp)The shared memory manager (shm_mgr.cpp) provides a unified interface for different shared memory backends:
ShmMgrInit() - Initializes the shared memory subsystemShmLocalMalloc() - Allocates shared memory for local useShmRemoteMalloc() - Allocates shared memory accessible by remote nodesShmFree() - Releases shared memory resourcesUBRing uses a high-precision timer system (timer_mgr.cpp) for connection management and timeout handling, supporting both epoll (Linux) and kqueue (macOS).