Documentation Index
Fetch the complete documentation index at: https://mintlify.com/Neumenon/cowrie/llms.txt
Use this file to discover all available pages before exploring further.
Overview
This guide provides practical optimization strategies for both Gen1 and Gen2 codecs. Follow these guidelines to achieve optimal performance for your use case.When to Use Gen1 vs Gen2
| Use Case | Recommended | Why |
|---|---|---|
| Simple JSON APIs | Gen1 | Faster, simpler, lower latency |
| Repeated schemas (logs, events) | Gen2 | Dictionary coding saves ~50% |
| ML pipelines (tensors, images) | Gen2 | Native ML type support |
| Graph data (GNN) | Gen2 | Node, Edge, GraphShard types |
| Embedded/IoT | Gen1 | Smaller code footprint |
| Real-time systems | Gen1 | Single-pass, predictable latency |
| Bulk data transfer | Gen2 + compression | Best compression ratio |
| High-frequency trading | Gen1 | Minimal encode/decode time |
Array Promotion Optimization
What is Array Promotion?
When encoding arrays with 4+ elements of the same numeric type, Cowrie automatically promotes them to typed arrays (Int64Array, Float64Array, StringArray) for more efficient encoding.Threshold: 4 Elements
- Typed array overhead: 2-3 bytes (tag + length varint)
- Generic array: 1 byte per element tag + value
- Break-even point: ~4 elements
Manual Control (Advanced)
Some implementations allow overriding the threshold:- Lower threshold (2-3): Dense numeric workloads (ML, scientific)
- Higher threshold (8-10): Mixed data with small arrays
Gen2 Dictionary Coding
How Dictionary Coding Works
Gen2 collects all unique object keys during encoding and stores them once in the header. Objects then reference keys by index (varint). Example:- JSON: 48KB (keys repeated 1000 times)
- Gen2: 23KB (keys stored once, 52% reduction)
Optimizing Dictionary Usage
Best case: Homogeneous arrays of objectsCompression Tradeoffs
Gen2 supports optional compression (gzip, zstd):When to Enable Compression
Enable when:- Network bandwidth is constrained
- Storage cost matters
- Data has repetitive patterns
- Decode latency is acceptable
- CPU is constrained
- Ultra-low latency required
- Data is already compressed (images, audio)
- Throughput > bandwidth
Compression Ratios
| Data Type | Gen2 Uncompressed | Gen2 + gzip | Gen2 + zstd |
|---|---|---|---|
| Text-heavy JSON | 100% | ~30-40% | ~25-35% |
| Numeric arrays | 100% | ~60-70% | ~50-60% |
| Mixed data | 100% | ~50-60% | ~40-50% |
| Graph data | 100% | ~40-50% | ~35-45% |
- gzip: 3-5x slower encode, 2-3x slower decode
- zstd: 2-3x slower encode, 1.5-2x slower decode
Compression Example
Memory Optimization
Streaming Large Payloads
For large datasets, use streaming APIs to avoid loading everything into memory: Gen1 - Record-by-Record:Column-wise Access (Gen2 Only)
Read specific fields without deserializing entire objects:- Analytics queries (SELECT name, age FROM data)
- Partial updates
- Large objects with many fields
Graph Type Optimization
Batch Operations
Use batch types for bulk operations:- Single dictionary for all nodes
- Efficient batch encoding
- 30-40% smaller than encoding nodes individually
GraphShard for Mini-batches
For GNN training, use GraphShard to encode complete subgraphs:Language-Specific Tips
Go
- Use
gen1.Encode()directly for simple types - Preallocate buffers for repeated encoding
- Use
sync.Poolto reuse encoder/decoder instances
Python
- Use C extension for performance-critical paths
- Batch operations to amortize overhead
- Consider PyPy for 2-3x speedup
Rust
- Use
&[u8]slices to avoid allocations - Enable
simdfeature for varint decoding - Use
rkyvintegration for zero-copy deserialization
TypeScript/JavaScript
- Use ArrayBuffer for binary data
- Avoid copying with TypedArray views
- Use Web Workers for background encoding
Profiling and Measurement
Measuring Performance
Go:Common Bottlenecks
-
String encoding: UTF-8 validation is expensive
- Fix: Use bytes when possible, cache validated strings
-
Dictionary building: Linear scan of keys
- Fix: Use Gen1 if schema is unpredictable
-
Memory allocations: Frequent small allocations
- Fix: Preallocate buffers, use object pools
-
Nested depth: Recursive encoding/decoding
- Fix: Flatten structures when possible
Best Practices Summary
- Choose the right format: Gen1 for speed, Gen2 for size
- Use typed arrays: Let promotion threshold work for you
- Batch graph operations: Leverage NodeBatch/EdgeBatch
- Stream large data: Avoid loading everything into memory
- Profile first: Measure before optimizing
- Test compression: May provide 2-3x size reduction
- Cache encoders: Reuse encoder instances in hot paths
- Validate assumptions: Run benchmarks on your data
Next Steps
- See Benchmarks for real numbers
- See Comparison for format selection
- Profile your application to identify bottlenecks