dgen-py 0.1.2__cp310-cp310-manylinux_2_24_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Zero-Copy Demo
4
+ ==============
5
+
6
+ Demonstrates TRUE zero-copy data generation and access.
7
+ """
8
+
9
+ import dgen_py
10
+ import numpy as np
11
+ import time
12
+
13
+
14
+ def main():
15
+ print("=" * 60)
16
+ print("dgen-py ZERO-COPY DEMONSTRATION")
17
+ print("=" * 60)
18
+
19
+ size = 100 * 1024 * 1024 # 100 MiB
20
+
21
+ print(f"\nGenerating {size // (1024*1024)} MiB of data...\n")
22
+
23
+ # =========================================================================
24
+ # Step 1: Generate data (Rust allocation)
25
+ # =========================================================================
26
+ start = time.perf_counter()
27
+ data = dgen_py.generate_data(size)
28
+ gen_time = time.perf_counter() - start
29
+ throughput = size / gen_time / 1e9
30
+
31
+ print(f"✓ Generation: {throughput:.2f} GB/s ({gen_time*1000:.1f} ms)")
32
+ print(f" Type: {type(data).__name__}")
33
+ print(f" Size: {len(data):,} bytes")
34
+
35
+ # =========================================================================
36
+ # Step 2: Create memoryview (ZERO COPY - just pointer!)
37
+ # =========================================================================
38
+ start = time.perf_counter()
39
+ view = memoryview(data)
40
+ view_time = time.perf_counter() - start
41
+
42
+ print(f"\n✓ Memoryview: {view_time * 1e6:.1f} µs (ZERO COPY)")
43
+ print(f" Readonly: {view.readonly}")
44
+ print(f" Format: '{view.format}' (unsigned byte)")
45
+ print(f" Size: {len(view):,} bytes")
46
+
47
+ # =========================================================================
48
+ # Step 3: Create numpy array (ZERO COPY - same memory!)
49
+ # =========================================================================
50
+ start = time.perf_counter()
51
+ arr = np.frombuffer(view, dtype=np.uint8)
52
+ arr_time = time.perf_counter() - start
53
+
54
+ print(f"\n✓ Numpy array: {arr_time * 1e6:.1f} µs (ZERO COPY)")
55
+ print(f" Shape: {arr.shape}")
56
+ print(f" Dtype: {arr.dtype}")
57
+ print(f" Size: {arr.nbytes:,} bytes")
58
+
59
+ # =========================================================================
60
+ # Verification: All share same memory
61
+ # =========================================================================
62
+ print("\n" + "=" * 60)
63
+ print("VERIFICATION: All three share the SAME memory location")
64
+ print("=" * 60)
65
+
66
+ # Sample first 10 bytes
67
+ print(f"\nFirst 10 bytes:")
68
+ print(f" Memoryview: {bytes(view[:10]).hex()}")
69
+ print(f" Numpy: {arr[:10].tobytes().hex()}")
70
+ print(f" ✓ Identical!")
71
+
72
+ # Total time breakdown
73
+ total_copy_time = view_time + arr_time
74
+ print(f"\n" + "=" * 60)
75
+ print(f"PERFORMANCE SUMMARY")
76
+ print(f"=" * 60)
77
+ print(f"Generation: {gen_time*1000:6.1f} ms ({throughput:.2f} GB/s)")
78
+ print(f"Memoryview: {view_time*1e6:6.1f} µs (zero-copy)")
79
+ print(f"Numpy: {arr_time*1e6:6.1f} µs (zero-copy)")
80
+ print(f" {'-'*20}")
81
+ print(f"Total copy: {total_copy_time*1e6:6.1f} µs (<< 1% overhead)")
82
+
83
+ # Memory efficiency
84
+ print(f"\n" + "=" * 60)
85
+ print(f"MEMORY EFFICIENCY")
86
+ print(f"=" * 60)
87
+ print(f"Without zero-copy: {size * 3 / (1024**2):.1f} MiB (3 copies)")
88
+ print(f"With zero-copy: {size / (1024**2):.1f} MiB (1 allocation)")
89
+ print(f"Savings: {size * 2 / (1024**2):.1f} MiB (66% reduction)")
90
+
91
+ print(f"\n" + "=" * 60)
92
+ print("✓ TRUE ZERO-COPY: Same performance as Rust!")
93
+ print("=" * 60)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
@@ -0,0 +1,271 @@
1
+ Metadata-Version: 2.4
2
+ Name: dgen-py
3
+ Version: 0.1.2
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: MIT License
7
+ Classifier: License :: OSI Approved :: Apache Software License
8
+ Classifier: Programming Language :: Python :: 3.10
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Rust
12
+ Classifier: Topic :: Software Development :: Libraries
13
+ Classifier: Topic :: System :: Benchmark
14
+ Requires-Dist: numpy>=1.21.0
15
+ Requires-Dist: zstandard>=0.25.0
16
+ Requires-Dist: pytest>=8.0.0 ; extra == 'dev'
17
+ Requires-Dist: pytest-benchmark>=4.0.0 ; extra == 'dev'
18
+ Requires-Dist: maturin>=1.0.0 ; extra == 'dev'
19
+ Requires-Dist: numpy>=2.0.0 ; extra == 'numpy'
20
+ Provides-Extra: dev
21
+ Provides-Extra: numpy
22
+ License-File: LICENSE
23
+ Summary: High-performance random data generation with NUMA optimization and zero-copy Python interface
24
+ Keywords: data-generation,benchmark,numa,performance,zero-copy
25
+ Author-email: Russ Fellows <russ.fellows@gmail.com>
26
+ License: MIT OR Apache-2.0
27
+ Requires-Python: >=3.10
28
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
29
+
30
+ # dgen-rs / dgen-py
31
+
32
+ **High-performance random data generation with controllable deduplication, compression, and NUMA optimization**
33
+
34
+ [![License: MIT OR Apache-2.0](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue)](LICENSE)
35
+ [![Rust Version](https://img.shields.io/badge/rust-1.90+-orange.svg)](https://www.rust-lang.org)
36
+ [![Python Version](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org)
37
+ [![Tests](https://img.shields.io/badge/tests-14%20passing-brightgreen.svg)](#testing)
38
+
39
+ ## Features
40
+
41
+ - 🚀 **Blazing Fast**: 5-15 GB/s per core using Xoshiro256++ RNG
42
+ - 🎯 **Controllable Characteristics**:
43
+ - Deduplication ratios (1:1 to N:1)
44
+ - Compression ratios (1:1 to N:1)
45
+ - 🔬 **NUMA-Aware**: Automatic topology detection and optimization on multi-socket systems
46
+ - 🐍 **Zero-Copy Python API**: Direct buffer writes, no unnecessary copies
47
+ - 📦 **Both Simple and Streaming**: Single-call or incremental generation
48
+ - 🛠️ **Built with Rust**: Memory-safe, production-quality code
49
+
50
+ ## Quick Start
51
+
52
+ ### Python Installation
53
+
54
+ ```bash
55
+ # Install from PyPI (when published)
56
+ pip install dgen-py
57
+
58
+ # Or build from source
59
+ cd dgen-rs
60
+ maturin develop --release
61
+ ```
62
+
63
+ ### Python Usage
64
+
65
+ **Simple API** (generate all at once):
66
+
67
+ ```python
68
+ import dgen_py
69
+
70
+ # Generate 100 MiB incompressible data
71
+ data = dgen_py.generate_data(100 * 1024 * 1024)
72
+ print(f"Generated {len(data)} bytes")
73
+
74
+ # Generate with 2:1 dedup and 3:1 compression
75
+ data = dgen_py.generate_data(
76
+ size=100 * 1024 * 1024,
77
+ dedup_ratio=2.0,
78
+ compress_ratio=3.0
79
+ )
80
+ ```
81
+
82
+ **Zero-Copy API** (write into existing buffer):
83
+
84
+ ```python
85
+ import dgen_py
86
+ import numpy as np
87
+
88
+ # Pre-allocate buffer
89
+ buf = bytearray(1024 * 1024)
90
+
91
+ # Generate directly into buffer (zero-copy!)
92
+ nbytes = dgen_py.fill_buffer(buf, compress_ratio=2.0)
93
+ print(f"Wrote {nbytes} bytes")
94
+
95
+ # Works with NumPy arrays
96
+ arr = np.zeros(100 * 1024 * 1024, dtype=np.uint8)
97
+ dgen_py.fill_buffer(arr, dedup_ratio=2.0, compress_ratio=3.0)
98
+ ```
99
+
100
+ **Streaming API** (incremental generation):
101
+
102
+ ```python
103
+ import dgen_py
104
+
105
+ # Create generator for 1 GiB
106
+ gen = dgen_py.Generator(
107
+ size=1024 * 1024 * 1024,
108
+ dedup_ratio=2.0,
109
+ compress_ratio=3.0,
110
+ numa_aware=True # Auto-detected by default
111
+ )
112
+
113
+ # Generate in chunks
114
+ chunk_size = 8192
115
+ buf = bytearray(chunk_size)
116
+ total = 0
117
+
118
+ while not gen.is_complete():
119
+ nbytes = gen.fill_chunk(buf)
120
+ if nbytes == 0:
121
+ break
122
+
123
+ total += nbytes
124
+ # Process chunk (write to file, network, etc.)
125
+ # ...
126
+
127
+ print(f"Generated {total} bytes")
128
+ ```
129
+
130
+ **NUMA Information**:
131
+
132
+ ```python
133
+ import dgen_py
134
+
135
+ info = dgen_py.get_system_info()
136
+ if info:
137
+ print(f"NUMA nodes: {info['num_nodes']}")
138
+ print(f"Physical cores: {info['physical_cores']}")
139
+ print(f"Deployment: {info['deployment_type']}")
140
+ ```
141
+
142
+ ### Rust Usage
143
+
144
+ ```rust
145
+ use dgen_rs::{generate_data_simple, GeneratorConfig, DataGenerator};
146
+
147
+ // Simple API
148
+ let data = generate_data_simple(100 * 1024 * 1024, 1, 1);
149
+
150
+ // Full configuration
151
+ let config = GeneratorConfig {
152
+ size: 100 * 1024 * 1024,
153
+ dedup_factor: 2,
154
+ compress_factor: 3,
155
+ numa_aware: true,
156
+ };
157
+ let data = dgen_rs::generate_data(config);
158
+
159
+ // Streaming
160
+ let mut gen = DataGenerator::new(config);
161
+ let mut chunk = vec![0u8; 8192];
162
+ while !gen.is_complete() {
163
+ let written = gen.fill_chunk(&mut chunk);
164
+ if written == 0 {
165
+ break;
166
+ }
167
+ // Process chunk...
168
+ }
169
+ ```
170
+
171
+ ## How It Works
172
+
173
+ ### Deduplication
174
+
175
+ Deduplication ratio `N` means:
176
+ - Generate `total_blocks / N` unique blocks
177
+ - Reuse blocks in round-robin fashion
178
+ - Example: 100 blocks, dedup=2 → 50 unique blocks, repeated 2x each
179
+
180
+ ### Compression
181
+
182
+ Compression ratio `N` means:
183
+ - Fill block with high-entropy Xoshiro256++ keystream
184
+ - Add local back-references to achieve N:1 compressibility
185
+ - Example: compress=3 → zstd will compress to ~33% of original size
186
+
187
+ **compress=1**: Truly incompressible (zstd ratio ~1.00-1.02)
188
+ **compress>1**: Target ratio via local back-refs, evenly distributed
189
+
190
+ ### NUMA Optimization
191
+
192
+ On multi-socket systems (NUMA nodes > 1):
193
+ - Detects topology via `/sys/devices/system/node` (Linux)
194
+ - Can pin rayon threads to specific NUMA nodes (optional)
195
+ - Ensures memory locality for maximum bandwidth
196
+
197
+ ## Performance
198
+
199
+ Typical throughput on modern CPUs:
200
+
201
+ - **Incompressible** (compress=1): 5-15 GB/s per core
202
+ - **Compressible** (compress=3): 1-4 GB/s per core
203
+ - **Multi-core**: Near-linear scaling with rayon
204
+
205
+ Benchmark on AMD EPYC 7742 (64 cores):
206
+ ```
207
+ Incompressible: ~500 GB/s (all cores)
208
+ Compress 3:1: ~150 GB/s (all cores)
209
+ ```
210
+
211
+ ## Algorithm Details
212
+
213
+ Based on s3dlio's `data_gen_alt.rs`:
214
+
215
+ 1. **Block-level generation**: 4 MiB blocks processed in parallel
216
+ 2. **Xoshiro256++**: 5-10x faster than ChaCha20, cryptographically strong
217
+ 3. **Integer error accumulation**: Even compression distribution
218
+ 4. **No cross-block compression**: Realistic compressor behavior
219
+ 5. **Per-call entropy**: Unique data across distributed nodes
220
+
221
+ ## Use Cases
222
+
223
+ - **Storage benchmarking**: Generate realistic test data
224
+ - **Network testing**: High-throughput data sources
225
+ - **AI/ML profiling**: Simulate data loading pipelines
226
+ - **Compression testing**: Validate compressor behavior
227
+ - **Deduplication testing**: Test dedup ratios
228
+
229
+ ## Building from Source
230
+
231
+ ```bash
232
+ # Clone repository
233
+ git clone https://github.com/russfellows/dgen-rs.git
234
+ cd dgen-rs
235
+
236
+ # Build Rust library
237
+ cargo build --release
238
+
239
+ # Build Python wheel
240
+ maturin build --release
241
+
242
+ # Install locally
243
+ maturin develop --release
244
+
245
+ # Run tests
246
+ cargo test
247
+ python -m pytest python/tests/
248
+ ```
249
+
250
+ ## Requirements
251
+
252
+ - **Rust**: 1.90+ (edition 2021)
253
+ - **Python**: 3.10+ (for Python bindings)
254
+ - **Platform**: Linux (NUMA detection required)
255
+
256
+ ## License
257
+
258
+ Dual-licensed under MIT OR Apache-2.0
259
+
260
+ ## Credits
261
+
262
+ - Data generation algorithm ported from [s3dlio](https://github.com/russfellows/s3dlio)
263
+ - Built with [PyO3](https://pyo3.rs/) and [Maturin](https://www.maturin.rs/)
264
+
265
+ ## See Also
266
+
267
+ - **s3dlio**: High-performance multi-protocol storage I/O
268
+ - **sai3-bench**: Multi-protocol I/O benchmarking suite
269
+ - **kv-cache-bench**: LLM KV cache storage benchmarking
270
+
271
+
@@ -0,0 +1,14 @@
1
+ dgen_py/__init__.py,sha256=79ZYgtU8WmD_mBKvnJ5iFS4jWgr-4kwHy2ZkN1EyQsA,5168
2
+ dgen_py/__init__.pyi,sha256=gkd3mNrCwYd2I1eLB7SlsqcJCVTfxV04VH2ZlgFSZXQ,1359
3
+ dgen_py/_dgen_rs.cpython-310-x86_64-linux-gnu.so,sha256=9Zh6z6rd0H041R04cx-sX4faLpeuzvrwqZIP3d8rn9Y,850000
4
+ dgen_py/docs/PERFORMANCE.md,sha256=4iBLdr40G_9WVgOV05fyh8is4d4oYhY9MMlUU4trezo,7615
5
+ dgen_py/examples/README.md,sha256=ds1pNjwAZnL0LXhe0EVMDuCsFxezt5N9qpMlvvjNJXQ,5033
6
+ dgen_py/examples/benchmark_cpu_numa.py,sha256=N0Z6h-lf8GxdN9fKv782i2eg65385kNGOPDB2dsvnyw,11500
7
+ dgen_py/examples/benchmark_vs_numpy.py,sha256=rTuN93XpUv_STzTn1HYkmP_dw1YYjUxd1bhUre_LDnQ,4711
8
+ dgen_py/examples/demo.py,sha256=_YlWxqVZockT3Lv6aWcYZ5WIr3KZLoCd9e4hQ_Lujwg,3161
9
+ dgen_py/examples/quick_perf_test.py,sha256=o2GFu74gPKhEEldTeEI6CLgBeXRuZPJDfeb_g-mDzik,3360
10
+ dgen_py/examples/zero_copy_demo.py,sha256=WTrg8o5t5HGYgoy4I2UxbUi5POQ2K8iyPz7wPlopSo4,3473
11
+ dgen_py-0.1.2.dist-info/METADATA,sha256=poGy_DeXvtGuU2bkFq3qj_aNXJee9IU7nlboud7U_cc,7276
12
+ dgen_py-0.1.2.dist-info/WHEEL,sha256=eoKEw9I9Gn4nu_ZUo2vZXZfzt_PDszeNEndfEj9KkmQ,109
13
+ dgen_py-0.1.2.dist-info/licenses/LICENSE,sha256=ZG2WWfkEUQMV0SWnn4DKVsF-2BRjQjmuCxIA9hxmJzY,1648
14
+ dgen_py-0.1.2.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: maturin (1.11.2)
3
+ Root-Is-Purelib: false
4
+ Tag: cp310-cp310-manylinux_2_24_x86_64
@@ -0,0 +1,39 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Russ Fellows
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Apache License 2.0
26
+
27
+ Copyright 2026 Russ Fellows
28
+
29
+ Licensed under the Apache License, Version 2.0 (the "License");
30
+ you may not use this file except in compliance with the License.
31
+ You may obtain a copy of the License at
32
+
33
+ http://www.apache.org/licenses/LICENSE-2.0
34
+
35
+ Unless required by applicable law or agreed to in writing, software
36
+ distributed under the License is distributed on an "AS IS" BASIS,
37
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
38
+ See the License for the specific language governing permissions and
39
+ limitations under the License.