Skip to content

Commit 367d9ab

Browse files
committed
Add datasource benchmark tests
Tests run on PR are regression tests - each datasource's performance is compared with base reference. Because memory datasource operates on memory only, datasources run was limited to only smallest file (261M), excluding the 7.5G one. To support that list of read/write files was moved to fixture. Manually workflow gives more freedom. There is an option to run stream/memory datasource against our default one to see how different datasources performance compares.
1 parent f23280a commit 367d9ab

4 files changed

Lines changed: 110 additions & 20 deletions

File tree

.github/actions/benchmark/action.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ inputs:
77
compare:
88
description: results comparison string
99
default: --benchmark-compare=0001 --benchmark-compare-fail=min:25% --benchmark-group-by=fullname --color=yes
10+
datasource:
11+
description: datasource to run on
12+
default: default
1013

1114
runs:
1215
using: "composite"
@@ -76,11 +79,29 @@ runs:
7679
ls -lh file-small.sgy
7780
7881
- name: Run benchmark tests
82+
if: ${{ inputs.datasource == 'default' }}
7983
shell: bash
8084
working-directory: python
8185
run: |
8286
pytest test/benchmarks.py -rP --benchmark-sort=name --benchmark-autosave ${{ inputs.compare }}
8387
88+
- name: Run benchmark tests on datasource
89+
if: ${{ inputs.datasource != 'default' }}
90+
shell: bash
91+
working-directory: python
92+
run: |
93+
pytest \
94+
test/benchmarks.py::test_read_speed \
95+
test/benchmarks.py::test_cube_speed \
96+
test/benchmarks.py::test_write_file \
97+
-rP \
98+
--datasource ${{ inputs.datasource }} \
99+
--readf file-small.sgy \
100+
--writef file-small.sgy \
101+
--benchmark-sort=name \
102+
--benchmark-autosave \
103+
${{ inputs.compare }}
104+
84105
- name: Remove build artifacts
85106
shell: bash
86107
run: |

.github/workflows/benchmarks.yaml

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,45 @@ on:
1010
commit_ref:
1111
description: "optional: compare to specific ref"
1212
required: false
13+
run_on_default:
14+
type: boolean
15+
description: Run on default file
16+
default: true
17+
run_on_stream:
18+
type: boolean
19+
description: Run on pyfile stream
20+
default: false
21+
run_on_memory:
22+
type: boolean
23+
description: Run on memory datasource
24+
default: false
25+
compare_to_self:
26+
description: "True: compare to older version of the same datasource. False: compare to standard C-file."
27+
default: true
28+
type: boolean
1329

1430
jobs:
1531
benchmarks:
16-
name: Benchmark scripts
32+
name: Benchmark script on ${{ matrix.datasource }} datasource
1733
runs-on: ubuntu-latest
34+
strategy:
35+
fail-fast: false
36+
# matrix set up to combine running manually and on PR
37+
matrix:
38+
datasource: [default, pyfile, nativememory]
39+
run_on_default:
40+
- ${{ github.event.inputs.run_on_default }}
41+
run_on_stream:
42+
- ${{ github.event.inputs.run_on_stream }}
43+
run_on_memory:
44+
- ${{ github.event.inputs.run_on_memory }}
45+
exclude:
46+
- datasource: default
47+
run_on_default: "false"
48+
- datasource: pyfile
49+
run_on_stream: "false"
50+
- datasource: nativememory
51+
run_on_memory: "false"
1852

1953
steps:
2054
- uses: actions/checkout@v4
@@ -30,19 +64,35 @@ jobs:
3064
python3 -m pip install -r requirements-dev.txt
3165
3266
- name: Set default benchmark reference
33-
run: echo "BENCHMARK_REF=142e45a2b941a1b603723c38882b193db1c1d968" >> $GITHUB_ENV
67+
run: |
68+
if [ "${{ matrix.datasource }}" = "default" ]; then
69+
echo "BENCHMARK_REF=142e45a2b941a1b603723c38882b193db1c1d968" >> $GITHUB_ENV
70+
else
71+
echo "BENCHMARK_REF=2b3be755d8e1bd536275a9cbcf16c06717b30bd0" >> $GITHUB_ENV
72+
fi
3473
3574
- name: Set benchmark reference if defined by workflow_dispatch
3675
if: github.event.inputs.commit_ref != ''
3776
run: echo "BENCHMARK_REF=${{ github.event.inputs.commit_ref }}" >> $GITHUB_ENV
3877

78+
- name: Set base datasource for comparison
79+
run: |
80+
if [ "${{ github.event.inputs.compare_to_self }}" = "false" ]; then
81+
echo "BASE_DATASOURCE=default" >> $GITHUB_ENV
82+
else
83+
# also the case when compare_to_self = "" because run is trigger by PR.
84+
echo "BASE_DATASOURCE=${{ matrix.datasource }}" >> $GITHUB_ENV
85+
fi
86+
3987
- name: Benchmark old commit
4088
uses: "./.github/actions/benchmark"
4189
with:
4290
ref: ${{ env.BENCHMARK_REF }}
91+
datasource: ${{ env.BASE_DATASOURCE }}
4392
compare: ""
4493

4594
- name: Benchmark current commit and compare
4695
uses: "./.github/actions/benchmark"
4796
with:
4897
ref: ${{ github.sha }}
98+
datasource: ${{ matrix.datasource }}

python/test/benchmarks.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,6 @@
77
import numpy as np
88

99

10-
# Files are expected to be present at the run location
11-
# Files size should be compatible with retrieved lines
12-
read_files = [
13-
'file.sgy',
14-
'file-small.sgy',
15-
]
16-
17-
write_files = [
18-
'file-small.sgy',
19-
]
20-
21-
2210
def run(filepath, mmap, func, mode="r"):
2311
with segyio.open(filepath, mode=mode) as f:
2412
if mmap:
@@ -38,9 +26,13 @@ def run_in_memory(memory_buffer, func):
3826

3927
def run_with(filepath, mode, mmap, func, make_datasource):
4028
filepath, memory_buffer, stream = make_datasource(filepath, mode)
41-
if stream and "open_with" in dir(segyio):
29+
if stream:
30+
if "open_with" not in dir(segyio):
31+
raise RuntimeError("segyio.open_with is not available")
4232
run_with_stream(stream, func)
43-
elif memory_buffer and "open_from_memory" in dir(segyio):
33+
elif memory_buffer:
34+
if "open_from_memory" not in dir(segyio):
35+
raise RuntimeError("segyio.open_from_memory is not available")
4436
run_in_memory(memory_buffer, func)
4537
else:
4638
run(filepath, mmap, func, mode)
@@ -162,29 +154,25 @@ def create(output_file):
162154

163155

164156
@pytest.mark.benchmark(group="nommap")
165-
@pytest.mark.parametrize("read_file", read_files)
166157
@pytest.mark.parametrize("func", operations)
167158
def test_read_speed(make_datasource, benchmark, read_file, func):
168159
benchmark(run_with, read_file, "rb", False, func, make_datasource)
169160

170161

171162
@pytest.mark.benchmark(group="with mmap")
172-
@pytest.mark.parametrize("read_file", read_files)
173163
@pytest.mark.parametrize("func", operations)
174164
def test_mmap_read_speed(benchmark, read_file, func):
175165
benchmark(run, read_file, True, func)
176166

177167

178168
@pytest.mark.benchmark(group="cube")
179-
@pytest.mark.parametrize("read_file", read_files)
180169
def test_cube_speed(make_datasource, benchmark, read_file):
181170
benchmark.pedantic(
182171
run_with, rounds=5, args=[read_file, "rb", False, cube, make_datasource]
183172
)
184173

185174

186175
@pytest.mark.benchmark(group="write")
187-
@pytest.mark.parametrize("write_file", write_files)
188176
@pytest.mark.parametrize("func", write_operations)
189177
def test_write_file(make_datasource, benchmark, write_file, func):
190178
# note that original file will get overwritten

python/test/conftest.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,34 @@ def pytest_addoption(parser):
159159
default="default",
160160
help="Known datasource in testing. Options: pyfile, pymemory, nativememory."
161161
)
162+
parser.addoption(
163+
"--readf",
164+
action="append",
165+
default=[],
166+
help=("Files used for benchmark read tests. "
167+
"Files size should be compatible with retrieved lines. "
168+
"Option may be used multiple times.")
169+
)
170+
171+
parser.addoption(
172+
"--writef",
173+
action="append",
174+
default=[],
175+
help=("Files used for benchmark write tests (files will get modified)."
176+
"File size should be compatible with modified lines."
177+
"Option may be be used multiple times.")
178+
)
179+
180+
def pytest_generate_tests(metafunc):
181+
# default files are expected to be present at the run location if options are not overridden
182+
if "read_file" in metafunc.fixturenames:
183+
read_files = metafunc.config.getoption("readf")
184+
if not read_files:
185+
read_files = ['file.sgy', 'file-small.sgy']
186+
metafunc.parametrize("read_file", read_files)
187+
188+
if "write_file" in metafunc.fixturenames:
189+
write_files = metafunc.config.getoption("writef")
190+
if not write_files:
191+
write_files = ['file-small.sgy']
192+
metafunc.parametrize("write_file", write_files)

0 commit comments

Comments
 (0)