Skip to content

Commit 0e27409

Browse files
authored
Add expression and parser benchmarks (#145)
1 parent a282438 commit 0e27409

1 file changed

Lines changed: 89 additions & 0 deletions

File tree

tests/test_benchmark.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
from __future__ import annotations
22

3+
from functools import partial
34
from typing import TYPE_CHECKING
45

56
import pytest
67

8+
from dissect.cstruct.expression import Expression
9+
710
if TYPE_CHECKING:
811
from pytest_benchmark.fixture import BenchmarkFixture
912

@@ -85,3 +88,89 @@ def test_benchmark_getattr_typedefs(cs: cstruct, benchmark: BenchmarkFixture) ->
8588
cs.load(cdef)
8689

8790
benchmark(lambda: cs.my_uint8)
91+
92+
93+
@pytest.mark.benchmark
94+
def test_benchmark_expression_parse(cs: cstruct, benchmark: BenchmarkFixture) -> None:
95+
"""Benchmark the parsing of expressions."""
96+
cs.load("#define a 5\n#define b 10")
97+
98+
benchmark(lambda: Expression("a * 2 + b * (3 + 4) >> 1"))
99+
100+
101+
@pytest.mark.benchmark
102+
def test_benchmark_expression_evaluate(cs: cstruct, benchmark: BenchmarkFixture) -> None:
103+
"""Benchmark the evaluation of expressions."""
104+
cs.load("#define a 5\n#define b 10")
105+
106+
expression = Expression("a * 2 + b * (3 + 4) >> 1")
107+
benchmark(lambda: expression.evaluate(cs))
108+
109+
110+
@pytest.mark.benchmark
111+
def test_benchmark_expression_parse_and_evaluate(cs: cstruct, benchmark: BenchmarkFixture) -> None:
112+
"""Benchmark the parsing and evaluation of expressions."""
113+
cs.load("#define a 5\n#define b 10")
114+
115+
benchmark(lambda: Expression("a * 2 + b * (3 + 4) >> 1").evaluate(cs))
116+
117+
118+
_BENCHMARK_CDEF = """
119+
struct SECURITY_DESCRIPTOR {
120+
uint8 Revision;
121+
uint8 Sbz1;
122+
uint16 Control;
123+
uint32 OffsetOwner;
124+
uint32 OffsetGroup;
125+
uint32 OffsetSacl;
126+
uint32 OffsetDacl;
127+
};
128+
129+
struct LDAP_SID_IDENTIFIER_AUTHORITY {
130+
char Value[6];
131+
};
132+
133+
struct LDAP_SID {
134+
uint8 Revision;
135+
uint8 SubAuthorityCount;
136+
LDAP_SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
137+
uint32 SubAuthority[SubAuthorityCount];
138+
};
139+
140+
struct ACL {
141+
uint8 AclRevision;
142+
uint8 Sbz1;
143+
uint16 AclSize;
144+
uint16 AceCount;
145+
uint16 Sbz2;
146+
char Data[AclSize - 8];
147+
};
148+
149+
struct ACE {
150+
uint8 AceType;
151+
uint8 AceFlags;
152+
uint16 AceSize;
153+
char Data[AceSize - 4];
154+
};
155+
156+
struct ACCESS_ALLOWED_ACE {
157+
uint16 Mask;
158+
LDAP_SID Sid;
159+
};
160+
161+
struct ACCESS_ALLOWED_OBJECT_ACE {
162+
uint32 Mask;
163+
uint32 Flags;
164+
char ObjectType[(Flags & 1) * 16];
165+
char InheritedObjectType[(Flags & 2) * 8];
166+
LDAP_SID Sid;
167+
};
168+
"""
169+
170+
171+
@pytest.mark.benchmark
172+
def test_benchmark_lexer_and_parser(cs: cstruct, benchmark: BenchmarkFixture) -> None:
173+
"""Benchmark tokenizing and parsing a realistic set of struct definitions."""
174+
cs.add_type = partial(cs.add_type, replace=True)
175+
176+
benchmark(lambda: cs.load(_BENCHMARK_CDEF))

0 commit comments

Comments
 (0)