Bazel工程化集成google/benchmark 这是一个开源实践
使用 Bazel 集成 Google Benchmark 到你的项目中:
1. 添加依赖 在项目根目录下的WORKSPACE
文件里添加 Google Benchmark 的依赖。你可以通过http_archive
规则从 GitHub 下载源码。示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 workspace(name = "fury" ) load("//bazel:fury_deps_setup.bzl" , "setup_deps" ) setup_deps() load("@bazel_skylib//:workspace.bzl" , "bazel_skylib_workspace" ) load("@com_github_grpc_grpc//bazel:grpc_deps.bzl" , "grpc_deps" ) load("@com_github_grpc_grpc//third_party/py:python_configure.bzl" , "python_configure" ) load("//bazel/arrow:pyarrow_configure.bzl" , "pyarrow_configure" ) load("@bazel_tools//tools/build_defs/repo:git.bzl" , "git_repository" ) git_repository( name = "com_google_benchmark" , remote = "https://github.com/google/benchmark.git" , tag = "v1.9.1" , ) bazel_skylib_workspace() python_configure(name="local_config_python" ) pyarrow_configure(name="local_config_pyarrow" ) grpc_deps()
上述代码从 GitHub 下载了 Google Benchmark 1.8.3 版本和 Google Test 1.13.0 版本。可根据需求调整版本号。
2. 创建 BUILD 文件 在包含基准测试代码的目录下创建BUILD
文件,以定义构建规则。以下是一个示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 load("@rules_cc//cc:defs.bzl" , "cc_library" , "cc_test" ) cc_library( name = "fury_benchmark" , srcs = glob(["*.cc" ], exclude=["benchmark*.cc" ]), hdrs = glob(["*.h" ]), strip_include_prefix = "/cpp" , alwayslink = True , linkstatic = True , deps = [ "//cpp/fury/util:fury_util" , "@com_google_benchmark//:benchmark" , ], visibility = ["//visibility:public" ], ) cc_test( name = "benchmark_string_util" , srcs = ["benchmark_string_util.cc" ], deps = [ ":fury_benchmark" , ], )
cc_binary
规则用于构建可执行的基准测试程序。
benchmark
规则是 Google Benchmark 提供的,用于运行基准测试并展示结果。
3. 编写基准测试代码 在benchmark_string_util.cc
文件中编写基准测试代码,示例如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 const size_t num_tests = 1000 ;const size_t string_length = 1000 ;std ::vector <std ::string > generateAsciiString(size_t num_tests, size_t string_length) { std ::vector <std ::string > test_strings; for (size_t i = 0 ; i < string_length; ++i) { test_strings.push_back(generateUtf8(num_tests)); } return test_strings; } const std ::vector <std ::string > test_ascii_strings = generateAsciiString(num_tests, string_length); std ::vector <std ::u16string> generateLatin1String(size_t num_tests, size_t string_length) { std ::vector <std ::u16string> test_strings; for (size_t i = 0 ; i < num_tests; ++i) { test_strings.push_back(generateLatin1(string_length)); } return test_strings; } const std ::vector <std ::u16string> test_latin1_strings = generateLatin1String(num_tests, string_length); std ::vector <std ::u16string> generateUTF16String(size_t num_tests, size_t string_length) { std ::vector <std ::u16string> test_strings; for (size_t i = 0 ; i < string_length; ++i) { test_strings.push_back(generateUtf16(num_tests)); } return test_strings; } const std ::vector <std ::u16string> test_utf16_strings = generateUTF16String(num_tests, string_length); std ::vector <std ::string > generateUTF8String(size_t num_tests, size_t string_length) { std ::vector <std ::string > test_strings; for (size_t i = 0 ; i < string_length; ++i) { test_strings.push_back(generateUtf8(num_tests)); } return test_strings; } const std ::vector <std ::string > test_utf8_strings = generateUTF8String(num_tests, string_length); bool isAscii_BaseLine (const std ::string &str) { for (char c : str) { if (static_cast <uint8_t >(c) > 0x7F ) { return false ; } } return true ; } static void BM_IsAscii_BaseLine (benchmark::State &state) { for (auto _ : state) { for (const auto &str : test_ascii_strings) { bool result = isAscii_BaseLine(str); benchmark::DoNotOptimize(result); } } } static void BM_IsAscii_SIMD (benchmark::State &state) { for (auto _ : state) { for (const auto &str : test_ascii_strings) { bool result = fury::isAscii(str); benchmark::DoNotOptimize(result); } } } BENCHMARK(BM_IsAscii_BaseLine); BENCHMARK(BM_IsAscii_SIMD); BENCHMARK(BM_Utf8ToUtf16_StandardLibrary); BENCHMARK(BM_Utf8ToUtf16_BaseLine); BENCHMARK(BM_Utf8ToUtf16_SIMD); BENCHMARK_MAIN();
引入benchmark/benchmark.h
头文件。
定义BM_EmptyLoop
函数,该函数接受benchmark::State& state
参数,函数内部是一个空循环。
利用BENCHMARK(BM_EmptyLoop)
注册基准测试函数。
BENCHMARK_MAIN()
宏定义程序入口点。
4. 构建并运行基准测试 在项目根目录下使用以下命令构建并运行基准测试:
1 2 3 4 5 bazel build //cpp/fury/benchmark:all bazel test //cpp/fury/benchmark:all bazel run //cpp/fury/benchmark:benchmark_string_util
运行命令后,Bazel 会构建基准测试程序并执行,最后输出基准测试结果。