Skip to content

Commit 2037847

Browse files
authored
Improve benchmarks and add more (#77)
1 parent 3857d2a commit 2037847

File tree

12 files changed

+116
-21
lines changed

12 files changed

+116
-21
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ dump-nskeyedarchiver = "dissect.util.tools.dump_nskeyedarchiver:main"
4646

4747
[tool.ruff]
4848
line-length = 120
49-
required-version = ">=0.9.0"
49+
required-version = ">=0.11.0"
5050

5151
[tool.ruff.format]
5252
docstring-code-format = true

tests/conftest.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import importlib.util
2+
3+
import pytest
4+
5+
HAS_BENCHMARK = importlib.util.find_spec("pytest_benchmark") is not None
6+
7+
8+
def pytest_configure(config: pytest.Config) -> None:
9+
if not HAS_BENCHMARK:
10+
# If we don't have pytest-benchmark (or pytest-codspeed) installed, register the benchmark marker ourselves
11+
# to avoid pytest warnings
12+
config.addinivalue_line("markers", "benchmark: mark test for benchmarking (requires pytest-benchmark)")
13+
14+
15+
def pytest_runtest_setup(item: pytest.Item) -> None:
16+
if not HAS_BENCHMARK and item.get_closest_marker("benchmark") is not None:
17+
pytest.skip("pytest-benchmark is not installed")

tests/test_compression.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1+
from __future__ import annotations
2+
13
import hashlib
24
import lzma
35
from io import BytesIO
6+
from typing import TYPE_CHECKING
47

58
import pytest
69

710
from dissect.util.compression import lz4, lznt1, lzo, lzxpress, lzxpress_huffman, sevenbit, xz
811

12+
if TYPE_CHECKING:
13+
from pytest_benchmark.fixture import BenchmarkFixture
14+
915

1016
def test_lz4_decompress() -> None:
1117
assert (
@@ -26,6 +32,19 @@ def test_lznt1_decompress() -> None:
2632
)
2733

2834

35+
@pytest.mark.benchmark
36+
def test_benchmark_lznt1_decompress(benchmark: BenchmarkFixture) -> None:
37+
buf = bytes.fromhex(
38+
"38b08846232000204720410010a24701a045204400084501507900c045200524"
39+
"138805b4024a44ef0358028c091601484500be009e000401189000"
40+
)
41+
assert benchmark(lznt1.decompress, buf) == (
42+
b"F# F# G A A G F# E D D E F# F# E E F# F# G A A "
43+
b"G F# E D D E F# E D D E E F# D E F# G F# D E F# "
44+
b"G F# E D E A F# F# G A A G F# E D D E F# E D D\x00"
45+
)
46+
47+
2948
def test_lzo_decompress() -> None:
3049
assert (
3150
lzo.decompress(bytes.fromhex("0361626361626320f314000f616263616263616263616263616263616263110000"), False)
@@ -231,28 +250,68 @@ def test_lzxpress_huffman_decompress() -> None:
231250
)
232251

233252

253+
@pytest.mark.benchmark
254+
def test_benchmark_lzxpress_huffman_decompress(benchmark: BenchmarkFixture) -> None:
255+
buf = bytes.fromhex(
256+
"0000000000000000000000000000000000000000000000000000000000000000"
257+
"0000000000000000000000000000000030230000000000000000000000000000"
258+
"0000000000000000000000000000000000000000000000000000000000000000"
259+
"0000000000000000000000000000000000000000000000000000000000000000"
260+
"0200000000000000000000000000002000000000000000000000000000000000"
261+
"0000000000000000000000000000000000000000000000000000000000000000"
262+
"0000000000000000000000000000000000000000000000000000000000000000"
263+
"0000000000000000000000000000000000000000000000000000000000000000"
264+
"a8dc0000ff2601"
265+
)
266+
assert benchmark(lzxpress_huffman.decompress, buf) == b"abc" * 100
267+
268+
234269
def test_lzxpress_decompress() -> None:
235270
assert lzxpress.decompress(bytes.fromhex("ffff ff1f 6162 6317 000f ff26 01")) == b"abc" * 100
236271

237272

273+
@pytest.mark.benchmark
274+
def test_benchmark_lzxpress_decompress(benchmark: BenchmarkFixture) -> None:
275+
buf = bytes.fromhex("ffff ff1f 6162 6317 000f ff26 01")
276+
assert benchmark(lzxpress.decompress, buf) == b"abc" * 100
277+
278+
238279
def test_sevenbit_compress() -> None:
239280
result = sevenbit.compress(b"7-bit compression test string")
240281
target = bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06")
241282
assert result == target
242283

243284

285+
@pytest.mark.benchmark
286+
def test_benchmark_sevenbit_compress(benchmark: BenchmarkFixture) -> None:
287+
buf = b"7-bit compression test string"
288+
assert benchmark(sevenbit.compress, buf) == bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06")
289+
290+
244291
def test_sevenbit_decompress() -> None:
245292
result = sevenbit.decompress(bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06"))
246293
target = b"7-bit compression test string"
247294
assert result == target
248295

249296

297+
@pytest.mark.benchmark
298+
def test_benchmark_sevenbit_decompress(benchmark: BenchmarkFixture) -> None:
299+
buf = bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06")
300+
assert benchmark(sevenbit.decompress, buf) == b"7-bit compression test string"
301+
302+
250303
def test_sevenbit_decompress_wide() -> None:
251304
result = sevenbit.decompress(bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06"), wide=True)
252305
target = "7-bit compression test string".encode("utf-16-le")
253306
assert result == target
254307

255308

309+
@pytest.mark.benchmark
310+
def test_benchmark_sevenbit_decompress_wide(benchmark: BenchmarkFixture) -> None:
311+
buf = bytes.fromhex("b796384d078ddf6db8bc3c9fa7df6e10bd3ca783e67479da7d06")
312+
assert benchmark(sevenbit.decompress, buf, wide=True) == "7-bit compression test string".encode("utf-16-le")
313+
314+
256315
def test_xz_repair_checksum() -> None:
257316
buf = BytesIO(
258317
bytes.fromhex(

tests/test_cpio.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
from __future__ import annotations
2+
13
import gzip
24
from pathlib import Path
3-
from tarfile import TarFile
5+
from typing import TYPE_CHECKING
46

57
import pytest
68

79
from dissect.util import cpio
810

11+
if TYPE_CHECKING:
12+
from tarfile import TarFile
13+
914

1015
def absolute_path(filename: str) -> Path:
1116
return Path(__file__).parent / filename

tests/test_crc32c.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import importlib.util
43
from typing import TYPE_CHECKING
54

65
import pytest
@@ -10,8 +9,6 @@
109
if TYPE_CHECKING:
1110
from pytest_benchmark.fixture import BenchmarkFixture
1211

13-
HAS_BENCHMARK = importlib.util.find_spec("pytest_benchmark") is not None
14-
1512

1613
@pytest.mark.parametrize(
1714
("data", "value", "expected"),
@@ -36,6 +33,6 @@ def test_crc32c(data: bytes, value: int, expected: int) -> None:
3633
assert crc32c.crc32c(data, value) == expected
3734

3835

39-
@pytest.mark.skipif(not HAS_BENCHMARK, reason="pytest-benchmark not installed")
36+
@pytest.mark.benchmark
4037
def test_crc32c_benchmark(benchmark: BenchmarkFixture) -> None:
4138
benchmark(crc32c.crc32c, b"hello, world!", 0)

tests/test_feature.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import pytest
24

35
from dissect.util.feature import Feature, FeatureError, feature, feature_enabled

tests/test_plist.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from __future__ import annotations
2+
13
import datetime
24
import sys
35
import uuid

tests/test_sid.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import importlib.util
43
import io
54
from typing import TYPE_CHECKING, BinaryIO
65

@@ -11,8 +10,6 @@
1110
if TYPE_CHECKING:
1211
from pytest_benchmark.fixture import BenchmarkFixture
1312

14-
HAS_BENCHMARK = importlib.util.find_spec("pytest_benchmark") is not None
15-
1613

1714
def id_fn(val: bytes | str) -> str:
1815
if isinstance(val, io.BytesIO):
@@ -91,7 +88,7 @@ def test_read_sid(binary_sid: bytes | BinaryIO, endian: str, swap_last: bool, re
9188
assert readable_sid == sid.read_sid(binary_sid, endian, swap_last)
9289

9390

94-
@pytest.mark.skipif(not HAS_BENCHMARK, reason="pytest-benchmark not installed")
91+
@pytest.mark.benchmark
9592
@pytest.mark.parametrize(
9693
("binary_sid", "swap_last"),
9794
[

tests/test_stream.py

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import importlib.util
43
import io
54
import zlib
65
from typing import TYPE_CHECKING
@@ -13,8 +12,6 @@
1312
if TYPE_CHECKING:
1413
from pytest_benchmark.fixture import BenchmarkFixture
1514

16-
HAS_BENCHMARK = importlib.util.find_spec("pytest_benchmark") is not None
17-
1815

1916
def test_range_stream() -> None:
2017
buf = io.BytesIO(b"\x01" * 10 + b"\x02" * 10 + b"\x03" * 10)
@@ -236,13 +233,25 @@ def _read(self, offset: int, length: int) -> bytes:
236233
return b"\x00" * length
237234

238235

239-
@pytest.mark.skipif(not HAS_BENCHMARK, reason="pytest-benchmark not installed")
236+
@pytest.mark.benchmark
240237
def test_aligned_stream_read_fixed_size_benchmark(benchmark: BenchmarkFixture) -> None:
241238
fh = NullStream(1024 * 1024)
242-
benchmark(fh.read, 1234)
239+
240+
@benchmark
241+
def run() -> None:
242+
fh.seek(0)
243+
fh.read(1234)
244+
245+
assert run is None
243246

244247

245-
@pytest.mark.skipif(not HAS_BENCHMARK, reason="pytest-benchmark not installed")
248+
@pytest.mark.benchmark
246249
def test_aligned_stream_read_none_size_benchmark(benchmark: BenchmarkFixture) -> None:
247250
fh = NullStream(None)
248-
benchmark(fh.read, 1234)
251+
252+
@benchmark
253+
def run() -> None:
254+
fh.seek(0)
255+
fh.read(1234)
256+
257+
assert run is None

tests/test_ts.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1+
from __future__ import annotations
2+
13
import platform
24
from datetime import datetime, timedelta, timezone
35
from importlib import reload
4-
from types import ModuleType
6+
from typing import TYPE_CHECKING
57
from unittest.mock import patch
68

79
import pytest
810

11+
if TYPE_CHECKING:
12+
from types import ModuleType
13+
914

1015
@pytest.fixture(params=["windows", "emscripten", "linux"])
1116
def imported_ts(request: pytest.FixtureRequest) -> ModuleType:

0 commit comments

Comments
 (0)