You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++异常与值返回错误处理性能基准测试及疑问

C++错误处理方式性能基准测试与疑问

测试方案

针对两种C++错误处理方式的性能差异开展基准测试:

  • 值返回(错误汇总):使用std::variant适配C++17标准,未采用std::expected
  • 抛出异常

测试场景为大型整数数组求和,设计了err_a和err_b两种错误类型,完整测试代码如下:

#include <benchmark/benchmark.h>

#include <random>

#include <variant>
#include <vector>

namespace {

constexpr int k_err_a_value = 8;
constexpr int k_err_b_value = 15;

struct err_a {};
struct err_b {};

[[maybe_unused]] std::variant<int, err_a, err_b>
sum_raw(const std::vector<int> &v) {
  for (const auto &i : v) {
    if (k_err_a_value == i)
      return {err_a{}};
  }

  for (const auto &i : v) {
    if (k_err_b_value == i)
      return {err_b{}};
  }

  int sum = 0;
  for (int i: v)
    sum += i;

  return {sum};
}

[[maybe_unused]] int sum_exceptions(const std::vector<int> &v) {
  for (const auto &i : v) {
    if (k_err_a_value == i)
      throw err_a{};
  }

  for (const auto &i : v) {
    if (k_err_b_value == i)
      throw err_b{};
  }

  int sum = 0;
  for (int i: v)
    sum += i;

  return sum;
}

std::vector<int> generate(const size_t n, const double err_perc,
                          bool use_err_b) {
  std::mt19937 gen32;
  std::uniform_int_distribution<decltype(gen32)::result_type> dist{};
  std::vector<int> generated;
  generated.reserve(n);

  for (size_t i = 0; i < n; ++i) {
    auto g = dist(gen32);
    while (k_err_a_value == g || k_err_b_value == g)
      g = dist(gen32);
    generated.emplace_back(g);
  }

  if (err_perc <= 100.0)
    generated[n / 100.0 * err_perc] = use_err_b ? k_err_b_value : k_err_a_value;

  return generated;
}

class bm_sum : public ::benchmark::Fixture {
public:
  void SetUp(benchmark::State &state) override {
    const size_t elems = state.range(0);
    const double err_perc = state.range(1);
    const bool use_err_b = state.range(2);

    _generated = generate(elems, err_perc, use_err_b);
  }

  const std::vector<int> &generated() const { return _generated; }

  constexpr static int
  from_variant(std::variant<int, err_a, err_b> v) noexcept {
    return std::visit([](auto i) {
        if constexpr (std::is_same_v<decltype(i), int>)
            return i;
        else
            return 0;
    }, std::move(v));
  }

private:
  std::vector<int> _generated;
};

BENCHMARK_DEFINE_F(bm_sum, raw)(benchmark::State &state) {
  for (auto _ : state) {
    benchmark::DoNotOptimize(from_variant(sum_raw(generated())));
    benchmark::ClobberMemory();
  }
}

BENCHMARK_DEFINE_F(bm_sum, exceptions)(benchmark::State &state) {
  for (auto _ : state) {
    benchmark::DoNotOptimize([&] {
      try {
        return sum_exceptions(generated());
      } catch (...) {
        return 0;
      }
    }());
    benchmark::ClobberMemory();
  }
}

// todo: how not to repeat?
BENCHMARK_REGISTER_F(bm_sum, raw)
    ->ArgsProduct({benchmark::CreateRange(1'000, 10'000'000, 10),
                   {101, 80}, // perc of range where to put error
                   {0, 1}});  // which error to put
BENCHMARK_REGISTER_F(bm_sum, exceptions)
    ->ArgsProduct({benchmark::CreateRange(1'000, 10'000'000, 10),
                   {101, 80}, // perc of range where to put error
                   {0, 1}});  // which error to put

} // namespace

BENCHMARK_MAIN();

测试环境与结果

测试环境为g++ 11.4.0,得到以下结果:

  • 无异常抛出场景(参数101):两种错误处理方式性能几乎一致
  • 在处理80%输入时抛出异常场景:小数据集下异常方式比值返回方式慢2-3倍;但大数据集下,异常方式的性能反而更优

技术疑问

  1. 上述观察到的性能现象是否合理?
  2. 如何构造极简示例来展示异常处理的实际性能劣势?

注:这类带实际代码和性能数据的测试,对参与“异常优劣论战”的开发者有参考价值。

内容的提问来源于stack exchange,提问作者Sergey Kolesnik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:15:21