py: test that an edit releases the GIL
A thread appending timestamps in a loop runs while a 1024x1024 gzip dataset is rewritten through 'r+': the largest gap between its stamps during the edit must be under half the edit's duration (an edit holding the GIL stalls it for the whole edit; checked with a GIL-holding regex standing in for the edit: one 0.20 s gap in a 0.21 s call). Edits already ran detached; nothing tested it. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
@@ -896,3 +896,38 @@ def test_path_replaced_between_edits(h5py, tmp_path):
|
||||
from pathlib import Path
|
||||
_held_file_edited(h5py, moved, Path(path), other_bytes)
|
||||
|
||||
|
||||
def test_an_edit_releases_the_gil(h5py, tmp_path):
|
||||
"""Another Python thread keeps running while a large edit is written:
|
||||
had the edit held the GIL, the other thread would stall for the whole
|
||||
edit (Rust code never yields it)."""
|
||||
import time
|
||||
path = str(tmp_path / "big.h5")
|
||||
with h5py.File(path, "w") as f:
|
||||
f.create_dataset("d", shape=(1024, 1024), dtype="<f8", chunks=(64, 64), compression="gzip")
|
||||
value = np.random.default_rng(0).standard_normal((1024, 1024))
|
||||
stamps = []
|
||||
stop = threading.Event()
|
||||
|
||||
def spin():
|
||||
while not stop.is_set():
|
||||
stamps.append(time.perf_counter())
|
||||
|
||||
with clawhdf5.File(path, "r+") as f:
|
||||
ds = f["d"]
|
||||
t = threading.Thread(target=spin)
|
||||
t.start()
|
||||
try:
|
||||
time.sleep(0.05)
|
||||
t0 = time.perf_counter()
|
||||
ds[...] = value
|
||||
t1 = time.perf_counter()
|
||||
finally:
|
||||
stop.set()
|
||||
t.join()
|
||||
np.testing.assert_array_equal(ds[...], value)
|
||||
during = [x for x in stamps if t0 <= x <= t1]
|
||||
gaps = np.diff([t0] + during + [t1])
|
||||
assert t1 - t0 > 0.1, "the edit is too quick to tell"
|
||||
assert gaps.max() < 0.5 * (t1 - t0), (
|
||||
f"the other thread stalled for {gaps.max():.3f} s of a {t1 - t0:.3f} s edit")
|
||||
|
||||
Reference in New Issue
Block a user