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

为何为不会抛出异常的函数添加noexcept会降低性能?

为何添加noexcept会降低无异常函数的性能?

问题背景

原本预期给绝不会抛出异常的函数添加noexcept关键字不会产生性能负面影响,就像const关键字一样,但测试中发现给isVowel函数添加noexcept后,性能反而出现了下降。

测试场景

先生成标记元音字符的std::array<bool,256>映射表,再通过isVowel函数查询字符是否为元音,对比有无noexcept修饰的两个版本的性能差异。

简化示例代码

#include <array>
#include <limits>

static constexpr unsigned char vowels[]{ 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };

auto constexpr genVowelTestMap() {
  std::array<bool, std::numeric_limits<256> m{};
  for (const unsigned char& c : vowels) { 
    m[c] = true;
  }
  return m;
}
static constexpr auto vowelTestMap = genVowelTestMap();

bool isVowel(const char c)noexcept/*The relevant noexcept*/{
  return vowelTestMap[c];
}

完整测试代码

#include <array>
#include <limits>
#include <string>
#include <cassert>
#include <chrono>
#include <iostream>

static constexpr unsigned char vowels[]{ 'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U' };

auto constexpr genVowelTestMap() {
  std::array<bool, 256> m{}; static_assert(sizeof(char) == 1);
  for (const unsigned char& c : vowels) { 
    m[c] = true;
  }
  return m;
}
static constexpr auto vowelTestMap = genVowelTestMap();

inline bool isVowel(const char c){
  return vowelTestMap[c];
}
inline bool isVowelNoExcept(const char c)noexcept{
  return vowelTestMap[c];
}

std::string genRandomLetterString(size_t size) {
  std::string s(size, '\0');
  //24 + 24 options = 48 options.
  for (size_t i = 0; i < size; i++) {
    char& c = s[i];
    c = std::rand() % 48;
    if (c < 24) c += 'a';
    else c += 'a' - 24;
    assert(isalpha(c));
  }
  return s;
}

template<bool USE_NO_EXCEPT>
void runTest() {
  const int runs = 1000;
  auto start = std::chrono::high_resolution_clock::now();
  const std::string s = genRandomLetterString(1u << 20);

  size_t a = 0;
  for (int i = 0; i < runs; i++) {
    for (const char& c : s) {
      if constexpr (USE_NO_EXCEPT) {
        if (isVowelNoExcept(c))a++;
      }
      else {
        if (isVowel(c))a++;
      }
    }
  }

  auto end = std::chrono::high_resolution_clock::now();
  auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start).count();
  std::cout << (USE_NO_EXCEPT?"NOEXCEPT":"\t") << "\tr(" << (a/runs) << ")Time taken : " << duration << " microseconds." << std::endl;
}

int main() {
  for (int j = 0; j < 10; j++) {
    runTest<true>();
    runTest<false>();
  }
}

测试结果

使用MSVC编译器(C++20、x64、/O2、/Ob2、/Oi、/GL)编译时,noexcept版本性能比普通版本低约20%;切换至/O3优化等级后,两者性能一致。多次测试数据如下:

Time taken : noexcept version : normal version.
Time taken : 814786 microseconds:645568 microseconds. //The first is always slowest. Should prob be ignored.
Time taken : 675711 microseconds:612367 microseconds. //Run order was noexcept, normal and then repeat.
Time taken : 685613 microseconds:605072 microseconds.
Time taken : 655509 microseconds:607108 microseconds.
Time taken : 756300 microseconds:623599 microseconds.
Time taken : 718311 microseconds:605397 microseconds.
Time taken : 672052 microseconds:615306 microseconds.
Time taken : 703469 microseconds:608384 microseconds.
Time taken : 668540 microseconds:604204 microseconds.
Time taken : 667859 microseconds:605363 microseconds.

此外,对比两个版本的汇编代码,未发现明显差异。

核心疑问

为何noexcept会降低绝不会抛出异常的函数的性能?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 11:55:56