C中的一个好奇的字符串复制函数

Gha*_*uni 9 c optimization nginx memcpy

当我阅读nginx代码时,我看到了这个函数:

#define ngx_cpymem(dst, src, n)   (((u_char *) memcpy(dst, src, n)) + (n))

static ngx_inline u_char *
ngx_copy(u_char *dst, u_char *src, size_t len)
{
    if (len < 17) {

        while (len) {
            *dst++ = *src++;
            len--;
        }

        return dst;

    } else {
        return ngx_cpymem(dst, src, len);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个简单的字符串复制功能.但是为什么它测试字符串的长度并在长度> = 17时切换到memcpy?

osg*_*sgx 12

这是一个优化 - 对于非常小的字符串,简单复制比调用系统(libc)复制功能更快.

while循环的简单复制对于短字符串工作相当快,系统复制功能(通常)对长字符串进行优化.但是系统复制还会进行大量检查和一些设置.

实际上,在此代码之前有作者的评论:nginx,/ src/core/ngx_string.h(search ngx_copy)

/*
 * the simple inline cycle copies the variable length strings up to 16
 * bytes faster than icc8 autodetecting _intel_fast_memcpy()
 */
Run Code Online (Sandbox Code Playgroud)

另外,两行鞋面是

#if ( __INTEL_COMPILER >= 800 )
Run Code Online (Sandbox Code Playgroud)

因此,作者进行了测量并得出结论,ICC优化的memcopy执行长CPU检查以选择最优化的memcopy变体.他发现手动复制16个字节比ICC最快的memcpy代码快.

对于其他编译器,nginx ngx_cpymem 直接使用(memcpy)

#define ngx_copy                  ngx_cpymem
Run Code Online (Sandbox Code Playgroud)

作者memcpy对不同尺寸的不同s进行了研究:

/*
 * gcc3, msvc, and icc7 compile memcpy() to the inline "rep movs".
 * gcc3 compiles memcpy(d, s, 4) to the inline "mov"es.
 * icc8 compile memcpy(d, s, 4) to the inline "mov"es or XMM moves.
 */
Run Code Online (Sandbox Code Playgroud)

  • 大概.我想这就是意图,程序员可能会在他们的环境中描述它,但是它总是更快,很难说. (2认同)