# Performance Optimization Guide

## Overview

This document describes the performance optimizations implemented in the IoTDB Node.js client.

## Performance Benchmarks (2026)

### Write Performance - Multi-Process Cluster Mode

| Configuration | Workers | Clients/Worker | Throughput | Avg Latency |
|---------------|---------|----------------|------------|-------------|
| **Best Config** | **8** | **10** | **5.42M pts/s** | **329ms** |
| Single Process | 1 | 20 | 4.28M pts/s | 107ms |
| Over-parallel | 10 | 10 | 3.81M pts/s | 551ms |

**Best Configuration:**
```bash
WORKER_COUNT=8 CLIENT_NUMBER=10 DEVICE_NUMBER=1000 \
SENSOR_NUMBER=50 BATCH_SIZE_PER_WRITE=500 POOL_MAX_SIZE=10 \
node benchmark/benchmark-table-cluster.js
```

### Node.js vs Java Performance

| Client | Max Throughput | Architecture |
|--------|----------------|--------------|
| Node.js (multi-process) | ~5.5M pts/s | 8 workers × event loop |
| Java iot-benchmark | ~60M pts/s | Multi-threaded |

**Gap Analysis (~11x):**
- Node.js single-threaded architecture limits true parallelism
- Java Thrift implementation has JIT optimization
- Java can use DirectByteBuffer for zero-copy

### Key Optimization Findings

1. **Tablet Size**: 25K points (500 rows × 50 sensors) is optimal
   - Larger tablets (100K) cause latency spikes (3.5s)
   - Smaller tablets increase RPC overhead

2. **Worker Count**: 8 workers is optimal for most servers
   - 10+ workers cause server saturation
   - Each worker needs independent SessionPool

3. **Memory Management**: Use streaming batch processing
   - Build tablets per-loop, not all upfront
   - Prevents OOM for large-scale tests (billions of points)

## Implemented Optimizations

### 1. Buffer Pooling

**Problem**: Frequent buffer allocations and deallocations cause significant GC (Garbage Collection) pressure, especially when serializing large datasets.

**Solution**: Implemented `BufferPool` with size-based pooling strategy:

```typescript
import { globalBufferPool } from '@iotdb/client';

// Buffer pool automatically manages buffers in 7 size classes:
// 1KB, 4KB, 16KB, 64KB, 256KB, 1MB, 4MB

// Get statistics
const stats = globalBufferPool.getStats();
console.log(`Hit rate: ${stats.hitRate}`);
console.log(`Pooled buffers: ${stats.pooledBuffers}`);
```

**Impact**: 
- Reduces GC pressure by 70-80%
- Particularly effective for batch operations
- Automatic cleanup prevents memory bloat

**When to use**:
- Enabled by default via `enableFastSerialization: true`
- Most beneficial for workloads with:
  - Large batch inserts (100+ rows)
  - High-frequency writes
  - Long-running processes

### 2. Fast Serialization

**Problem**: Original serialization used multiple buffer concatenations and intermediate allocations, causing performance bottlenecks.

**Solution**: Implemented type-specific fast serializers in `FastSerializer.ts`:

```typescript
// Old approach (multiple allocations):
const buffer1 = serializeColumn1();
const buffer2 = serializeColumn2();
const result = Buffer.concat([buffer1, buffer2]); // Extra allocation!

// New approach (single pre-allocated buffer):
const totalSize = calculateSize();
const result = Buffer.allocUnsafe(totalSize);
// Write directly to result buffer
```

**Features**:
- Single-pass serialization
- Pre-calculated buffer sizes
- Direct buffer writes (no intermediate arrays)
- Conditional pooling (only for buffers >= 1KB)

**Impact**:
- **1.5-2x faster** serialization
- **50-60% reduction** in memory allocations
- Zero intermediate buffer copies

### 3. Optimized Timestamp Handling

**Problem**: Converting timestamps one-by-one to BigInt and writing to buffer was inefficient.

**Solution**: Batch timestamp conversion with optimized buffer writes:

```typescript
// Optimized timestamp serialization
function serializeTimestamps(timestamps: number[]): Buffer {
  const size = timestamps.length * 8;
  const buffer = size >= 1024 ? globalBufferPool.acquire(size) : Buffer.allocUnsafe(size);
  
  for (let i = 0; i < timestamps.length; i++) {
    buffer.writeBigInt64BE(BigInt(Math.floor(timestamps[i])), i * 8);
  }
  
  return buffer.subarray(0, size);
}
```

**Impact**:
- **20-30% faster** timestamp processing
- Particularly effective for large batches

### 4. Columnar Result Format (Phase 2)

**Problem**: Row-by-row processing with object allocation creates overhead for large result sets.

**Solution**: Added `toColumnar()` API inspired by pg's array mode:

```typescript
const dataSet = await session.executeQueryStatement('SELECT temp, humidity FROM root.test');

// OLD WAY: Object per row (high allocation overhead)
while (await dataSet.hasNext()) {
  const row = dataSet.next();  // Creates RowRecord object
  console.log(row.getValue('temp'));
}

// NEW WAY: Columnar format (zero allocation overhead)
const columnar = await dataSet.toColumnar();
// columnar = {
//   timestamps: [ts1, ts2, ts3, ...],
//   values: [[temp1, temp2, temp3, ...], [humidity1, humidity2, humidity3, ...]],
//   columnNames: ['temp', 'humidity'],
//   columnTypes: ['FLOAT', 'FLOAT']
// }

// Process entire columns at once
const avgTemp = columnar.values[0].reduce((a, b) => a + b) / columnar.values[0].length;
```

**Impact**:
- **2-3x faster** for bulk query processing
- **80-90% reduction** in GC pressure
- Enables vectorized processing
- Perfect for analytics workloads

**When to use**:
- ✅ Small to medium result sets (< 100K rows)
- ✅ Analytics and aggregation workloads
- ✅ When processing entire columns
- ❌ Very large result sets (use iterator pattern)
- ❌ When you need streaming with backpressure

## Configuration

### Enabling/Disabling Fast Serialization

```typescript
import { Session } from '@iotdb/client';

// Enable (default)
const session = new Session({
  host: 'localhost',
  port: 6667,
  enableFastSerialization: true,  // Uses optimized serializers
});

// Disable (fall back to legacy)
const legacySession = new Session({
  host: 'localhost',
  port: 6667,
  enableFastSerialization: false,  // Uses original serializers
});
```

### When to Disable Fast Serialization

You might want to disable fast serialization if:
- Debugging serialization issues
- Running on memory-constrained environments
- Comparing performance with legacy behavior

## Performance Benchmarks

### Write Performance

| Scenario | Legacy | Optimized | Improvement |
|----------|--------|-----------|-------------|
| Small batch (10 rows, 10 columns) | 2.5ms | 1.8ms | **1.4x** |
| Medium batch (100 rows, 10 columns) | 15ms | 6ms | **2.5x** |
| Large batch (1000 rows, 10 columns) | 180ms | 65ms | **2.8x** |
| Mixed data types | 25ms | 10ms | **2.5x** |

### Query Performance (toColumnar vs iterator)

| Result Set Size | Iterator (objects) | toColumnar | Improvement |
|-----------------|-------------------|------------|-------------|
| 1,000 rows | 45ms | 18ms | **2.5x** |
| 10,000 rows | 520ms | 180ms | **2.9x** |
| 100,000 rows | 5800ms | 1900ms | **3.1x** |

*Benchmarks performed on Node.js v20, Intel i7, 16GB RAM*

## Best Practices

### 1. Use Batch Inserts

```typescript
// ❌ BAD: One-by-one inserts
for (let i = 0; i < 1000; i++) {
  await session.insertTablet({
    deviceId: 'root.test.device1',
    measurements: ['temp'],
    dataTypes: [TSDataType.FLOAT],
    timestamps: [Date.now() + i],
    values: [[25.5]],
  });
}

// ✅ GOOD: Batch insert
const batchSize = 100;
await session.insertTablet({
  deviceId: 'root.test.device1',
  measurements: ['temp'],
  dataTypes: [TSDataType.FLOAT],
  timestamps: Array.from({ length: batchSize }, (_, i) => Date.now() + i),
  values: Array.from({ length: batchSize }, () => [25.5]),
});
```

### 2. Use Columnar Format for Analytics

```typescript
// ✅ GOOD: Columnar processing for analytics
const columnar = await dataSet.toColumnar();
const temps = columnar.values[0];

// Vectorized operations
const avg = temps.reduce((a, b) => a + b, 0) / temps.length;
const max = Math.max(...temps);
const min = Math.min(...temps);

await dataSet.close();
```

### 3. Choose the Right Query Method

```typescript
// For small result sets - use toColumnar()
const smallDataSet = await session.executeQueryStatement('SELECT * FROM root.test LIMIT 100');
const columnar = await smallDataSet.toColumnar();
await smallDataSet.close();

// For large result sets - use iterator
const largeDataSet = await session.executeQueryStatement('SELECT * FROM root.test');
while (await largeDataSet.hasNext()) {
  const row = largeDataSet.next();
  await processRow(row);  // Process with backpressure
}
await largeDataSet.close();
```

### 4. Monitor Buffer Pool Usage

```typescript
import { globalBufferPool } from '@iotdb/client';

// After warmup period
setInterval(() => {
  const stats = globalBufferPool.getStats();
  console.log(`Buffer Pool - Hit rate: ${stats.hitRate}, Pooled: ${stats.pooledBuffers}`);
  
  // If hit rate < 50%, consider adjusting batch sizes
  if (parseFloat(stats.hitRate) < 50) {
    console.warn('Low buffer pool hit rate - consider larger batch sizes');
  }
}, 60000); // Check every minute
```

## Future Optimizations (Planned)

### Phase 2 (In Progress)
- [ ] Batch insert helpers
- [x] Query result array mode
- [ ] Cursor/streaming API with backpressure
- [ ] Request pipelining

### Phase 3 (Future)
- [ ] Optional native bindings for critical paths
- [ ] Zero-copy deserialization
- [ ] Custom type parsers
- [ ] Prepared statement caching

## Troubleshooting

### High Memory Usage

```typescript
// Clear buffer pool periodically in long-running processes
import { globalBufferPool } from '@iotdb/client';

// Clear pool every hour to prevent potential memory bloat
setInterval(() => {
  globalBufferPool.clear();
}, 3600000);
```

### Slow Serialization

```typescript
// Enable performance logging
process.env.LOG_LEVEL = 'debug';

// Check serialization timings in logs:
// [PERF] Values serialization: 5ms, buffer size: 4096 bytes
// [PERF] Timestamp serialization (fast=true): 1ms
```

### Unexpected Results

```typescript
// Disable fast serialization for debugging
const session = new Session({
  host: 'localhost',
  port: 6667,
  enableFastSerialization: false,  // Use legacy serializers
});
```

## Contributing

Performance improvements are welcome! When contributing:

1. **Benchmark first**: Establish baseline with existing code
2. **Profile**: Use Node.js profiler to identify bottlenecks
3. **Test thoroughly**: Ensure correctness with existing test suite
4. **Document**: Update this guide with your improvements

## References

- [pg nodejs client](https://github.com/brianc/node-postgres) - Inspiration for buffer management
- [postgres.js](https://github.com/porsager/postgres) - Additional optimization patterns
- [Node.js Buffer Documentation](https://nodejs.org/api/buffer.html)
- [IoTDB Documentation](https://iotdb.apache.org/)

## License

Apache License 2.0
