Skip to content

Commit 4eed97c

Browse files
committed
New cache for the last block read
1 parent e60e31c commit 4eed97c

2 files changed

Lines changed: 35 additions & 1 deletion

File tree

src/blosc2/batch_store.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ def __init__(self, parent: BatchStore, nbatch: int, lazybatch: bytes) -> None:
3434
self._nbatch = nbatch
3535
self._lazybatch = lazybatch
3636
self._items: list[Any] | None = None
37+
self._cached_block_index: int | None = None
38+
self._cached_block: list[Any] | None = None
3739
self._nbytes, self._cbytes, self._nblocks = blosc2.get_cbuffer_sizes(lazybatch)
3840

3941
def _normalize_index(self, index: int) -> int:
@@ -51,6 +53,14 @@ def _decode_items(self) -> list[Any]:
5153
self._items = [item for block in blocks for item in block]
5254
return self._items
5355

56+
def _get_block(self, block_index: int) -> list[Any]:
57+
if self._cached_block_index == block_index and self._cached_block is not None:
58+
return self._cached_block
59+
block = msgpack_unpackb(self._parent.schunk.get_vlblock(self._nbatch, block_index))
60+
self._cached_block_index = block_index
61+
self._cached_block = block
62+
return block
63+
5464
def __getitem__(self, index: int | slice) -> Any | list[Any]:
5565
if isinstance(index, slice):
5666
items = self._decode_items()
@@ -64,7 +74,7 @@ def __getitem__(self, index: int | slice) -> Any | list[Any]:
6474
block_index, item_index = divmod(index, blocksize_max)
6575
if block_index >= self._nblocks:
6676
raise IndexError("Batch index out of range")
67-
block = msgpack_unpackb(self._parent.schunk.get_vlblock(self._nbatch, block_index))
77+
block = self._get_block(block_index)
6878
try:
6979
return block[item_index]
7080
except IndexError as exc:

tests/test_batch_store.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,30 @@ def test_batchstore_get_vlblock_and_scalar_access():
202202
blosc2.remove_urlpath(urlpath)
203203

204204

205+
def test_batchstore_scalar_reads_cache_vlblocks():
206+
barray = blosc2.BatchStore(blocksize_max=2)
207+
barray.append([0, 1, 2, 3, 4])
208+
209+
batch = barray[0]
210+
original_get_vlblock = barray.schunk.get_vlblock
211+
calls = []
212+
213+
def wrapped_get_vlblock(nchunk, nblock):
214+
calls.append((nchunk, nblock))
215+
return original_get_vlblock(nchunk, nblock)
216+
217+
barray.schunk.get_vlblock = wrapped_get_vlblock
218+
try:
219+
assert batch[0] == 0
220+
assert batch[1] == 1
221+
assert batch[0] == 0
222+
assert batch[2] == 2
223+
assert batch[3] == 3
224+
assert calls == [(0, 0), (0, 1)]
225+
finally:
226+
barray.schunk.get_vlblock = original_get_vlblock
227+
228+
205229
def test_batchstore_respects_explicit_use_dict_and_non_zstd():
206230
barray = blosc2.BatchStore(cparams={"codec": blosc2.Codec.LZ4, "clevel": 5})
207231
assert barray.cparams.codec == blosc2.Codec.LZ4

0 commit comments

Comments
 (0)