Skip to content
Merged
13 changes: 13 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,19 @@ $ poetry run tox
This requires you to have all the Python interpreters supported by **nidaqmx** installed on your
machine.

# Benchmarks

Benchmark tests are not run by default when you run pytest. To run the benchmarks, use this command:

```sh
# Run the benchmarks
# Compare benchmark before/after a change
# see https://pytest-benchmark.readthedocs.io/en/latest/comparing.html
# Run 1: --benchmark-save=some-name
# Run N: --benchmark-compare=0001
$ poetry run pytest -v tests/benchmark
```

# Building Documentation

To build the documentation install the optional docs packages and run sphinx. For example:
Expand Down
35 changes: 34 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ types-grpcio = ">=1.0"

[tool.poetry.group.test.dependencies]
pytest = ">=7.2"
pytest-benchmark = ">=5.1"
pytest-cov = ">=4.0"
pytest-mock = ">=3.0"
pykka = ">=3.0"
Expand Down Expand Up @@ -135,7 +136,7 @@ application-import-names = "nidaqmx"
[tool.pytest.ini_options]
addopts = "--doctest-modules --strict-markers"
filterwarnings = ["always::ImportWarning", "always::ResourceWarning"]
testpaths = ["tests"]
testpaths = ["tests/acceptance", "tests/component", "tests/legacy", "tests/unit"]
markers = [
# Defines custom markers used by nidaqmx tests. Prevents PytestUnknownMarkWarning.
"library_only(reason=...): run the test with only the library interpreter implementation.",
Expand Down Expand Up @@ -184,6 +185,8 @@ module = [
"importlib_metadata",
"mako.*",
"nidaqmx.*",
# https://github.com/ionelmc/pytest-benchmark/issues/212 - Add type annotations
"pytest_benchmark.*",
]
ignore_missing_imports = true

Expand Down
1 change: 1 addition & 0 deletions tests/benchmark/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Benchmarks for the nidaqmx package."""
4 changes: 4 additions & 0 deletions tests/benchmark/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"""Import fixtures from component tests for benchmark tests."""

# Import all fixtures from component conftest.py to make them available for benchmark tests
from tests.component.conftest import * # noqa: F403, F401
88 changes: 88 additions & 0 deletions tests/benchmark/test_analog_stream_readers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
from __future__ import annotations

import math

import numpy
import pytest
from nitypes.waveform import AnalogWaveform
from pytest_benchmark.fixture import BenchmarkFixture

import nidaqmx
from nidaqmx.stream_readers._analog_multi_channel_reader import AnalogMultiChannelReader
from nidaqmx.stream_readers._analog_single_channel_reader import (
AnalogSingleChannelReader,
)


@pytest.mark.benchmark(group="analog_stream_readers")
def test___analog_single_channel_reader___read_one_sample___1_sample(
benchmark: BenchmarkFixture,
ai_single_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogSingleChannelReader(ai_single_channel_task.in_stream)

benchmark(reader.read_one_sample)


@pytest.mark.benchmark(group="analog_stream_readers")
def test___analog_single_channel_reader___read_many_sample___1000_samples(
benchmark: BenchmarkFixture,
ai_single_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogSingleChannelReader(ai_single_channel_task.in_stream)
samples_to_read = 1000
data = numpy.full(samples_to_read, math.inf, dtype=numpy.float64)

benchmark(reader.read_many_sample, data, samples_to_read)


@pytest.mark.benchmark(group="analog_stream_readers")
@pytest.mark.grpc_skip(reason="read_analog_waveform not implemented in GRPC")
def test___analog_single_channel_reader___read_waveform___1000_samples(
benchmark: BenchmarkFixture,
ai_single_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogSingleChannelReader(ai_single_channel_task.in_stream)
samples_to_read = 1000
waveform = AnalogWaveform(samples_to_read)

benchmark(reader.read_waveform, waveform, samples_to_read)


@pytest.mark.benchmark(group="analog_stream_readers")
def test___analog_multi_channel_reader___read_one_sample___1_sample(
benchmark: BenchmarkFixture,
ai_multi_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogMultiChannelReader(ai_multi_channel_task.in_stream)
num_channels = 3
data = numpy.full(num_channels, math.inf, dtype=numpy.float64)

benchmark(reader.read_one_sample, data)


@pytest.mark.benchmark(group="analog_stream_readers")
def test___analog_multi_channel_reader___read_many_sample___1000_samples(
benchmark: BenchmarkFixture,
ai_multi_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogMultiChannelReader(ai_multi_channel_task.in_stream)
num_channels = 3
samples_to_read = 1000
data = numpy.full((num_channels, samples_to_read), math.inf, dtype=numpy.float64)

benchmark(reader.read_many_sample, data, samples_to_read)


@pytest.mark.benchmark(group="analog_stream_readers")
@pytest.mark.grpc_skip(reason="read_analog_waveforms not implemented in GRPC")
def test___analog_multi_channel_reader___read_waveform___1000_samples(
benchmark: BenchmarkFixture,
ai_multi_channel_task: nidaqmx.Task,
) -> None:
reader = AnalogMultiChannelReader(ai_multi_channel_task.in_stream)
num_channels = 3
samples_to_read = 1000
waveforms = [AnalogWaveform(samples_to_read) for _ in range(num_channels)]

benchmark(reader.read_waveforms, waveforms, samples_to_read)
85 changes: 85 additions & 0 deletions tests/benchmark/test_analog_stream_writers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
from __future__ import annotations

import numpy
import pytest
from nitypes.waveform import AnalogWaveform
from pytest_benchmark.fixture import BenchmarkFixture

import nidaqmx
from nidaqmx.stream_writers._analog_multi_channel_writer import AnalogMultiChannelWriter
from nidaqmx.stream_writers._analog_single_channel_writer import (
AnalogSingleChannelWriter,
)


@pytest.mark.benchmark(group="analog_stream_writers")
def test___analog_single_channel_writer___write_one_sample___1_sample(
benchmark: BenchmarkFixture,
ao_single_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogSingleChannelWriter(ao_single_channel_task.out_stream)

benchmark(writer.write_one_sample, 1.0)


@pytest.mark.benchmark(group="analog_stream_writers")
def test___analog_single_channel_writer___write_many_sample___100_samples(
benchmark: BenchmarkFixture,
ao_single_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogSingleChannelWriter(ao_single_channel_task.out_stream)
samples_to_write = 100
data = numpy.linspace(0.0, 1.0, num=samples_to_write, dtype=numpy.float64)

benchmark(writer.write_many_sample, data)


@pytest.mark.benchmark(group="analog_stream_writers")
@pytest.mark.grpc_skip(reason="write_analog_waveform not implemented in GRPC")
def test___analog_single_channel_writer___write_waveform___100_samples(
benchmark: BenchmarkFixture,
ao_single_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogSingleChannelWriter(ao_single_channel_task.out_stream)
num_samples = 100
waveform = AnalogWaveform(num_samples)

benchmark(writer.write_waveform, waveform)


@pytest.mark.benchmark(group="analog_stream_writers")
def test___analog_multi_channel_writer___write_one_sample___1_sample(
benchmark: BenchmarkFixture,
ao_multi_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogMultiChannelWriter(ao_multi_channel_task.out_stream)
expected = [1.0, 1.0]
data = numpy.asarray(expected, dtype=numpy.float64)

benchmark(writer.write_one_sample, data)


@pytest.mark.benchmark(group="analog_stream_writers")
def test___analog_multi_channel_writer___write_many_sample___100_samples(
benchmark: BenchmarkFixture,
ao_multi_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogMultiChannelWriter(ao_multi_channel_task.out_stream)
num_channels = 2
samples_to_write = 100
data = numpy.full((num_channels, samples_to_write), 1.0, dtype=numpy.float64)

benchmark(writer.write_many_sample, data)


@pytest.mark.benchmark(group="analog_stream_writers")
@pytest.mark.grpc_skip(reason="write_analog_waveform not implemented in GRPC")
def test___analog_multi_channel_writer___write_waveform___100_samples(
benchmark: BenchmarkFixture,
ao_multi_channel_task: nidaqmx.Task,
) -> None:
writer = AnalogMultiChannelWriter(ao_multi_channel_task.out_stream)
num_samples = 100
waveform = [AnalogWaveform(num_samples), AnalogWaveform(num_samples)]

benchmark(writer.write_waveforms, waveform)
Loading
Loading