Skip to content

Commit 549685a

Browse files
committed
Remove custom testing and benchmarking code.
Snappy includes a testing framework, which implements a subset of the Google Test API, and can be used when Google Test is not available. Snappy also includes a micro-benchmark framework, which implements an old version of the Google Benchmark API. This CL replaces the custom test and micro-benchmark frameworks with google/googletest and google/benchmark. The code is vendored in third_party/ via git submodules. The setup is similar to google/crc32c and google/leveldb. This CL also updates the benchmarking code to the modern Google Benchmark API. Benchmark results are expected to be more precise, as the old framework ran each benchmark with a fixed number of iterations, whereas Google Benchmark keeps iterating until the noise is low. PiperOrigin-RevId: 347456142
1 parent 11f9a77 commit 549685a

File tree

7 files changed

+154
-433
lines changed

7 files changed

+154
-433
lines changed

.gitmodules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
[submodule "third_party/benchmark"]
2+
path = third_party/benchmark
3+
url = https://github.com/google/benchmark.git
4+
[submodule "third_party/googletest"]
5+
path = third_party/googletest
6+
url = https://github.com/google/googletest.git

CMakeLists.txt

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ elseif (SNAPPY_REQUIRE_AVX)
134134
endif(HAVE_CLANG_MAVX)
135135
endif(SNAPPY_REQUIRE_AVX2)
136136

137+
# Used by googletest.
138+
check_cxx_compiler_flag(-Wno-missing-field-initializers
139+
SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
140+
137141
include(CheckCXXSourceCompiles)
138142
check_cxx_source_compiles("
139143
int main() {
@@ -174,11 +178,6 @@ include(CheckSymbolExists)
174178
check_symbol_exists("mmap" "sys/mman.h" HAVE_FUNC_MMAP)
175179
check_symbol_exists("sysconf" "unistd.h" HAVE_FUNC_SYSCONF)
176180

177-
find_package(GTest QUIET)
178-
if(GTEST_FOUND)
179-
set(HAVE_GTEST 1)
180-
endif(GTEST_FOUND)
181-
182181
find_package(Gflags QUIET)
183182
if(GFLAGS_FOUND OR GFLAGS_TARGET)
184183
set(HAVE_GFLAGS 1)
@@ -254,14 +253,37 @@ endif(BUILD_SHARED_LIBS)
254253
if(SNAPPY_BUILD_TESTS)
255254
enable_testing()
256255

256+
# Prevent overriding the parent project's compiler/linker settings on Windows.
257+
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
258+
set(install_gtest OFF)
259+
set(install_gmock OFF)
260+
set(build_gmock ON)
261+
262+
# This project is tested using GoogleTest.
263+
add_subdirectory("third_party/googletest")
264+
265+
# This project uses Google benchmark for benchmarking.
266+
set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
267+
set(BENCHMARK_ENABLE_EXCEPTIONS OFF CACHE BOOL "" FORCE)
268+
add_subdirectory("third_party/benchmark")
269+
270+
# GoogleTest triggers a missing field initializers warning.
271+
if(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
272+
set_property(TARGET gtest
273+
APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
274+
set_property(TARGET gmock
275+
APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-field-initializers)
276+
endif(SNAPPY_HAVE_NO_MISSING_FIELD_INITIALIZERS)
277+
257278
add_executable(snappy_unittest "")
258279
target_sources(snappy_unittest
259280
PRIVATE
260281
"snappy_unittest.cc"
261282
"snappy-test.cc"
262283
)
263284
target_compile_definitions(snappy_unittest PRIVATE -DHAVE_CONFIG_H)
264-
target_link_libraries(snappy_unittest snappy ${GFLAGS_LIBRARIES} ${GTEST_LIBRARY})
285+
target_link_libraries(snappy_unittest
286+
snappy ${GFLAGS_LIBRARIES} gmock gtest benchmark)
265287

266288
if(HAVE_LIBZ)
267289
target_link_libraries(snappy_unittest z)
@@ -276,7 +298,6 @@ if(SNAPPY_BUILD_TESTS)
276298
target_include_directories(snappy_unittest
277299
BEFORE PRIVATE
278300
"${PROJECT_SOURCE_DIR}"
279-
"${GTEST_INCLUDE_DIRS}"
280301
"${GFLAGS_INCLUDE_DIRS}"
281302
)
282303

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
master, TBD:
2+
3+
* Performance improvements.
4+
5+
* Google Test and Google Benchmark are now bundled in third_party/.
6+
17
Snappy v1.1.8, January 15th 2020:
28

39
* Small performance improvements.

README.md

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ You need the CMake version specified in [CMakeLists.txt](./CMakeLists.txt)
7070
or later to build:
7171

7272
```bash
73+
git submodule update --init
7374
mkdir build
7475
cd build && cmake ../ && make
7576
```
@@ -114,14 +115,10 @@ but it contains several useful components for Snappy development.
114115

115116
First of all, it contains unit tests, verifying correctness on your machine in
116117
various scenarios. If you want to change or optimize Snappy, please run the
117-
tests to verify you have not broken anything. Note that if you have the
118-
Google Test library installed, unit test behavior (especially failures) will be
119-
significantly more user-friendly. You can find Google Test at
118+
tests to verify you have not broken anything.
120119

121-
https://github.com/google/googletest
122-
123-
You probably also want the gflags library for handling of command-line flags;
124-
you can find it at
120+
The gflags library for handling of command-line flags is used if it's installed.
121+
You can find it at
125122

126123
https://gflags.github.io/gflags/
127124

@@ -145,5 +142,5 @@ test.)
145142
Contact
146143
=======
147144

148-
Snappy is distributed through GitHub. For the latest version, a bug tracker,
149-
and other information, see https://github.com/google/snappy.
145+
Snappy is distributed through GitHub. For the latest version and other
146+
information, see https://github.com/google/snappy.

snappy-test.cc

Lines changed: 0 additions & 185 deletions
Original file line numberDiff line numberDiff line change
@@ -76,191 +76,6 @@ std::string StrFormat(const char* format, ...) {
7676
return buf;
7777
}
7878

79-
bool benchmark_running = false;
80-
int64_t benchmark_real_time_us = 0;
81-
int64_t benchmark_cpu_time_us = 0;
82-
std::string* benchmark_label = nullptr;
83-
int64_t benchmark_bytes_processed = 0;
84-
85-
void ResetBenchmarkTiming() {
86-
benchmark_real_time_us = 0;
87-
benchmark_cpu_time_us = 0;
88-
}
89-
90-
#ifdef WIN32
91-
LARGE_INTEGER benchmark_start_real;
92-
FILETIME benchmark_start_cpu;
93-
#else // WIN32
94-
struct timeval benchmark_start_real;
95-
struct rusage benchmark_start_cpu;
96-
#endif // WIN32
97-
98-
void StartBenchmarkTiming() {
99-
#ifdef WIN32
100-
QueryPerformanceCounter(&benchmark_start_real);
101-
FILETIME dummy;
102-
CHECK(GetProcessTimes(
103-
GetCurrentProcess(), &dummy, &dummy, &dummy, &benchmark_start_cpu));
104-
#else
105-
gettimeofday(&benchmark_start_real, NULL);
106-
if (getrusage(RUSAGE_SELF, &benchmark_start_cpu) == -1) {
107-
std::perror("getrusage(RUSAGE_SELF)");
108-
std::exit(1);
109-
}
110-
#endif
111-
benchmark_running = true;
112-
}
113-
114-
void StopBenchmarkTiming() {
115-
if (!benchmark_running) {
116-
return;
117-
}
118-
119-
#ifdef WIN32
120-
LARGE_INTEGER benchmark_stop_real;
121-
LARGE_INTEGER benchmark_frequency;
122-
QueryPerformanceCounter(&benchmark_stop_real);
123-
QueryPerformanceFrequency(&benchmark_frequency);
124-
125-
double elapsed_real = static_cast<double>(
126-
benchmark_stop_real.QuadPart - benchmark_start_real.QuadPart) /
127-
benchmark_frequency.QuadPart;
128-
benchmark_real_time_us += elapsed_real * 1e6 + 0.5;
129-
130-
FILETIME benchmark_stop_cpu, dummy;
131-
CHECK(GetProcessTimes(
132-
GetCurrentProcess(), &dummy, &dummy, &dummy, &benchmark_stop_cpu));
133-
134-
ULARGE_INTEGER start_ulargeint;
135-
start_ulargeint.LowPart = benchmark_start_cpu.dwLowDateTime;
136-
start_ulargeint.HighPart = benchmark_start_cpu.dwHighDateTime;
137-
138-
ULARGE_INTEGER stop_ulargeint;
139-
stop_ulargeint.LowPart = benchmark_stop_cpu.dwLowDateTime;
140-
stop_ulargeint.HighPart = benchmark_stop_cpu.dwHighDateTime;
141-
142-
benchmark_cpu_time_us +=
143-
(stop_ulargeint.QuadPart - start_ulargeint.QuadPart + 5) / 10;
144-
#else // WIN32
145-
struct timeval benchmark_stop_real;
146-
gettimeofday(&benchmark_stop_real, NULL);
147-
benchmark_real_time_us +=
148-
1000000 * (benchmark_stop_real.tv_sec - benchmark_start_real.tv_sec);
149-
benchmark_real_time_us +=
150-
(benchmark_stop_real.tv_usec - benchmark_start_real.tv_usec);
151-
152-
struct rusage benchmark_stop_cpu;
153-
if (getrusage(RUSAGE_SELF, &benchmark_stop_cpu) == -1) {
154-
std::perror("getrusage(RUSAGE_SELF)");
155-
std::exit(1);
156-
}
157-
benchmark_cpu_time_us += 1000000 * (benchmark_stop_cpu.ru_utime.tv_sec -
158-
benchmark_start_cpu.ru_utime.tv_sec);
159-
benchmark_cpu_time_us += (benchmark_stop_cpu.ru_utime.tv_usec -
160-
benchmark_start_cpu.ru_utime.tv_usec);
161-
#endif // WIN32
162-
163-
benchmark_running = false;
164-
}
165-
166-
void SetBenchmarkLabel(const std::string& str) {
167-
if (benchmark_label) {
168-
delete benchmark_label;
169-
}
170-
benchmark_label = new std::string(str);
171-
}
172-
173-
void SetBenchmarkBytesProcessed(int64_t bytes) {
174-
benchmark_bytes_processed = bytes;
175-
}
176-
177-
struct BenchmarkRun {
178-
int64_t real_time_us;
179-
int64_t cpu_time_us;
180-
};
181-
182-
struct BenchmarkCompareCPUTime {
183-
bool operator() (const BenchmarkRun& a, const BenchmarkRun& b) const {
184-
return a.cpu_time_us < b.cpu_time_us;
185-
}
186-
};
187-
188-
void Benchmark::Run() {
189-
for (int test_case_num = start_; test_case_num <= stop_; ++test_case_num) {
190-
// Run a few iterations first to find out approximately how fast
191-
// the benchmark is.
192-
const int kCalibrateIterations = 100;
193-
ResetBenchmarkTiming();
194-
StartBenchmarkTiming();
195-
(*function_)(kCalibrateIterations, test_case_num);
196-
StopBenchmarkTiming();
197-
198-
// Let each test case run for about 200ms, but at least as many
199-
// as we used to calibrate.
200-
// Run five times and pick the median.
201-
const int kNumRuns = 5;
202-
const int kMedianPos = kNumRuns / 2;
203-
int num_iterations = 0;
204-
if (benchmark_real_time_us > 0) {
205-
num_iterations = 200000 * kCalibrateIterations / benchmark_real_time_us;
206-
}
207-
num_iterations = std::max(num_iterations, kCalibrateIterations);
208-
BenchmarkRun benchmark_runs[kNumRuns];
209-
210-
for (int run = 0; run < kNumRuns; ++run) {
211-
ResetBenchmarkTiming();
212-
StartBenchmarkTiming();
213-
(*function_)(num_iterations, test_case_num);
214-
StopBenchmarkTiming();
215-
216-
benchmark_runs[run].real_time_us = benchmark_real_time_us;
217-
benchmark_runs[run].cpu_time_us = benchmark_cpu_time_us;
218-
}
219-
220-
std::string heading = StrFormat("%s/%d", name_.c_str(), test_case_num);
221-
std::string human_readable_speed;
222-
223-
std::nth_element(benchmark_runs,
224-
benchmark_runs + kMedianPos,
225-
benchmark_runs + kNumRuns,
226-
BenchmarkCompareCPUTime());
227-
int64_t real_time_us = benchmark_runs[kMedianPos].real_time_us;
228-
int64_t cpu_time_us = benchmark_runs[kMedianPos].cpu_time_us;
229-
if (cpu_time_us <= 0) {
230-
human_readable_speed = "?";
231-
} else {
232-
int64_t bytes_per_second =
233-
benchmark_bytes_processed * 1000000 / cpu_time_us;
234-
if (bytes_per_second < 1024) {
235-
human_readable_speed =
236-
StrFormat("%dB/s", static_cast<int>(bytes_per_second));
237-
} else if (bytes_per_second < 1024 * 1024) {
238-
human_readable_speed = StrFormat(
239-
"%.1fkB/s", bytes_per_second / 1024.0f);
240-
} else if (bytes_per_second < 1024 * 1024 * 1024) {
241-
human_readable_speed = StrFormat(
242-
"%.1fMB/s", bytes_per_second / (1024.0f * 1024.0f));
243-
} else {
244-
human_readable_speed = StrFormat(
245-
"%.1fGB/s", bytes_per_second / (1024.0f * 1024.0f * 1024.0f));
246-
}
247-
}
248-
249-
std::fprintf(stderr,
250-
#ifdef WIN32
251-
"%-18s %10I64d %10I64d %10d %s %s\n",
252-
#else
253-
"%-18s %10lld %10lld %10d %s %s\n",
254-
#endif
255-
heading.c_str(),
256-
static_cast<long long>(real_time_us * 1000 / num_iterations),
257-
static_cast<long long>(cpu_time_us * 1000 / num_iterations),
258-
num_iterations,
259-
human_readable_speed.c_str(),
260-
benchmark_label->c_str());
261-
}
262-
}
263-
26479
#ifdef HAVE_LIBZ
26580

26681
ZLib::ZLib()

0 commit comments

Comments
 (0)