|
1 | | -Announcing Python-Blosc2 4.8.0 |
| 1 | +Announcing Python-Blosc2 4.8.1 |
2 | 2 | ============================== |
3 | 3 |
|
4 | | -We are happy to announce this release, which brings support for |
5 | | -**sharing containers safely across processes** — opt-in file locking for |
6 | | -``SChunk``/``NDArray``/``EmbedStore``/``DictStore``, atomic archive |
7 | | -replacement, and readers that follow another process's writes — plus a |
8 | | -couple of data-loss and data-correctness bug fixes worth upgrading for even |
9 | | -if you don't touch any of the new locking API. |
| 4 | +This is a maintenance release with a solid batch of bug fixes — including |
| 5 | +use-after-free hazards around zero-copy cframes, wrong-chunk deletion with |
| 6 | +negative-step slices, and inconsistent ``DictStore`` overwrite semantics — |
| 7 | +plus read-only memory mapping for ``CTable`` stores and a documentation |
| 8 | +restructuring with a new Optimization Tips section. |
10 | 9 |
|
11 | 10 | The main highlights are: |
12 | 11 |
|
13 | | -- **Cross-process locking**: a new ``locking`` storage parameter (and the |
14 | | - ``BLOSC_LOCKING`` env var to enable it fleet-wide) serializes accesses to an |
15 | | - on-disk ``SChunk``/``NDArray``/``EmbedStore``/``DictStore`` against other |
16 | | - handles and processes via a small sidecar lock file. ``holding_lock()`` |
17 | | - holds the exclusive lock across several operations and now auto-refreshes |
18 | | - the handle right after acquiring it, so a decision made inside the block |
19 | | - never acts on a stale in-memory read. |
20 | | - |
21 | | -- **Cross-process writes for ``EmbedStore``/``DictStore``** (``.b2d``): under |
22 | | - locking, one process can add or remove keys while another has the store |
23 | | - open, and the other side's next lookup sees the change — no need to |
24 | | - reopen the store. |
25 | | - |
26 | | -- **Atomic ``.b2z`` archives**: writing a ``DictStore.to_b2z()`` file (which |
27 | | - ``TreeStore`` also uses) now swaps the new file in atomically. A process |
28 | | - reading the archive concurrently always gets either the complete old |
29 | | - version or the complete new one — never a partially-written file from a |
30 | | - save that's still in progress. This needs no locking on the reader's side. |
31 | | - |
32 | | -- **Growth-SWMR**: a reader ``NDArray`` handle opened before a ``resize()`` |
33 | | - made through another handle follows the new shape on its next data access, |
34 | | - or via the new explicit ``NDArray.refresh()`` / ``SChunk.refresh()``. |
35 | | - |
36 | | -- **Two bug fixes worth knowing about**: ``NDArray.append()`` could silently |
37 | | - delete another writer's just-appended data under concurrent growth (fixed |
38 | | - by refreshing the cached shape before computing the resize target); and |
39 | | - ``detect_aligned_chunks()`` could silently return the wrong chunk's data |
40 | | - for an aligned slice on arrays whose shape isn't a multiple of the chunk |
41 | | - shape (a floor-division bug that undercounted the chunk grid). |
42 | | - |
43 | | -- New user guide page, |
44 | | - `Sharing containers across processes |
45 | | - <https://www.blosc.org/python-blosc2/guides/sharing_across_processes.html>`_, |
46 | | - covering all of the above plus the caveats (NFS, ``mmap_mode``, Windows |
47 | | - in-use-file rename). |
48 | | - |
49 | | -A quick taste — hold the lock across a read-modify-write from two processes:: |
50 | | - |
51 | | - with ndarr.holding_lock(): |
52 | | - ndarr[:] = ndarr[:] + 1 # atomic w.r.t. other locked handles |
| 12 | +- **Read-only mmap for ``CTable`` stores**: ``CTable.open()`` gains an |
| 13 | + ``mmap_mode="r"`` parameter, mirroring ``blosc2.open()``. All members of a |
| 14 | + read-only store — scalar, list, varlen and dictionary columns alike — are |
| 15 | + read from mapped pages; for ``.b2z`` archives, in place inside the single |
| 16 | + mapped container file. With several concurrent readers on one file this |
| 17 | + pays off quickly: 2.5x/4.4x/4.5x faster wall time for 1/4/8 readers in |
| 18 | + our benchmark. |
| 19 | + |
| 20 | +- **Zero-copy cframe fix**: ``schunk_from_cframe()`` / |
| 21 | + ``ndarray_from_cframe()`` with ``copy=False`` (the default) returned |
| 22 | + objects pointing into the caller's bytes buffer without keeping it alive, |
| 23 | + so a temporary cframe could be reclaimed under the live object, corrupting |
| 24 | + reads. The buffer is now pinned on the returned object. |
| 25 | + |
| 26 | +- **More correctness fixes**: negative-step slice deletion in |
| 27 | + ``BatchArray``/``ObjectArray`` removed the wrong chunks; ``DictStore`` |
| 28 | + overwrite semantics depended on value size (now uniformly dict-like); |
| 29 | + ``stack()``/``vecdot()`` shape inference was off for negative axes; |
| 30 | + chunked ``matmul()`` mishandled broadcast batch dims; and |
| 31 | + ``ListArray.extend_arrow()`` could reorder unflushed rows. |
| 32 | + |
| 33 | +- **Faster ``.b2z``/``.b2d`` opens**: a builtin-shadowing bug made store |
| 34 | + detection in ``blosc2.open()`` silently recurse ~250 times on every open. |
| 35 | + |
| 36 | +- **Docs restructuring**, with a new `Optimization tips |
| 37 | + <https://www.blosc.org/python-blosc2/guides/optimization_tips.html>`_ |
| 38 | + section, including tips on grouping related data into a single |
| 39 | + memory-mapped ``.b2z`` file and on using ``mmap_mode="r"`` with many |
| 40 | + concurrent readers. |
53 | 41 |
|
54 | 42 | Install it with:: |
55 | 43 |
|
|
0 commit comments