fastsimdjson 0.4.0__tar.gz → 0.6.0__tar.gz

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.
Files changed (25) hide show
  1. {fastsimdjson-0.4.0/src/fastsimdjson.egg-info → fastsimdjson-0.6.0}/PKG-INFO +55 -1
  2. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/README.md +54 -0
  3. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/pyproject.toml +1 -1
  4. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/src/fastsimdjson.cpp +697 -26
  5. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0/src/fastsimdjson.egg-info}/PKG-INFO +55 -1
  6. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/tests/test_stream.py +159 -0
  7. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/MANIFEST.in +0 -0
  8. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/setup.cfg +0 -0
  9. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/setup.py +0 -0
  10. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/src/fastsimdjson.egg-info/SOURCES.txt +0 -0
  11. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/src/fastsimdjson.egg-info/dependency_links.txt +0 -0
  12. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/src/fastsimdjson.egg-info/requires.txt +0 -0
  13. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/src/fastsimdjson.egg-info/top_level.txt +0 -0
  14. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/tests/test_dumps.py +0 -0
  15. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/tests/test_files.py +0 -0
  16. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/tests/test_lazy.py +0 -0
  17. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/tests/test_loads.py +0 -0
  18. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/simdjson.cpp +0 -0
  19. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/simdjson.h +0 -0
  20. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/simdutf.cpp +0 -0
  21. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/simdutf.h +0 -0
  22. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/simdutf_c.h +0 -0
  23. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/zmij-LICENSE +0 -0
  24. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/zmij.cc +0 -0
  25. {fastsimdjson-0.4.0 → fastsimdjson-0.6.0}/vendor/zmij.h +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fastsimdjson
3
- Version: 0.4.0
3
+ Version: 0.6.0
4
4
  Summary: Fast JSON parsing for Python, built on simdjson
5
5
  Author-email: Daniel Lemire <daniel@lemire.me>
6
6
  License-Expression: Apache-2.0
@@ -197,6 +197,42 @@ returned, otherwise `JSONDecodeError` reports `json`'s message and the
197
197
  position in the whole input. A truncated last document is an error. The
198
198
  views returned by `parse_many` remain valid after the iterator moves on.
199
199
 
200
+ ### Streams on several threads: `threads=N` and `map_many`
201
+
202
+ On free-threaded Python (3.14t and newer), a stream can be parsed by several
203
+ threads at once:
204
+
205
+ ```python
206
+ docs = fastsimdjson.loads_many(data, threads=16) # a list, in order
207
+ views = fastsimdjson.parse_many(data, threads=16) # a list of views
208
+ # fn runs in the threads too, on each document; its results, in order:
209
+ scores = fastsimdjson.map_many(score, data, threads=16)
210
+ ```
211
+
212
+ With `threads`, `loads_many` and `parse_many` return a list of all the
213
+ documents instead of an iterator. `map_many(fn, data, **kw)` returns
214
+ `[fn(doc) for doc in loads_many(data, **kw)]` (`parse_many` with
215
+ `lazy=True`), with `fn` called in the threads. `threads=0` (or `None`) uses
216
+ one thread per processor; small inputs use fewer threads (about one per
217
+ 512 KB). The input is cut into chunks at newlines (before each `\x1e` for
218
+ `json_seq`), so `threads` works with the formats `"whitespace"`, `"lines"`
219
+ and `"json_seq"`.
220
+
221
+ The results, and the exceptions, are those of one thread: when a chunk
222
+ contains an error or a document that only `json` accepts, the documents
223
+ before it are kept and the rest is parsed in the calling thread, as without
224
+ threads. An exception raised by `fn` is raised again, for the first document
225
+ where it happened; `fn` may then have been called on later documents, in
226
+ other threads, and it must be safe to call from several threads at once.
227
+
228
+ The worker threads are started by the first call that needs them and kept
229
+ for later calls (they wait, detached from the interpreter, between calls,
230
+ and stop at exit). `map_many` scales best: each document is built, used and
231
+ freed in the same thread, and only `fn`'s results come back. `loads_many` must return every
232
+ document, and the Python objects of all of them, to the calling thread.
233
+ With the GIL (the default build of Python), the calling thread does all the
234
+ work: `threads` has no effect on speed.
235
+
200
236
  ### `release`
201
237
 
202
238
  `release()` frees the simdjson parser and the string caches kept by the
@@ -433,6 +469,24 @@ msgspec's `decode_lines` and `loads_many` are on par (`loads_many` is about 2%
433
469
  faster). `parse_many` only creates the views; reading values from them adds to
434
470
  its time.
435
471
 
472
+ ### Streams on several threads
473
+
474
+ 300 MB of NDJSON (146,624 records: tweets, GitHub events, citm performances,
475
+ gsoc and update-center entries), free-threaded Python 3.14.6, collector
476
+ disabled (see below), Intel Xeon Gold 6548N (64 cores); GB/s:
477
+
478
+ | threads | 1 | 2 | 4 | 8 | 16 | 32 | 64 |
479
+ |---|---:|---:|---:|---:|---:|---:|---:|
480
+ | `map_many(len, data, threads=N)` | 1.03 | 1.78 | 3.66 | 6.82 | 13.0 | 23.7 | **28.8** |
481
+ | `parse_many(data, threads=N)` | 2.00 | 2.84 | 5.28 | 9.26 | 16.1 | 22.7 | 25.8 |
482
+ | `loads_many(data, threads=N)` | 0.90 | 1.44 | 2.79 | 4.99 | 8.98 | 13.3 | 15.4 |
483
+
484
+ `map_many` is 28 times faster on 64 threads than on one (up to 38 GB/s when
485
+ nothing else runs in the process). `loads_many` builds every document for
486
+ the calling thread and is 17 times faster. With the collector enabled,
487
+ Python collects after the call returns: it examines the millions of objects
488
+ just created, which takes about 0.1 s here, with or without threads.
489
+
436
490
  ## Limitations
437
491
 
438
492
  * The simdjson parser and the key and string caches are thread-local.
@@ -166,6 +166,42 @@ returned, otherwise `JSONDecodeError` reports `json`'s message and the
166
166
  position in the whole input. A truncated last document is an error. The
167
167
  views returned by `parse_many` remain valid after the iterator moves on.
168
168
 
169
+ ### Streams on several threads: `threads=N` and `map_many`
170
+
171
+ On free-threaded Python (3.14t and newer), a stream can be parsed by several
172
+ threads at once:
173
+
174
+ ```python
175
+ docs = fastsimdjson.loads_many(data, threads=16) # a list, in order
176
+ views = fastsimdjson.parse_many(data, threads=16) # a list of views
177
+ # fn runs in the threads too, on each document; its results, in order:
178
+ scores = fastsimdjson.map_many(score, data, threads=16)
179
+ ```
180
+
181
+ With `threads`, `loads_many` and `parse_many` return a list of all the
182
+ documents instead of an iterator. `map_many(fn, data, **kw)` returns
183
+ `[fn(doc) for doc in loads_many(data, **kw)]` (`parse_many` with
184
+ `lazy=True`), with `fn` called in the threads. `threads=0` (or `None`) uses
185
+ one thread per processor; small inputs use fewer threads (about one per
186
+ 512 KB). The input is cut into chunks at newlines (before each `\x1e` for
187
+ `json_seq`), so `threads` works with the formats `"whitespace"`, `"lines"`
188
+ and `"json_seq"`.
189
+
190
+ The results, and the exceptions, are those of one thread: when a chunk
191
+ contains an error or a document that only `json` accepts, the documents
192
+ before it are kept and the rest is parsed in the calling thread, as without
193
+ threads. An exception raised by `fn` is raised again, for the first document
194
+ where it happened; `fn` may then have been called on later documents, in
195
+ other threads, and it must be safe to call from several threads at once.
196
+
197
+ The worker threads are started by the first call that needs them and kept
198
+ for later calls (they wait, detached from the interpreter, between calls,
199
+ and stop at exit). `map_many` scales best: each document is built, used and
200
+ freed in the same thread, and only `fn`'s results come back. `loads_many` must return every
201
+ document, and the Python objects of all of them, to the calling thread.
202
+ With the GIL (the default build of Python), the calling thread does all the
203
+ work: `threads` has no effect on speed.
204
+
169
205
  ### `release`
170
206
 
171
207
  `release()` frees the simdjson parser and the string caches kept by the
@@ -402,6 +438,24 @@ msgspec's `decode_lines` and `loads_many` are on par (`loads_many` is about 2%
402
438
  faster). `parse_many` only creates the views; reading values from them adds to
403
439
  its time.
404
440
 
441
+ ### Streams on several threads
442
+
443
+ 300 MB of NDJSON (146,624 records: tweets, GitHub events, citm performances,
444
+ gsoc and update-center entries), free-threaded Python 3.14.6, collector
445
+ disabled (see below), Intel Xeon Gold 6548N (64 cores); GB/s:
446
+
447
+ | threads | 1 | 2 | 4 | 8 | 16 | 32 | 64 |
448
+ |---|---:|---:|---:|---:|---:|---:|---:|
449
+ | `map_many(len, data, threads=N)` | 1.03 | 1.78 | 3.66 | 6.82 | 13.0 | 23.7 | **28.8** |
450
+ | `parse_many(data, threads=N)` | 2.00 | 2.84 | 5.28 | 9.26 | 16.1 | 22.7 | 25.8 |
451
+ | `loads_many(data, threads=N)` | 0.90 | 1.44 | 2.79 | 4.99 | 8.98 | 13.3 | 15.4 |
452
+
453
+ `map_many` is 28 times faster on 64 threads than on one (up to 38 GB/s when
454
+ nothing else runs in the process). `loads_many` builds every document for
455
+ the calling thread and is 17 times faster. With the collector enabled,
456
+ Python collects after the call returns: it examines the millions of objects
457
+ just created, which takes about 0.1 s here, with or without threads.
458
+
405
459
  ## Limitations
406
460
 
407
461
  * The simdjson parser and the key and string caches are thread-local.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "fastsimdjson"
7
- version = "0.4.0"
7
+ version = "0.6.0"
8
8
  description = "Fast JSON parsing for Python, built on simdjson"
9
9
  readme = "README.md"
10
10
  authors = [