Skip to content

Commit

Permalink
Write specific benchmarks for CodSpeed (#1306)
Browse files Browse the repository at this point in the history
* Write specific benchmarks for CodSpeed

* Add frozen benchmark

* Remove instantiation noise

* Put into separate dir like cattrs

* Be consistent
  • Loading branch information
hynek committed Jul 18, 2024
1 parent 0a09c1a commit 1fd3af0
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
121 changes: 121 additions & 0 deletions bench/test_benchmarks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
"""
Benchmark attrs using CodSpeed.
"""

from __future__ import annotations

import pytest

import attrs


pytestmark = pytest.mark.benchmark()

ROUNDS = 1_000


def test_create_simple_class():
"""
Benchmark creating a simple class without any extras.
"""
for _ in range(ROUNDS):

@attrs.define
class LocalC:
x: int
y: str
z: dict[str, int]


def test_create_frozen_class():
"""
Benchmark creating a frozen class without any extras.
"""
for _ in range(ROUNDS):

@attrs.frozen
class LocalC:
x: int
y: str
z: dict[str, int]

LocalC(1, "2", {})


def test_create_simple_class_make_class():
"""
Benchmark creating a simple class using attrs.make_class().
"""
for i in range(ROUNDS):
LocalC = attrs.make_class(
f"LocalC{i}",
{
"x": attrs.field(type=int),
"y": attrs.field(type=str),
"z": attrs.field(type=dict[str, int]),
},
)

LocalC(1, "2", {})


@attrs.define
class C:
x: int = 0
y: str = "foo"
z: dict[str, int] = attrs.Factory(dict)


def test_instantiate_no_defaults():
"""
Benchmark instantiating a class without using any defaults.
"""
for _ in range(ROUNDS):
C(1, "2", {})


def test_instantiate_with_defaults():
"""
Benchmark instantiating a class relying on defaults.
"""
for _ in range(ROUNDS):
C()


def test_eq_equal():
"""
Benchmark comparing two equal instances for equality.
"""
c1 = C()
c2 = C()

for _ in range(ROUNDS):
c1 == c2


def test_eq_unequal():
"""
Benchmark comparing two unequal instances for equality.
"""
c1 = C()
c2 = C(1, "bar", {"baz": 42})

for _ in range(ROUNDS):
c1 == c2


@attrs.frozen
class HashableC:
x: int = 0
y: str = "foo"
z: tuple[str] = ("bar",)


def test_hash():
"""
Benchmark hashing an instance.
"""
c = HashableC()

for _ in range(ROUNDS):
hash(c)
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ ignore = [
]

[tool.ruff.lint.per-file-ignores]
"bench/**" = [
"INP001", # Benchmarks don't have to be importable.
]
"**/test_*" = [
"ARG005", # we need stub lambdas
"S",
Expand Down
6 changes: 0 additions & 6 deletions tests/test_functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@ class TestFunctional:
Functional tests.
"""

@pytest.mark.benchmark()
@pytest.mark.parametrize("cls", [C2, C2Slots])
def test_fields(self, cls):
"""
Expand Down Expand Up @@ -146,7 +145,6 @@ def test_fields(self, cls):
),
) == attr.fields(cls)

@pytest.mark.benchmark()
@pytest.mark.parametrize("cls", [C1, C1Slots])
def test_asdict(self, cls):
"""
Expand Down Expand Up @@ -182,7 +180,6 @@ class C3:

assert "C3(_x=1)" == repr(C3(x=1))

@pytest.mark.benchmark()
@given(booleans(), booleans())
def test_programmatic(self, slots, frozen):
"""
Expand Down Expand Up @@ -340,7 +337,6 @@ def test_metaclass_preserved(self, cls):
"""
assert Meta is type(cls)

@pytest.mark.benchmark()
def test_default_decorator(self):
"""
Default decorator sets the default and the respective method gets
Expand Down Expand Up @@ -544,7 +540,6 @@ class C:
assert "itemgetter" == attr.fields(C).itemgetter.name
assert "x" == attr.fields(C).x.name

@pytest.mark.benchmark()
def test_auto_exc(self, slots, frozen):
"""
Classes with auto_exc=True have a Exception-style __str__, compare and
Expand Down Expand Up @@ -739,7 +734,6 @@ class D(C):
assert "_setattr('y', y)" in src
assert object.__setattr__ != D.__setattr__

@pytest.mark.benchmark()
def test_unsafe_hash(self, slots):
"""
attr.s(unsafe_hash=True) makes a class hashable.
Expand Down
2 changes: 1 addition & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ pass_env =
ARCH
PYTHONHASHSEED
PYTHONMALLOC
commands = pytest --codspeed -n auto
commands = pytest --codspeed -n auto bench/test_benchmarks.py


[testenv:docs]
Expand Down

0 comments on commit 1fd3af0

Please sign in to comment.