Files
2026-07-13 12:24:33 +08:00

162 lines
5.6 KiB
Markdown

# LMCache Controller ZMQ Benchmark Tool
This tool performs load testing on LMCache Controller using ZMQ interface to measure message throughput, latency, and system performance.
## Overview
The benchmark tool simulates multiple instances and workers sending various types of messages to the LMCache Controller:
- **BatchedKVOperationMsg**: admit/evict messages via pull socket
- **BatchedP2PLookupMsg**: p2p_lookup messages via reply socket
- **RegisterMsg/DeRegisterMsg/HeartbeatMsg**: worker lifecycle messages
### Key Components
- **constants.py**: Defines ZMQ socket timeouts and other constants
- **config.py**: `ZMQBenchmarkConfig` dataclass for benchmark configuration
- **handlers/**: Operation handlers using Strategy Pattern with dynamic discovery
- Each operation has its own file (e.g., `admit.py`, `evict.py`)
- Automatically discovers and registers all handlers at import time
- Add new operations by creating a new handler file - no need to modify existing code
- **benchmark.py**: `ZMQControllerBenchmark` class with core logic
- **__main__.py**: Argument parsing and main entry point
## Prerequisites
- A running LMCache Controller instance
- Python 3.10+
- Required dependencies: `zmq`, `msgspec`, `psutil`
## Quick Start
### Basic Usage
- Start the controller
```bash
python3 -m lmcache.v1.api_server --host 0.0.0.0 --port 9009 \
--monitor-ports "{\"pull\":7555,\"reply\":7556}" \
--lmcache-worker-timeout 100 --health-check-interval 10
```
- Start the benchmark
```bash
python3 -m lmcache.tools.controller_benchmark \
--monitor-ports "{\"pull\":7555,\"reply\":7556}" \
--num-instances 50 --num-workers 1 --num-keys 1000000 --batch-size 100 \
--operations "admit:35,evict:29,heartbeat:1,p2p_lookup:35"
```
## Command Line Options
| Option | Default | Description |
|--------|---------|-------------|
| `--controller-host` | `localhost` | Controller host address |
| `--monitor-ports` | `{"pull":8100,"reply":8101}` | Monitor ports in JSON format |
| `--duration` | `60` | Benchmark duration in seconds |
| `--batch-size` | `50` | Number of KV operations per batch message |
| `--operations` | `admit:70,evict:25,heartbeat:5` | Operation distribution (name:percentage) |
| `--num-instances` | `10` | Number of instances to simulate |
| `--num-workers` | `1` | Number of workers per instance |
| `--num-locations` | `1` | Number of storage locations |
| `--num-keys` | `10000` | Number of unique keys |
| `--num-hashes` | `100` | Number of hashes for P2P lookup operations |
| `--no-register-first` | `false` | Skip pre-registering workers before benchmark |
## Operation Types
The benchmark supports the following operation types:
| Operation | Description |
|-----------|-------------------------------------------|
| `admit` | Simulates KV cache admission (adds entries) |
| `evict` | Simulates KV cache eviction (removes entries) |
| `p2p_lookup` | Simulates p2p batch lookup messages |
| `register` | Simulates worker registration |
| `deregister` | Simulates worker deregistration |
### Adding New Operations
To add a new operation, simply create a new handler file in `handlers/` directory:
1. Create `handlers/your_operation.py` implementing `OperationHandler` base class
2. Define `operation_name` property and implement required methods
3. The handler will be automatically discovered and registered
No need to modify existing code - the system uses dynamic discovery!
## Output Metrics
The benchmark reports:
- **Overall QPS**: Total messages per second
- **Per-operation QPS**: Messages per second for each operation type
- **Latency statistics**: avg, min, max, p95 (in milliseconds)
- **Error counts**: Number of failed operations
- **Memory usage**: System memory usage during the test
### Sample Output
The following is a sample output from the benchmark ran in my macbook m4 pro.
```
================================================================================
LMCache Controller ZMQ Benchmark Results
================================================================================
Configuration:
Controller URL: 127.0.0.1:7555
Duration: 60 seconds
Batch Size: 100
Operations: {'admit': 35.0, 'evict': 29.0, 'heartbeat': 1.0, 'p2p_lookup': 35.0}
Instances: 50, Workers: 1, Locations: 1, Keys: 1000000
Overall Performance:
Total Requests: 270035
Total Messages: 26736200
Total Time: 60.00s
Overall RPS (Requests/sec): 4500.58
Overall QPS (Messages/sec): 445602.80
Per-Operation Performance:
admit:
RPS (Requests/sec): 1575.23
QPS (Messages/sec): 157523.14
Latency - Avg: 0.016ms, Min: 0.007ms, Max: 0.249ms, P95: 0.031ms
Errors: 0
evict:
RPS (Requests/sec): 1305.13
QPS (Messages/sec): 130513.18
Latency - Avg: 0.016ms, Min: 0.007ms, Max: 1.201ms, P95: 0.031ms
Errors: 0
heartbeat:
RPS (Requests/sec): 45.00
QPS (Messages/sec): 45.00
Latency - Avg: 0.010ms, Min: 0.003ms, Max: 0.138ms, P95: 0.024ms
Errors: 0
p2p_lookup:
RPS (Requests/sec): 1575.21
QPS (Messages/sec): 157521.48
Latency - Avg: 0.440ms, Min: 0.150ms, Max: 6.291ms, P95: 0.843ms
Errors: 0
System Metrics:
Memory Usage - Avg: 62.3%, Max: 63.5%
================================================================================
```
## Troubleshooting
### Send Timeout Error
If you see "Send timeout - Controller may not be running", ensure:
1. The LMCache Controller is running
2. The `--controller-host` and `--monitor-ports` are correct
3. No firewall is blocking the connection
### High Error Rate
If you observe high error rates:
1. Reduce `--batch-size` to decrease message size
2. Increase controller resources
3. Check network connectivity