Packages
snakepit
0.4.0
0.13.0
0.12.0
0.11.1
0.11.0
0.10.1
0.10.0
0.9.1
0.9.0
0.8.9
0.8.8
0.8.7
0.8.6
0.8.5
0.8.4
0.8.3
0.8.2
0.8.1
0.8.0
0.7.7
0.7.6
0.7.5
0.7.4
0.7.3
0.7.2
0.7.1
0.7.0
0.6.11
0.6.10
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.2
0.6.1
0.6.0
0.5.1
0.5.0
0.4.3
0.4.2
0.4.1
0.4.0
0.3.3
0.3.2
0.3.1
0.3.0
0.2.1
0.2.0
0.1.2
0.1.1
0.1.0
High-performance pooler and session manager for external language integrations. Supports Python, Node.js, Ruby, and more with gRPC streaming, session management, and production-ready process cleanup.
Current section
Files
Jump to
Current section
Files
priv/python/BINARY_SERIALIZATION.md
# Binary Serialization Guide
## Overview
The Snakepit bridge automatically uses binary serialization for large tensor and embedding data to improve performance. This guide explains how it works and how to use it effectively.
## Automatic Binary Encoding
When variable data exceeds 10KB (10,240 bytes), the system automatically switches from JSON to binary encoding:
- **Small data (<10KB)**: Uses JSON for readability and debugging
- **Large data (>10KB)**: Uses binary for performance
## Supported Types
Binary serialization is currently available for:
- `tensor`: Multi-dimensional arrays with shape information
- `embedding`: Vector representations (1D arrays)
## Python Usage
### Basic Example
```python
from snakepit_bridge import SessionContext
import numpy as np
class MLAdapter:
def process_large_data(self, ctx: SessionContext):
# Create a large tensor (>10KB)
large_tensor = np.random.randn(100, 100).tolist() # ~80KB
# This automatically uses binary serialization
ctx.register_variable("my_tensor", "tensor", {
"shape": [100, 100],
"data": large_tensor
})
# Retrieval is transparent - handles binary automatically
retrieved = ctx["my_tensor"]
print(f"Shape: {retrieved['shape']}")
```
### Performance Example
```python
import time
def benchmark_serialization(ctx: SessionContext):
# Small data - uses JSON
small_data = list(range(100)) # ~800 bytes
start = time.time()
ctx.register_variable("small", "embedding", small_data)
print(f"Small data: {time.time() - start:.3f}s")
# Large data - uses binary
large_data = list(range(10000)) # ~80KB
start = time.time()
ctx.register_variable("large", "embedding", large_data)
print(f"Large data: {time.time() - start:.3f}s")
# Typically 5-10x faster!
```
## Technical Details
### Serialization Format
- **Python side**: Uses `pickle` with highest protocol
- **Elixir side**: Uses Erlang Term Format (ETF)
- **Wire format**: Protocol Buffers with separate binary field
### Threshold Calculation
The 10KB threshold is based on the estimated serialized size:
- For tensors: `len(data) * 8` bytes (assuming float64)
- For embeddings: `len(array) * 8` bytes
### Binary Message Structure
When binary serialization is used:
1. **Metadata** (in `value` field):
```json
{
"shape": [100, 100],
"dtype": "float32",
"binary_format": "pickle",
"type": "tensor"
}
```
2. **Binary Data** (in `binary_value` field):
- Pickled Python object containing the actual data
## Best Practices
1. **Use Appropriate Types**: Always use `tensor` or `embedding` types for numerical data
2. **Batch Large Operations**: Group multiple large variables in batch updates
3. **Monitor Memory**: Binary data is held in memory during transfer
4. **Profile Your Data**: Check if your typical data sizes benefit from binary encoding
## Limitations
1. **Type Support**: Only `tensor` and `embedding` types use binary serialization
2. **Debugging**: Binary data is not human-readable in logs
3. **Compatibility**: Binary format is internal - use JSON for external APIs
## Configuration
Currently, the 10KB threshold is not configurable. This value was chosen as optimal for most workloads:
- Keeps small data human-readable
- Maximizes performance for large data
- Minimizes overhead of format detection