Skip to content

Commit e99b49a

Browse files
committedMar 12, 2025
Add simple parser benchmarking.
1 parent 3ab7742 commit e99b49a

File tree

4 files changed

+116
-0
lines changed

4 files changed

+116
-0
lines changed
 

‎spicy/runtime/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,7 @@ target_link_libraries(spicy-rt-tests
9999
PRIVATE $<IF:$<CONFIG:Debug>,spicy-rt-debug-objects,spicy-rt-objects>)
100100
target_link_libraries(spicy-rt-tests PRIVATE $<IF:$<CONFIG:Debug>,spicy-rt-debug,spicy-rt> doctest)
101101
add_test(NAME spicy-rt-tests COMMAND ${PROJECT_BINARY_DIR}/bin/spicy-rt-tests)
102+
103+
if (${USE_BENCHMARK})
104+
add_subdirectory(src/benchmarks/)
105+
endif ()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2+
3+
set(BENCH_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/parsers.spicy")
4+
set(BENCH_MODULE Benchmark)
5+
6+
list(TRANSFORM BENCH_MODULE PREPEND Benchmark_ OUTPUT_VARIABLE _generated_sources)
7+
list(TRANSFORM _generated_sources APPEND ".cc" OUTPUT_VARIABLE _generated_sources)
8+
list(APPEND _generated_sources "Benchmark___linker__.cc")
9+
10+
add_custom_command(
11+
OUTPUT ${_generated_sources}
12+
COMMAND ${CMAKE_BINARY_DIR}/bin/spicyc -x ${CMAKE_CURRENT_BINARY_DIR}/Benchmark
13+
"${BENCH_SOURCES}"
14+
DEPENDS spicyc
15+
COMMENT "Generating C++ code for Benchmark")
16+
17+
add_executable(spicy-rt-parsing-benchmark parsing.cc ${_generated_sources})
18+
target_compile_options(spicy-rt-parsing-benchmark PRIVATE "-Wall")
19+
target_link_libraries(spicy-rt-parsing-benchmark
20+
PRIVATE $<IF:$<CONFIG:Debug>,spicy-rt-debug,spicy-rt>)
21+
target_link_libraries(spicy-rt-parsing-benchmark
22+
PRIVATE $<IF:$<CONFIG:Debug>,hilti-rt-debug,hilti-rt>)
23+
target_link_libraries(spicy-rt-parsing-benchmark PRIVATE benchmark)
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2+
3+
module Benchmark;
4+
5+
public type WithUnit = unit {
6+
length: uint64;
7+
inner: Inner[] &size=self.length;
8+
end_: b"BB";
9+
};
10+
11+
type Inner = unit {
12+
b: uint8;
13+
};
14+
15+
public type Regex = unit {
16+
length: uint64;
17+
data: /A*/;
18+
end_: b"BB";
19+
};
+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Copyright (c) 2020-now by the Zeek Project. See LICENSE for details.
2+
3+
#include <benchmark/benchmark.h>
4+
5+
#include <hilti/rt/init.h>
6+
#include <hilti/rt/types/reference.h>
7+
#include <hilti/rt/types/stream.h>
8+
9+
#include <spicy/rt/init.h>
10+
#include <spicy/rt/parsed-unit.h>
11+
#include <spicy/rt/parser.h>
12+
13+
static std::string big_endian(std::uint64_t number) {
14+
char buffer[8];
15+
for ( int i = 0; i < 8; ++i ) {
16+
buffer[i] = static_cast<char>((number >> (56 - 8 * i)) & 0xFF);
17+
}
18+
return std::string(buffer, sizeof(buffer));
19+
}
20+
21+
static std::string make_input(std::uint64_t input_size) {
22+
std::string number = big_endian(input_size);
23+
std::string repeated(input_size, 'A');
24+
return number + repeated + 'B' + 'B';
25+
}
26+
27+
template<class... Args>
28+
static void benchmark_parser(benchmark::State& state, Args&&... args) {
29+
auto args_tuple = std::make_tuple(std::move(args)...);
30+
auto parser_name = std::get<0>(args_tuple);
31+
32+
hilti::rt::init();
33+
spicy::rt::init();
34+
35+
static const spicy::rt::Parser* parser = nullptr;
36+
for ( auto* p : spicy::rt::parsers() ) {
37+
if ( p->name == parser_name ) {
38+
parser = p;
39+
break;
40+
}
41+
}
42+
43+
assert(parser);
44+
45+
for ( auto _ : state ) {
46+
(void)_;
47+
state.PauseTiming();
48+
auto in = make_input(state.range(0));
49+
auto stream = hilti::rt::reference::make_value<hilti::rt::Stream>(in);
50+
stream->freeze();
51+
state.ResumeTiming();
52+
parser->parse1(stream, {}, {});
53+
}
54+
55+
hilti::rt::done();
56+
}
57+
58+
static const int64_t min_input = 100;
59+
static const int64_t max_input = 100000;
60+
static const int64_t mult = 10;
61+
62+
BENCHMARK_CAPTURE(benchmark_parser, Benchmark::WithUnit, std::string("Benchmark::WithUnit"))
63+
->RangeMultiplier(mult)
64+
->Range(min_input, max_input);
65+
66+
BENCHMARK_CAPTURE(benchmark_parser, Benchmark::Regex, std::string("Benchmark::Regex"))
67+
->RangeMultiplier(mult)
68+
->Range(min_input, max_input);
69+
70+
BENCHMARK_MAIN();

0 commit comments

Comments
 (0)