uintptr_t转换为bool会多次降低SSO基准测试速度

丹尼尔·兰格

考虑以下实现小字符串优化基本上是为了MCVE的类)的类(假设有小端字节序,64位指针等):

class String {
   char* data_;
   bool sso() const { return reinterpret_cast<uintptr_t>(data_) & 1; }     
 public:
    String(const char * arg = "") {
       auto len = strlen(arg);
       if (len > 6) {
          data_ = new char[len + 1];
          memcpy(data_, arg, len + 1);
       } 
       else {
          data_ = reinterpret_cast<char*>((uintptr_t)1);
          memcpy(reinterpret_cast<char*>(&data_) + 1, arg, len + 1);
       }            
   }  
   ~String() { if (sso() == false) delete data_; }
// ~String() { if (reinterpret_cast<uintptr_t>(data_) & 1 == 0) delete data_; }
};

请注意,有两个版本的析构函数。当我使用Quick C ++ Benchmark测量这两个版本之间的差异时:

static void CreateShort(benchmark::State& state) {    
   for (auto _ : state) {    
      String s("hello");
      benchmark::DoNotOptimize(s); 
   }  
}

快5.7倍与GCC第二种情况下的运行时间。我不明白为什么编译器在这里不能生成相同的优化程序集。在按位AND运算的结果另外转换为bool的情况下,是什么阻碍了编译器的优化呢?(尽管我不是汇编专家,但我可以看到两种变体在汇编输出中的一些差异,但无法弄清楚为什么会有这种差异。)

使用Clang,没有区别,并且两种变体都很快。


问题在于转换为bool,而不是内联。以下形式的析构函数会导致相同的问题:

~String() { if ((bool)(reinterpret_cast<uintptr_t>(data_) & 1) == false) delete data_; }
MM

对于此代码:

if (reinterpret_cast<uintptr_t>(data_) & 1 == 0) delete data_;

可以完全优化它:1 == 0始终为0,并且x & 0对所有人始终为x第一种情况比较慢,因为它实际上在做某事。

我想你的意思是:

if ( (reinterpret_cast<uintptr_t>(data_) & 1) == 0) delete data_;

我优先使用的助记符& |是回想一下,在C的前体中,没有单独的运算符&&&;。&运营商满足这两个角色(你手动转换为布尔值范围内,如果你想要一个合乎逻辑的比较)。x == y & z == w检查这两个等式是否成立的普通代码也是如此

&&引入时,为了避免破坏现有代码,&&给它的优先级比&;&保持不变==

C ++语言也没有改变这些优先顺序,大概是为了最大程度地减小两种语言之间的不兼容性。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将 QString 转换为 uintptr_t, Qt / C++

在将指针转换为uintptr_t之前需要转换为void *吗?反之亦然?

从size_t或uintptr_t来回转换指针是否会破坏严格的别名?

将非`void`指针转换为`uintptr_t`,反之亦然

如何将 std::stringstream 转换为 uintptr_t 并保持十六进制值?

C-为什么在执行指针算术时强制转换为uintptr_t vs char *

将 char[] 变量转换为 uintptr_t 变量 C++

函数的地址转换为UINTPTR_T给我错误的结果

在编译时将函数指针转换为std :: uintptr_t

将指针转换为数值以进行哈希处理-我应该使用`uintptr_t`还是`intptr_t`吗?

size_t与uintptr_t

释放 uintptr_t 指向的内存

字符数组和uintptr_t

什么是uintptr_t数据类型

将 OpenCV 程序转换为模块会大大降低帧率

多次调用一个函数会降低程序速度吗?

为什么sizeof(ptrdiff_t)== sizeof(uintptr_t)

C语言中的uintptr_t和intptr_t

了解针对intptr_t和uintptr_t的void *

将strtoull()的输出转换为double值然后返回uint64_t时,其精度会降低

uintptr_t是否存储指针的地址或其值?

uintptr_t和DWORD_PTR的用法

获取变量的十六进制地址为 uintptr_t

sizeof(void*) != sizeof(uintptr_t) 在实践中?

三个问题:是否定义了NULL?是否定义了(uintptr_t)NULL-(uintptr_t)NULL?

ToneGenerator会严重降低应用速度

注释会降低解释语言的速度吗?

多个开关会降低传输速度吗

Adblock会降低Firefox的速度吗?