]> git.ipfire.org Git - thirdparty/ccache.git/commitdiff
feat: Add benchmarks for source code scanning master
authorJoel Rosdahl <joel@rosdahl.net>
Wed, 15 Jul 2026 14:40:19 +0000 (16:40 +0200)
committerJoel Rosdahl <joel@rosdahl.net>
Thu, 16 Jul 2026 13:27:02 +0000 (15:27 +0200)
.clang-format
CMakeLists.txt
benchmark/CMakeLists.txt [new file with mode: 0644]
benchmark/benchmark_hashutil.cpp [new file with mode: 0644]
benchmark/main.cpp [new file with mode: 0644]
doc/install.md

index 48a1542189a44531c2e0c81948b6180a3ca30be3..87bf8073622179a8a12b27a9b60eb116eedf35b5 100644 (file)
@@ -32,7 +32,7 @@ IncludeCategories:
   - Regex: '^<ccache/'
     Priority: 2
   # Dependency headers:
-  - Regex: '^<(blake3\.h|cxxurl/url\.hpp|doctest/.*|fmt/.*|hiredis/.*|httplib\.h|tl/expected\.hpp|xx(hash|h_x86dispatch)\.h|zstd\.h)>$'
+  - Regex: '^<(benchmark/.*|blake3\.h|cxxurl/url\.hpp|doctest/.*|fmt/.*|hiredis/.*|httplib\.h|tl/expected\.hpp|xx(hash|h_x86dispatch)\.h|zstd\.h)>$'
     Priority: 3
   # System headers:
   - Regex: '\.h.*>$'
index 2c2657f26f7aa7320aa0600964109a9b2dda8ecd..c65b00181f2ce70df031b9f9d522f8430ed397bc 100644 (file)
@@ -69,6 +69,7 @@ include(EnableCcache)
 
 option(REDIS_STORAGE_BACKEND "Enable Redis remote storage" ON)
 option(HTTP_STORAGE_BACKEND "Enable HTTP remote storage" ON)
+option(ENABLE_BENCHMARKS "Enable benchmarks" OFF)
 option(ENABLE_TESTING "Enable tests" ON)
 
 include(InstallDirs)
@@ -151,6 +152,13 @@ if(ENABLE_TESTING)
     DEPENDS ccache unittest)
 endif()
 
+#
+# Benchmarks
+#
+if(ENABLE_BENCHMARKS)
+  add_subdirectory(benchmark)
+endif()
+
 #
 # Special formatting targets
 #
diff --git a/benchmark/CMakeLists.txt b/benchmark/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dc99847
--- /dev/null
@@ -0,0 +1,47 @@
+include(FetchContent)
+
+set(_benchmark_version_string 1.9.5)
+message(STATUS "Downloading Google Benchmark ${_benchmark_version_string}")
+
+set(BENCHMARK_ENABLE_GTEST_TESTS OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_TESTING OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_ENABLE_WERROR OFF CACHE BOOL "" FORCE)
+set(BENCHMARK_DOWNLOAD_DEPENDENCIES OFF CACHE BOOL "" FORCE)
+
+FetchContent_Declare(
+  benchmark
+  DOWNLOAD_EXTRACT_TIMESTAMP TRUE
+  URL "https://github.com/google/benchmark/archive/refs/tags/v${_benchmark_version_string}.tar.gz"
+  URL_HASH SHA256=9631341c82bac4a288bef951f8b26b41f69021794184ece969f8473977eaa340
+)
+FetchContent_MakeAvailable(benchmark)
+
+register_dependency(GoogleBenchmark DOWNLOADED "${_benchmark_version_string}")
+
+set(
+  source_files
+  main.cpp
+  benchmark_hashutil.cpp
+)
+
+add_executable(ccache_benchmark ${source_files})
+
+target_link_libraries(
+  ccache_benchmark
+  PRIVATE standard_settings standard_warnings ccache_framework benchmark::benchmark
+)
+
+target_include_directories(
+  ccache_benchmark
+  PRIVATE ${CMAKE_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${ccache_SOURCE_DIR}/src
+)
+
+add_custom_target(
+  benchmarks
+  COMMAND ccache_benchmark
+  WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+  DEPENDS ccache_benchmark
+  COMMENT "Running benchmarks"
+  USES_TERMINAL
+)
diff --git a/benchmark/benchmark_hashutil.cpp b/benchmark/benchmark_hashutil.cpp
new file mode 100644 (file)
index 0000000..244424f
--- /dev/null
@@ -0,0 +1,139 @@
+// Copyright (C) 2026 Joel Rosdahl and other contributors
+//
+// See doc/authors.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include <ccache/hash.hpp>
+#include <ccache/hashutil.hpp>
+
+#include <benchmark/benchmark.h>
+
+#include <string>
+#include <string_view>
+
+namespace {
+
+std::string
+generate_source_code(size_t size)
+{
+  // Synthetic preprocessed-C++-like code, hopefully reasonably representative
+  // of real source code.
+  //
+  // For our purposes, it's the frequency of _ (for temporal macro matching), .
+  // (for incbin matching) and # (for embed matching) that is of most
+  // importance.
+  static constexpr std::string_view corpus =
+    R"(# 42 "/usr/include/foo/bar/banana.h" 3
+
+namespace std _FOO_VISIBILITY(default) {
+
+constexpr double __one = 17.0 / 42.0;
+auto __pair = std::make_pair(__one, __one);
+__result._some_payload._do_bar(__one);
+__state._some_storage._do_foo();
+
+const char* __msg = "hello world";
+const char* __file = "/usr/include/hello.h";
+
+template<typename _ForwardIterator, typename _Compare>
+inline _ForwardIterator
+__some_name(_ForwardIterator __first, _ForwardIterator __last,
+            _ForwardIterator __middle, _Compare __comp)
+{
+  while (true) {
+    while (__comp(__first, __middle))
+      ++__first;
+    --__last;
+    while (__comp(__middle, __last))
+      --__last;
+    if (!(__first < __last))
+      return __first;
+    std::iter_swap(__first, __last);
+    ++__first;
+  }
+}
+
+// ... cut along line #eh4711 ...
+
+template<typename _MyAwesomeIterator>
+inline void
+__do_sort(_MyAwesomeIterator __first, _MyAwesomeIterator __last)
+{
+  for (_MyAwesomeIterator __i = __first + 1; __i != __last; ++__i)
+    if (__some::__ops::__do_foo()(__i, __first))
+      std::something(__first, __i, __i + 1);
+}
+
+template<typename _Tp>
+inline _Tp
+__what_what(_Tp __one, _Tp __two, _Tp __three)
+{
+  return foo(bar(__one, __two), __three);
+}
+
+}
+)";
+
+  std::string source;
+  source.reserve(size);
+
+  while (source.size() < size) {
+    source += corpus;
+  }
+
+  source.resize(size);
+  return source;
+}
+
+} // namespace
+
+#ifdef HAVE_AVX2
+static void
+BM_check_for_source_code_patterns_avx2(benchmark::State& state)
+{
+  const auto source = generate_source_code(state.range(0));
+  for (auto _ : state) {
+    auto result = check_for_source_code_patterns_avx2(source);
+    benchmark::DoNotOptimize(result);
+  }
+  state.SetBytesProcessed(state.iterations() * source.size());
+}
+#endif
+
+static void
+BM_check_for_source_code_patterns_scalar(benchmark::State& state)
+{
+  const auto source = generate_source_code(state.range(0));
+  for (auto _ : state) {
+    auto result = check_for_source_code_patterns_scalar(source);
+    benchmark::DoNotOptimize(result);
+  }
+  state.SetBytesProcessed(state.iterations() * source.size());
+}
+
+#ifdef HAVE_AVX2
+BENCHMARK(BM_check_for_source_code_patterns_avx2)
+  ->Arg(1000)
+  ->Arg(10000)
+  ->Arg(100000)
+  ->Arg(1000000);
+#endif
+
+BENCHMARK(BM_check_for_source_code_patterns_scalar)
+  ->Arg(1000)
+  ->Arg(10000)
+  ->Arg(100000)
+  ->Arg(1000000);
diff --git a/benchmark/main.cpp b/benchmark/main.cpp
new file mode 100644 (file)
index 0000000..335ea88
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright (C) 2026 Joel Rosdahl and other contributors
+//
+// See doc/authors.adoc for a complete list of contributors.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3 of the License, or (at your option)
+// any later version.
+//
+// This program is distributed in the hope that it will be useful, but WITHOUT
+// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the Free Software Foundation, Inc., 51
+// Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include <benchmark/benchmark.h>
+
+BENCHMARK_MAIN();
index c190cdcfd353eb6f010f5ec94108b930d96ddb53..9473190e669600b38793049c756f463c8555b9a6 100644 (file)
@@ -54,6 +54,8 @@ should be located or retrieved:
   HTTP_STORAGE_BACKEND=OFF`)
 - [doctest](https://github.com/doctest/doctest)[^2] (disable with `-D
   ENABLE_TESTING=OFF`)
+- [Google Benchmark](https://github.com/google/benchmark)[^2] (enable with `-D
+  ENABLE_BENCHMARKS=ON`)
 - [hiredis](https://github.com/redis/hiredis)[^2] (disable with `-D
   REDIS_STORAGE_BACKEND=OFF`)