Ubuntu 下 nginx-1.24.0 源码分析 - ngx_crc32_table_init 函数

 ngx_crc32_table_init

声明在 src/core/ngx_crc32.h 

ngx_int_t ngx_crc32_table_init(void);

实现在 src/core/ngx_crc32.c

ngx_int_t
ngx_crc32_table_init(void)
{
    void  *p;

    if (((uintptr_t) ngx_crc32_table_short
          & ~((uintptr_t) ngx_cacheline_size - 1))
        == (uintptr_t) ngx_crc32_table_short)
    {
        return NGX_OK;
    }

    p = ngx_alloc(16 * sizeof(uint32_t) + ngx_cacheline_size, ngx_cycle->log);
    if (p == NULL) {
        return NGX_ERROR;
    }

    p = ngx_align_ptr(p, ngx_cacheline_size);

    ngx_memcpy(p, ngx_crc32_table16, 16 * sizeof(uint32_t));

    ngx_crc32_table_short = p;

    return NGX_OK;
}

解析 

在 Nginx 的源码中,ngx_crc32_table_init 函数是一个非常重要的初始化函数,用于优化 CRC32 校验算法的性能


背景知识:CRC32 校验与查表法

CRC32(循环冗余校验)是一种广泛使用的校验算法,主要用于检测数据传输或存储中的错误。

Nginx 使用了两种查表法来加速 CRC32 的计算:

  1. 小表(16 元素) :占用 64 字节,适合短数据的快速计算。
  2. 大表(256 元素) :占用 1024 字节,适合长数据的高效处理。

为了进一步优化性能,Nginx 将小表对齐到 CPU 缓存行大小(ngx_cacheline_size),以减少缓存未命中带来的性能损失。

这就是 ngx_crc32_table_init 函数的核心任务。


函数原型

ngx_int_t ngx_crc32_table_init(void);
  • 作用:初始化 CRC32 短表,确保其内存对齐到 CPU 缓存行

  • 返回值

    • NGX_OK:初始化成功或无需初始化

    • NGX_ERROR:内存分配失败


缓存行对齐检查

if (((uintptr_t) ngx_crc32_table_short
      & ~((uintptr_t) ngx_cacheline_size - 1))
    == (uintptr_t) ngx_crc32_table_short)
{
    return NGX_OK;
}

首先检查全局变量 ngx_crc32_table_short 是否已经对齐到 CPU 缓存行边界

  • ngx_crc32_table_short 是一个指向小表(16 元素)的指针。
  • (uintptr_t) ngx_crc32_table_short 将指针转换为整数,方便进行位运算。
  • ~((uintptr_t) ngx_cacheline_size - 1) 计算出一个掩码,用于提取对齐地址的高位部分。
  • 如果 ngx_crc32_table_short 已经对齐,则直接返回 NGX_OK,无需额外操作

分配内存 

    p = ngx_alloc(16 * sizeof(uint32_t) + ngx_cacheline_size, ngx_cycle->log);
    if (p == NULL) {
        return NGX_ERROR;
    }

如果小表未对齐,则需要重新分配一块足够大的内存

ngx_alloc 是 Nginx 提供的内存分配函数,类似于 malloc

分配的内存大小为 16 * sizeof(uint32_t) + ngx_cacheline_size,即小表的实际大小加上缓存行大小

如果分配失败(返回 NULL),则返回 NGX_ERROR

空间计算

数据部分:16 个 uint32_t → 64 字节(短表大小)

对齐余量+ ngx_cacheline_size 确保即使原始指针未对齐,调整后仍有足够空间


内存对齐调整 
    p = ngx_align_ptr(p, ngx_cacheline_size);

将分配的内存指针对齐到缓存行边界


 数据迁移
    ngx_memcpy(p, ngx_crc32_table16, 16 * sizeof(uint32_t));

将原始的小表数据(ngx_crc32_table16)复制到对齐后的内存区域


更新全局变量 

    ngx_crc32_table_short = p;

将全局变量 ngx_crc32_table_short 更新为对齐后的指针


 返回成功状态

    return NGX_OK;
}

初始化完成,返回 NGX_OK 表示成功

你可能感兴趣的:(nginx,运维)