162 lines
5.6 KiB
Markdown
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
|