Comprehensive performance testing tools for Apache IoTDB Node.js client, inspired by the thulab/iot-benchmark project.
This benchmark suite provides specialized tools for testing IoTDB write performance:
benchmark-tree.js) - Tests timeseries data modelbenchmark-table.js) - Tests relational data modelbenchmark-table-cluster.js) - NEW Multi-process mode for maximum throughputbenchmark-comparison.js, benchmark-table-comparison.js) - Compare insertion methods| Mode | Configuration | Throughput | Notes |
|---|---|---|---|
| Single Process | 20 clients, 200 devices | 4.28M pts/s | Best single-process |
| Multi-Process | 8 workers × 10 clients | 5.42M pts/s | Recommended |
| Java iot-benchmark | Similar config | ~60M pts/s | Reference |
✅ Multi-Process Cluster Mode - Overcomes Node.js single-thread limitation ✅ Pre-generated Test Data - Eliminates data generation overhead ✅ Memory-Optimized - Streaming batch processing for large-scale tests ✅ Flexible Configuration - Extensive parameters for customizing scenarios ✅ Detailed Metrics - Comprehensive statistics including latency percentiles
Note: The benchmark tools require a working IoTDB instance. If you encounter connection issues, please ensure:
To verify the benchmark tools are correctly installed and configured:
node benchmark/test-benchmark.js
This will test the benchmark infrastructure without requiring IoTDB connection, validating:
Compare the performance of different insertion methods for tree model:
# Run with default settings node benchmark/benchmark-comparison.js # Customize parameters TABLET_COUNT=200 CONCURRENCY=20 node benchmark/benchmark-comparison.js
This benchmark compares:
Compare the performance of different insertion methods for table model:
# Run with default settings node benchmark/benchmark-table-comparison.js # Customize parameters TABLET_COUNT=200 CONCURRENCY=20 node benchmark/benchmark-table-comparison.js
This benchmark compares:
npm install
npm run build
# Using default settings node benchmark/benchmark-tree.js # With custom parameters DEVICE_NUMBER=50 CLIENT_NUMBER=5 node benchmark/benchmark-tree.js
# Using default settings node benchmark/benchmark-table.js # With custom parameters DEVICE_NUMBER=50 CLIENT_NUMBER=5 node benchmark/benchmark-table.js
# Best configuration (5.42M pts/s) IOTDB_HOST=localhost \ WORKER_COUNT=8 \ CLIENT_NUMBER=10 \ DEVICE_NUMBER=1000 \ SENSOR_NUMBER=50 \ LOOP=100 \ BATCH_SIZE_PER_WRITE=500 \ POOL_MAX_SIZE=10 \ node benchmark/benchmark-table-cluster.js
Multi-Process Parameters:
| Variable | Default | Description |
|---|---|---|
WORKER_COUNT | CPU cores | Number of worker processes |
CLIENT_NUMBER | 10 | Concurrent clients per worker |
DEVICE_NUMBER | 1000 | Total devices (distributed across workers) |
POOL_MAX_SIZE | 10 | Connection pool size per worker |
Performance Tips:
All benchmarks support configuration through environment variables. Default values are used if not specified.
| Variable | Default | Description |
|---|---|---|
IOTDB_HOST | localhost | IoTDB server host |
IOTDB_PORT | 6667 | IoTDB server port |
IOTDB_USER | root | Username for authentication |
IOTDB_PASSWORD | root | Password for authentication |
NODE_URLS | - | Multi-node URLs (e.g., "host1:6667,host2:6668") |
| Variable | Default | Description |
|---|---|---|
CLIENT_NUMBER | 10 | Number of concurrent clients |
DEVICE_NUMBER | 100 | Number of devices to simulate |
SENSOR_NUMBER | 10 | Number of sensors per device |
BATCH_SIZE_PER_WRITE | 100 | Data rows per write operation |
LOOP | - | Total execution loops (alternative to TOTAL_DATA_POINTS) |
TOTAL_DATA_POINTS | 100000 | Total data points (used when LOOP not set) |
Note on LOOP mode: When LOOP is set, total data points = DEVICE_NUMBER × BATCH_SIZE × SENSOR_NUMBER × LOOP. Each loop writes one complete batch for all devices (one tablet per device).
| Variable | Default | Description |
|---|---|---|
POINT_STEP | 1000 | Time interval between points (ms) |
TIMESTAMP_PRECISION | ms | Timestamp precision (ms, us, ns) |
STRING_LENGTH | 16 | Length of TEXT/STRING values |
REGENERATE_DATA | false | Force regenerate test data |
DATA_FILE_PATH | ./benchmark/benchmark_data.json | Path to pre-generated data |
Configure the proportion of different sensor types. Must sum to 1.0.
Default distribution:
| Variable | Default | Description |
|---|---|---|
WARMUP_ROUNDS | 0 | Number of warmup iterations |
TEST_ROUNDS | 1 | Number of test iterations |
REPORT_INTERVAL | 5000 | Progress report interval (ms) |
ENABLE_DETAILED_METRICS | true | Enable percentile calculations |
| Variable | Default | Description |
|---|---|---|
POOL_MAX_SIZE | 20 | Maximum connections in pool |
POOL_MIN_SIZE | 5 | Minimum connections in pool |
POOL_MAX_IDLE_TIME | 60000 | Maximum idle time (ms) |
POOL_WAIT_TIMEOUT | 60000 | Wait timeout for connection (ms) |
ENABLE_DEVICE_SESSION_BINDING | false | Bind devices to sessions (requires DEVICE_NUMBER % POOL_MAX_SIZE == 0) |
Device-Session Binding: When enabled, each session is bound to a specific set of devices, avoiding connection redirects and improving performance. Only enable this when DEVICE_NUMBER is evenly divisible by POOL_MAX_SIZE.
# Execute 1000 loops, each writing one batch for all devices LOOP=1000 \ DEVICE_NUMBER=100 \ SENSOR_NUMBER=10 \ BATCH_SIZE_PER_WRITE=100 \ CLIENT_NUMBER=10 \ node benchmark/benchmark-tree.js # Total data points = 100 devices × 100 rows × 10 sensors × 1000 loops = 100,000,000
# Bind 100 devices to 10 sessions (10 devices per session) LOOP=1000 \ DEVICE_NUMBER=100 \ SENSOR_NUMBER=10 \ BATCH_SIZE_PER_WRITE=100 \ POOL_MAX_SIZE=10 \ ENABLE_DEVICE_SESSION_BINDING=true \ node benchmark/benchmark-tree.js
CLIENT_NUMBER=5 \ DEVICE_NUMBER=50 \ SENSOR_NUMBER=5 \ BATCH_SIZE_PER_WRITE=100 \ TOTAL_DATA_POINTS=50000 \ node benchmark/benchmark-tree.js
CLIENT_NUMBER=50 \ DEVICE_NUMBER=1000 \ SENSOR_NUMBER=10 \ BATCH_SIZE_PER_WRITE=1000 \ TOTAL_DATA_POINTS=1000000 \ node benchmark/benchmark-tree.js
NODE_URLS="node1:6667,node2:6667,node3:6667" \ CLIENT_NUMBER=20 \ DEVICE_NUMBER=500 \ node benchmark/benchmark-tree.js
Create a custom configuration file:
// custom-config.js const { createConfig } = require('./benchmark/config'); const config = createConfig({ CLIENT_NUMBER: 10, DEVICE_NUMBER: 100, SENSOR_NUMBER: 8, INSERT_DATATYPE_PROPORTION: { 3: 0.5, // 50% FLOAT 4: 0.3, // 30% DOUBLE 1: 0.2, // 20% INT32 }, }); module.exports = config;
WARMUP_ROUNDS=3 \ TEST_ROUNDS=1 \ CLIENT_NUMBER=10 \ node benchmark/benchmark-tree.js
REPORT_INTERVAL=2000 \ ENABLE_DETAILED_METRICS=true \ CLIENT_NUMBER=10 \ TOTAL_DATA_POINTS=500000 \ node benchmark/benchmark-tree.js
The benchmark reports the following metrics:
================================================================================ BENCHMARK RESULTS ================================================================================ [Execution Time] Duration: 45.23s (45234ms) [Operations] Total Operations: 1000 Successful: 998 Failed: 2 Success Rate: 99.80% [Data Points] Total Points Written: 100,000 [Throughput] Operations/sec: 22.11 Points/sec: 2,210 [Latency (ms)] Min: 15.23ms Max: 1250.45ms Average: 45.23ms P50 (Median): 42.15ms P90: 78.45ms P95: 95.23ms P99: 125.67ms ================================================================================
REGENERATE_DATA=trueMemory Comparison (100K devices, 10 sensors, 100 rows):
benchmark/ ├── config.js # Configuration management ├── data-generator.js # Pre-generate test data ├── schema-manager.js # Metadata registration ├── benchmark-core.js # Core benchmark engine ├── benchmark-tree.js # Tree model entry point ├── benchmark-table.js # Table model entry point └── README.md # This file
POOL_MIN_SIZE to warm up connectionsPOOL_MAX_SIZE based on expected peak concurrencyREGENERATE_DATA=false after first runNote: The benchmark now uses memory-optimized shared batch templates and can handle 100K+ devices with minimal memory.
If you still encounter OOM:
BATCH_SIZE_PER_WRITECLIENT_NUMBERNODE_OPTIONS=--max-old-space-size=4096Memory usage reference (with optimization):
DELETE DATABASE root.benchmark.* (tree model)DROP DATABASE benchmark_db (table model)WARMUP_ROUNDS=3 for stable resultsContributions are welcome! Please:
Apache License 2.0