Skip to content

Commit 346de4d

Browse files
authored
Add TEA Benchmarks (#2438)
* Add GBench skeleton * Clean dead code & Fix Compilation issues * Add Google Benchmark as a submodule * Use Google Benchmark as a submodule * Remove GBench global buster installation * Change results output dir * Run `benchmarks_tea` during `runall.sh` * Trigger pipeline run on `tea` changes
1 parent bf53bdf commit 346de4d

File tree

13 files changed

+208
-93
lines changed

13 files changed

+208
-93
lines changed

.gitlab/benchmarks.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ benchmarks-tracer:
5858
- zend_abstract_interface/**/*
5959
- tests/Benchmarks/**/*
6060
- benchmark/*
61+
- tea/**/*
6162
compare_to: "master"
6263
when: on_success
6364
- when: manual

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,6 @@
1111
[submodule "appsec/third_party/libddwaf"]
1212
path = appsec/third_party/libddwaf
1313
url = https://github.com/DataDog/libddwaf.git
14+
[submodule "tea/benchmarks/google-benchmark"]
15+
path = tea/benchmarks/google-benchmark
16+
url = https://github.com/google/benchmark.git

Makefile

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ BUILD_DIR = $(PROJECT_ROOT)/tmp/build_$(BUILD_SUFFIX)
88
ZAI_BUILD_DIR = $(PROJECT_ROOT)/tmp/build_zai$(if $(ASAN),_asan)
99
TEA_BUILD_DIR = $(PROJECT_ROOT)/tmp/build_tea$(if $(ASAN),_asan)
1010
TEA_INSTALL_DIR = $(TEA_BUILD_DIR)/opt
11-
TEA_BUILD_TESTS = ON
11+
TEA_BUILD_TESTS ?= OFF
12+
TEA_BUILD_BENCHMARKS ?= OFF
13+
TEA_BENCHMARK_REPETITIONS ?= 10
14+
# Note: If the tea benchmark format or output is changed, make changes to ./benchmark/runall.sh
15+
TEA_BENCHMARK_FORMAT ?= json
16+
TEA_BENCHMARK_OUTPUT ?= $(PROJECT_ROOT)/tea/benchmarks/reports/tea-bench-results.$(TEA_BENCHMARK_FORMAT)
1217
COMPONENTS_BUILD_DIR = $(PROJECT_ROOT)/tmp/build_components
1318
SO_FILE = $(BUILD_DIR)/modules/ddtrace.so
1419
WALL_FLAGS = -Wall -Wextra
@@ -153,16 +158,25 @@ test_extension_ci: $(SO_FILE) $(TEST_FILES) $(TEST_STUB_FILES)
153158
$(RUN_TESTS_CMD) -d extension=$(SO_FILE) -m -s $$TEST_PHP_OUTPUT $(BUILD_DIR)/$(TESTS) && ! grep -e 'LEAKED TEST SUMMARY' $$TEST_PHP_OUTPUT; \
154159
)
155160

156-
build_tea:
161+
build_tea: TEA_BUILD_TESTS=ON
162+
build_tea: TEA_PREFIX_PATH=/opt/catch2
163+
build_tea: build_tea_common
164+
165+
build_tea_benchmarks: TEA_BUILD_BENCHMARKS=ON
166+
build_tea_benchmarks: TEA_PREFIX_PATH=/opt/gbench
167+
build_tea_benchmarks: build_tea_common
168+
169+
build_tea_common:
157170
$(Q) test -f $(TEA_BUILD_DIR)/.built || \
158171
( \
159172
mkdir -p "$(TEA_BUILD_DIR)" "$(TEA_INSTALL_DIR)"; \
160173
cd $(TEA_BUILD_DIR); \
161-
CMAKE_PREFIX_PATH=/opt/catch2 \
174+
CMAKE_PREFIX_PATH=$(TEA_PREFIX_PATH) \
162175
cmake \
163176
-DCMAKE_INSTALL_PREFIX=$(TEA_INSTALL_DIR) \
164177
-DCMAKE_BUILD_TYPE=Debug \
165178
-DBUILD_TEA_TESTING=$(TEA_BUILD_TESTS) \
179+
-DBUILD_TEA_BENCHMARKING=$(TEA_BUILD_BENCHMARKS) \
166180
-DPhpConfig_ROOT=$(shell php-config --prefix) \
167181
$(if $(ASAN), -DCMAKE_TOOLCHAIN_FILE=$(PROJECT_ROOT)/cmake/asan.cmake) \
168182
$(PROJECT_ROOT)/tea; \
@@ -175,13 +189,21 @@ test_tea: clean_tea build_tea
175189
! grep -e "=== Total .* memory leaks detected ===" $(TEA_BUILD_DIR)/Testing/Temporary/LastTest.log; \
176190
)
177191

192+
benchmarks_tea: clean_tea build_tea_benchmarks
193+
$(TEA_BUILD_DIR)/benchmarks/tea_benchmarks \
194+
--benchmark_repetitions=$(TEA_BENCHMARK_REPETITIONS) \
195+
--benchmark_out=$(TEA_BENCHMARK_OUTPUT) \
196+
--benchmark_format=$(TEA_BENCHMARK_FORMAT) \
197+
--benchmark_time_unit=ms
198+
178199
install_tea: build_tea
179200
$(Q) test -f $(TEA_BUILD_DIR)/.installed || \
180201
( \
181202
$(MAKE) -C $(TEA_BUILD_DIR) install; \
182203
touch $(TEA_BUILD_DIR)/.installed; \
183204
)
184205

206+
build_tea_coverage: TEA_BUILD_TESTS=ON
185207
build_tea_coverage:
186208
$(Q) test -f $(TEA_BUILD_DIR)/.built.coverage || \
187209
( \

benchmark/runall.sh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,8 @@ elif [ "$SCENARIO" = "tracer" ]; then
2525
## OPCache Benchmarks
2626
make benchmarks_opcache
2727
cp tests/Benchmarks/reports/tracer-bench-results-opcache.csv "$ARTIFACTS_DIR"
28+
29+
## Request Startup/Shutdown Benchmarks
30+
make benchmarks_tea
31+
cp tea/benchmarks/reports/tea-bench-results.json "$ARTIFACTS_DIR"
2832
fi

tea/CMakeLists.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ if(${BUILD_TEA_TESTING})
8585
add_subdirectory(tests)
8686
endif()
8787

88+
option(BUILD_TEA_BENCHMARKING "Enable TEA benchmarks" OFF)
89+
if(${BUILD_TEA_BENCHMARKING})
90+
add_subdirectory(benchmarks)
91+
endif()
92+
8893
# Copy the include files on install
8994
install(
9095
FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/common.h
@@ -95,6 +100,9 @@ install(
95100
${CMAKE_CURRENT_SOURCE_DIR}/include/sapi.h
96101
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tea)
97102

103+
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/testing/fixture.hpp
104+
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tea/testing)
105+
98106
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/testing/catch2.hpp
99107
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tea/testing)
100108

tea/benchmarks/CMakeLists.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
enable_language(CXX)
2+
3+
set(CMAKE_CXX_STANDARD 11)
4+
5+
add_executable(tea_benchmarks benchmark.cc)
6+
7+
# Google Benchmark is included as a git submodule.
8+
# It depends on Google Test, which it will download if this option is set.
9+
set(BENCHMARK_DOWNLOAD_DEPENDENCIES ON)
10+
# Don't build Google Benchmark's unit tests.
11+
set(BENCHMARK_ENABLE_TESTING OFF)
12+
add_subdirectory(google-benchmark)
13+
14+
target_link_libraries(tea_benchmarks PUBLIC benchmark::benchmark Tea::Tea)

tea/benchmarks/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Microbenchmarks
2+
3+
This directory contains the request **startup** and **shutdown** microbenchmarks.
4+
5+
The benchmarks uses [Google Benchmark](https://github.com/google/benchmark), whose source is included as a git submodule under `./google-benchmark`.
6+
7+
## How to run benchmarks
8+
9+
First refer to the [CONTRIBUTING.md](../../CONTRIBUTING.md) file to setup the environment.
10+
11+
Then you can run the benchmarks with the following command from the root of the repository:
12+
13+
```bash
14+
make benchmarks_tea
15+
```
16+
17+
## How to add a new benchmark
18+
19+
The benchmarks are located in the [benchmark.cc](./benchmark.cc) file and are written using [Google Benchmark](https://github.com/google/benchmark) (v1.8.3).
20+
21+
To add a new benchmark, create a new function in the [benchmark.cc](./benchmark.cc) file. Please, refer to the [User Guide](https://github.com/google/benchmark/blob/main/docs/user_guide.md) for more information.
22+
23+
## Results
24+
25+
The results of the benchmark are stored under the [reports](./reports) folder.

tea/benchmarks/benchmark.cc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
#include <iostream>
2+
#include <memory>
3+
#include <benchmark/benchmark.h>
4+
#include <include/testing/fixture.hpp>
5+
#include <Zend/zend_exceptions.h>
6+
7+
static void BM_TeaSapiSpinup(benchmark::State& state) {
8+
TeaTestCaseFixture fixture;
9+
for (auto _ : state) {
10+
fixture.tea_sapi_spinup();
11+
12+
state.PauseTiming();
13+
fixture.tea_sapi_spindown();
14+
state.ResumeTiming();
15+
}
16+
}
17+
BENCHMARK(BM_TeaSapiSpinup);
18+
19+
static void BM_TeaSapiSpindown(benchmark::State& state) {
20+
TeaTestCaseFixture fixture;
21+
for (auto _ : state) {
22+
state.PauseTiming();
23+
fixture.tea_sapi_spinup();
24+
state.ResumeTiming();
25+
26+
fixture.tea_sapi_spindown();
27+
}
28+
}
29+
BENCHMARK(BM_TeaSapiSpindown);
30+
31+
BENCHMARK_MAIN();

tea/benchmarks/google-benchmark

Submodule google-benchmark added at 3441176

tea/benchmarks/reports/.gitkeep

Whitespace-only changes.

tea/config.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ if test "$PHP_TEA" != "no"; then
2121
AC_DEFINE(HAVE_TEA, 1, [ ])
2222

2323
PHP_TEA_INCLUDE="sapi/tea/include"
24-
PHP_TEA_HEADERS="common.h error.h exceptions.h extension.h frame.h sapi.h testing/catch2.hpp"
24+
PHP_TEA_HEADERS="common.h error.h exceptions.h extension.h frame.h sapi.h testing/fixture.hpp testing/catch2.hpp"
2525
PHP_TEA_CFLAGS="-I${abs_srcdir}/${PHP_TEA_INCLUDE}"
2626
PHP_TEA_FILES="src/error.c src/exceptions.c src/frame.c src/io.c src/ini.c src/extension.c src/sapi.c"
2727

tea/include/testing/catch2.hpp

Lines changed: 1 addition & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,7 @@
3838
* Code or cases tested with bailout will fail if code does not bail
3939
* Code or cases tested without bailout will fail if code bails
4040
*/
41-
extern "C" {
42-
#include "../sapi.h"
43-
}
41+
#include "fixture.hpp"
4442

4543
#include <catch2/catch.hpp>
4644

@@ -65,92 +63,6 @@ extern "C" {
6563
__TEA_TEST_CASE_SUITE " [" __TEA_TEST_CASE_DESCRIPTION "]", \
6664
"[" __TEA_TEST_CASE_SUITE "]" __TEA_TEST_CASE_TAGS /* }}} */
6765

68-
/* {{{ Test Case Fixing */
69-
typedef enum {
70-
TEA_TEST_CASE_STAGE_INITIAL = 0b000,
71-
TEA_TEST_CASE_STAGE_PROLOGUE = 0b001,
72-
TEA_TEST_CASE_STAGE_PREFORK = 0b010,
73-
TEA_TEST_CASE_STAGE_REQUEST = 0b100
74-
} TeaTestCaseStage;
75-
76-
class TeaTestCaseFixture {
77-
public:
78-
TeaTestCaseFixture() {
79-
stage = TEA_TEST_CASE_STAGE_INITIAL;
80-
}
81-
82-
bool tea_sapi_sinit() {
83-
if (::tea_sapi_sinit()) {
84-
stage |= TEA_TEST_CASE_STAGE_PROLOGUE;
85-
return true;
86-
}
87-
return false;
88-
}
89-
90-
bool tea_sapi_minit() {
91-
if (::tea_sapi_minit()) {
92-
stage |= TEA_TEST_CASE_STAGE_PREFORK;
93-
return true;
94-
}
95-
return false;
96-
}
97-
98-
bool tea_sapi_rinit() {
99-
if (::tea_sapi_rinit()) {
100-
stage |= TEA_TEST_CASE_STAGE_REQUEST;
101-
return true;
102-
}
103-
return false;
104-
}
105-
106-
bool tea_sapi_spinup() {
107-
return tea_sapi_sinit() &&
108-
tea_sapi_minit() &&
109-
tea_sapi_rinit();
110-
}
111-
112-
void tea_sapi_rshutdown() {
113-
stage &= ~TEA_TEST_CASE_STAGE_REQUEST;
114-
115-
::tea_sapi_rshutdown();
116-
}
117-
118-
void tea_sapi_mshutdown() {
119-
stage &= ~TEA_TEST_CASE_STAGE_PREFORK;
120-
121-
::tea_sapi_mshutdown();
122-
}
123-
124-
void tea_sapi_sshutdown() {
125-
stage &= ~TEA_TEST_CASE_STAGE_PROLOGUE;
126-
127-
::tea_sapi_sshutdown();
128-
}
129-
130-
void tea_sapi_spindown() {
131-
tea_sapi_rshutdown();
132-
tea_sapi_mshutdown();
133-
tea_sapi_sshutdown();
134-
}
135-
136-
virtual ~TeaTestCaseFixture() {
137-
if (stage & TEA_TEST_CASE_STAGE_REQUEST) {
138-
tea_sapi_rshutdown();
139-
}
140-
141-
if (stage & TEA_TEST_CASE_STAGE_PREFORK) {
142-
tea_sapi_mshutdown();
143-
}
144-
145-
if (stage & TEA_TEST_CASE_STAGE_PROLOGUE) {
146-
tea_sapi_sshutdown();
147-
}
148-
}
149-
150-
private:
151-
unsigned int stage;
152-
};
153-
15466
#define TEA_TEST_CASE_DECL(...) \
15567
TEST_CASE_METHOD( \
15668
TeaTestCaseFixture, \

tea/include/testing/fixture.hpp

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
#ifndef HAVE_TEA_FIXTURE
2+
#define HAVE_TEA_FIXTURE
3+
4+
extern "C" {
5+
#include "../sapi.h"
6+
};
7+
8+
/* {{{ Test Case Fixing */
9+
typedef enum {
10+
TEA_TEST_CASE_STAGE_INITIAL = 0b000,
11+
TEA_TEST_CASE_STAGE_PROLOGUE = 0b001,
12+
TEA_TEST_CASE_STAGE_PREFORK = 0b010,
13+
TEA_TEST_CASE_STAGE_REQUEST = 0b100
14+
} TeaTestCaseStage;
15+
16+
class TeaTestCaseFixture {
17+
public:
18+
TeaTestCaseFixture() {
19+
stage = TEA_TEST_CASE_STAGE_INITIAL;
20+
}
21+
22+
bool tea_sapi_sinit() {
23+
if (::tea_sapi_sinit()) {
24+
stage |= TEA_TEST_CASE_STAGE_PROLOGUE;
25+
return true;
26+
}
27+
return false;
28+
}
29+
30+
bool tea_sapi_minit() {
31+
if (::tea_sapi_minit()) {
32+
stage |= TEA_TEST_CASE_STAGE_PREFORK;
33+
return true;
34+
}
35+
return false;
36+
}
37+
38+
bool tea_sapi_rinit() {
39+
if (::tea_sapi_rinit()) {
40+
stage |= TEA_TEST_CASE_STAGE_REQUEST;
41+
return true;
42+
}
43+
return false;
44+
}
45+
46+
bool tea_sapi_spinup() {
47+
return tea_sapi_sinit() &&
48+
tea_sapi_minit() &&
49+
tea_sapi_rinit();
50+
}
51+
52+
void tea_sapi_rshutdown() {
53+
stage &= ~TEA_TEST_CASE_STAGE_REQUEST;
54+
55+
::tea_sapi_rshutdown();
56+
}
57+
58+
void tea_sapi_mshutdown() {
59+
stage &= ~TEA_TEST_CASE_STAGE_PREFORK;
60+
61+
::tea_sapi_mshutdown();
62+
}
63+
64+
void tea_sapi_sshutdown() {
65+
stage &= ~TEA_TEST_CASE_STAGE_PROLOGUE;
66+
67+
::tea_sapi_sshutdown();
68+
}
69+
70+
void tea_sapi_spindown() {
71+
tea_sapi_rshutdown();
72+
tea_sapi_mshutdown();
73+
tea_sapi_sshutdown();
74+
}
75+
76+
virtual ~TeaTestCaseFixture() {
77+
if (stage & TEA_TEST_CASE_STAGE_REQUEST) {
78+
tea_sapi_rshutdown();
79+
}
80+
81+
if (stage & TEA_TEST_CASE_STAGE_PREFORK) {
82+
tea_sapi_mshutdown();
83+
}
84+
85+
if (stage & TEA_TEST_CASE_STAGE_PROLOGUE) {
86+
tea_sapi_sshutdown();
87+
}
88+
}
89+
90+
private:
91+
unsigned int stage;
92+
};
93+
94+
#endif // HAVE_TEA_FIXTURE

0 commit comments

Comments
 (0)