Skip to content

Commit e1a2162

Browse files
committed
Bytes to bson
1 parent 5a99d9b commit e1a2162

File tree

2 files changed

+535
-15
lines changed

2 files changed

+535
-15
lines changed

bson/_rbson/README.md

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -183,20 +183,94 @@ When these missing features were added to achieve 100% compatibility, the true p
183183
- Edge case handling for all 88 tests
184184
3. **The Fundamental Issue**: Both implementations suffer from the same architectural limitation (Python → Bson enum → bytes), but it only becomes a significant bottleneck when you implement all the features required for production use.
185185

186+
## Direct Byte-Writing Performance Results
187+
188+
### Implementation: `_dict_to_bson_direct()`
189+
190+
A new implementation has been added that writes BSON bytes directly from Python objects without converting to `Bson` enum types first. This eliminates the intermediate conversion layer.
191+
192+
**Architecture Comparison:**
193+
```
194+
Regular: Python objects → Rust Bson enum → BSON bytes
195+
Direct: Python objects → BSON bytes (no intermediate types)
196+
```
197+
198+
### Benchmark Results
199+
200+
Comprehensive benchmarks on realistic document types show **consistent 2x speedup**:
201+
202+
| Document Type | Regular (ops/sec) | Direct (ops/sec) | Speedup |
203+
|--------------|-------------------|------------------|---------|
204+
| User Profile | 99,970 | 208,658 | **2.09x** |
205+
| E-commerce Order | 93,578 | 165,636 | **1.77x** |
206+
| IoT Sensor Data | 136,824 | 312,058 | **2.28x** |
207+
| Blog Post | 65,782 | 134,154 | **2.04x** |
208+
209+
**Average Speedup: 2.04x** (range: 1.77x - 2.28x)
210+
211+
### Performance by Document Composition
212+
213+
| Document Type | Regular (ops/sec) | Direct (ops/sec) | Speedup |
214+
|--------------|-------------------|------------------|---------|
215+
| Simple types (int, str, float, bool, None) | 177,588 | 800,670 | **4.51x** |
216+
| Mixed types | 223,856 | 342,305 | **1.53x** |
217+
| Nested documents | 130,884 | 287,758 | **2.20x** |
218+
| BSON-specific types only | 342,059 | 304,844 | 0.89x |
219+
220+
### Key Findings
221+
222+
1. **Massive speedup for simple types**: 4.51x faster for documents with Python native types
223+
2. **Consistent 2x improvement for real-world documents**: All realistic mixed-type documents show 1.77x - 2.28x speedup
224+
3. **Slight slowdown for pure BSON types**: Documents with only BSON-specific types (ObjectId, Binary, etc.) are 10% slower due to extra Python attribute lookups
225+
4. **100% correctness**: All outputs verified to be byte-identical to the regular implementation
226+
227+
### Why Direct Byte-Writing is Faster
228+
229+
1. **Eliminates heap allocations**: No need to create intermediate `Bson` enum values
230+
2. **Reduces function call overhead**: Writes bytes immediately instead of going through `python_to_bson()``write_bson_value()`
231+
3. **Better for common types**: Python's native types (int, str, float, bool) can be written directly without any conversion
232+
233+
### Implementation Details
234+
235+
The direct approach is implemented in these functions:
236+
- `_dict_to_bson_direct()` - Public API function
237+
- `write_document_bytes_direct()` - Writes document structure directly
238+
- `write_element_direct()` - Writes individual elements without Bson conversion
239+
- `write_bson_type_direct()` - Handles BSON-specific types directly
240+
241+
### Usage
242+
243+
```python
244+
from bson import _rbson
245+
from bson.codec_options import DEFAULT_CODEC_OPTIONS
246+
247+
# Use direct byte-writing approach
248+
doc = {"name": "John", "age": 30, "score": 95.5}
249+
bson_bytes = _rbson._dict_to_bson_direct(doc, False, DEFAULT_CODEC_OPTIONS)
250+
```
251+
252+
### Benchmarking
253+
254+
Run the benchmarks yourself:
255+
```bash
256+
python benchmark_direct_bson.py # Quick comparison
257+
python benchmark_bson_types.py # Individual type analysis
258+
python benchmark_comprehensive.py # Detailed statistics
259+
```
260+
186261
## Steps to Achieve Performance Parity with C Extensions
187262

188-
Based on the analysis in PR #2695, here are the steps needed to match C extension performance:
263+
Based on the analysis in PR #2695 and the direct byte-writing results, here are the steps needed to match C extension performance:
189264

190-
### 1. Eliminate Intermediate Bson Enum (High Impact)
265+
### 1. Eliminate Intermediate Bson Enum (High Impact) - COMPLETED
191266
**Current**: Python → Bson → bytes
192267
**Target**: Python → bytes (direct)
193268

194-
Implement direct BSON byte writing from Python objects without converting to `Bson` enum first. This would require:
195-
- Custom serialization logic for each Python type
196-
- Manual BSON format handling (type bytes, length prefixes, etc.)
197-
- Bypassing the `bson` crate's serialization layer
269+
**Status**: ✅ **Implemented as `_dict_to_bson_direct()`**
270+
271+
**Actual Impact**: **2.04x average speedup** on realistic documents (range: 1.77x - 2.28x)
198272

199-
**Estimated Impact**: 3-4x performance improvement
273+
This brings the Rust extension from ~0.21x (5x slower than C) to **~0.43x (2.3x slower than C)** - a significant improvement!
200274

201275
### 2. Optimize Python API Calls (Medium Impact)
202276
- Reduce `getattr()` calls by caching attribute lookups
@@ -220,15 +294,14 @@ Implement direct BSON byte writing from Python objects without converting to `Bs
220294

221295
**Estimated Impact**: 1.05-1.1x performance improvement
222296

223-
### Combined Potential
224-
If all optimizations are implemented successfully:
225-
- Current: 0.21x (5x slower)
226-
- Target: 0.21x × 3.5 × 1.3 × 1.2 × 1.05 = **~1.13x** (13% faster than C)
297+
### Combined Potential (Updated with Direct Byte-Writing Results)
298+
With direct byte-writing implemented:
299+
- **Before**: 0.21x (5x slower than C)
300+
- **After direct byte-writing**: 0.43x (2.3x slower than C) ✅
301+
- **With all optimizations**: 0.43x × 1.3 × 1.2 × 1.05 = **~0.71x** (1.4x slower than C)
302+
- **Optimistic target**: Could potentially reach **~0.9x - 1.0x** (parity with C)
227303

228-
However, achieving this would require:
229-
- Significant engineering effort (weeks to months)
230-
- Bypassing the `bson` crate (losing its benefits)
231-
- Complex low-level code (harder to maintain)
304+
The direct byte-writing approach has already delivered the largest performance gain (2x). Additional optimizations could close the remaining gap to C extension performance.
232305

233306
## Building
234307

0 commit comments

Comments
 (0)