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

kzalloc()/kmem_cache_zalloc()相对kmalloc()+memset的性能优势探究

问题

除了写法更简洁之外,使用kzalloc()/kmem_cache_zalloc()相比kmalloc()/kmem_cache_alloc()搭配memset()是否还有其他优势?尤其是性能层面?我自己做了性能测试,但二者结果几乎一致。

内核版本:4.18.0-372.19.1.el8_6.x86_64

测试代码用于创建200万个4096字节的slab对象:

#define DATA_NUMBER    2000000
char *data[DATA_NUMBER];

/* kthread */
static int zero_slab(void *arg)
{
        unsigned int            counter, i;
        struct kmem_cache       *mp_cache;
        unsigned long           before, after;

        mp_cache = kmem_cache_create("MP_CACHE", PAGE_SIZE, 0, 0, NULL);
        if (!mp_cache) {
                printk(KERN_INFO "Failed to create slab.\n");
                return -ENOMEM;
        }
        printk(KERN_INFO "Slab MP_CACHE is created.\n");

        before = ktime_get();
        for (counter = 0; counter < DATA_NUMBER; counter++) {
                // data[counter] = kmem_cache_zalloc(mp_cache, GFP_KERNEL);
                data[counter] = kmem_cache_alloc(mp_cache, GFP_KERNEL);
                if (!data[counter])
                        goto err_out;
                memset(data[counter], 0, PAGE_SIZE);
        }
        after = ktime_get() - before;
        printk(KERN_INFO "Time taken in ns (%lu)\n", after);

err_out:
        printk(KERN_INFO "Total objects : %u\n", counter);
        for (i = 0; i < counter; ++i)
                kmem_cache_free(mp_cache, data[i]);
        kmem_cache_destroy(mp_cache);
        return 0;
}
回答

核心优势总结

  • 内存安全保障:kzalloc/kmem_cache_zalloc是内核原生的零初始化接口,能避免手动调用memset可能出现的疏漏——比如分配成功后、memset执行前就误用脏内存,或是memset的长度参数写错导致部分内存未清零,这类问题极易引发诡异的内存访问bug,且排查难度极大。
  • 性能的场景化优势:
    • 当分配的是伙伴系统刚拿出的全新物理页时,内核已经完成了清零操作,kzalloc这类接口会直接复用这个干净状态,跳过冗余的memset;而手动调用memset不管内存原本状态都会执行清零,这种场景下kzalloc的效率明显更高。
    • 部分架构的内核实现中,kmem_cache_zalloc会结合slab缓存的批量处理逻辑完成清零,比单独调用memset的单对象清零更高效,尤其是批量分配大量对象时。
  • 代码可读性与维护性:原生零初始化接口的意图更明确,看到kzalloc就能立刻知道是要获取零初始化的内存,无需额外检查后续代码是否有memset操作,降低了代码阅读和维护的成本。

测试结果一致的原因分析

你的测试用例中,slab对象大小为PAGE_SIZE,且分配后会被释放回缓存,再次分配时内存处于非清零状态。这种场景下,kmem_cache_zalloc和kmem_cache_alloc+memset都需要执行清零操作,因此性能表现几乎无差异。如果换用全新物理页的分配场景(比如第一次批量分配大量对象,或是给slab缓存添加SLAB_POISON标志让释放的对象被标记为脏数据),就能看到两者的性能差距。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 03:33:27