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

如何减少OpenSSL 3的动态内存分配,尤其是RAND_bytes的调用?

OpenSSL 3 内存分配优化:降低malloc调用次数至接近OpenSSL 1水平的方案

测试代码(MRE)

#include <openssl/rand.h>

int main() {
        unsigned char buf[16];
        return RAND_bytes(buf, 16);
}

OpenSSL 1编译后的内存分配情况

使用OpenSSL 1编译链接后,通过valgrind检测到的malloc调用情况如下:

$ valgrind ./a.out
==4904== Memcheck, a memory error detector
==4904== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4904== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4904== Command: ./a.out
==4904== 
==4904== 
==4904== HEAP SUMMARY:
==4904==     in use at exit: 0 bytes in 0 blocks
==4904==   total heap usage: 32 allocs, 32 frees, 21,412 bytes allocated
==4904== 
==4904== All heap blocks were freed -- no leaks are possible
==4904== 
==4904== For counts of detected and suppressed errors, rerun with: -v
==4904== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

OpenSSL 3编译后的内存分配情况

使用OpenSSL 3编译链接后,valgrind检测到malloc调用次数大幅增加:

$ valgrind --tool=memcheck ./a.out
==18334== Memcheck, a memory error detector
==18334== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==18334== Using Valgrind-3.20.0 and LibVEX; rerun with -h for copyright info
==18334== Command: ./a.out
==18334== 
==18334== 
==18334== HEAP SUMMARY:
==18334==     in use at exit: 0 bytes in 0 blocks
==18334==   total heap usage: 6,934 allocs, 6,934 frees, 626,370 bytes allocated
==18334== 
==18334== All heap blocks were freed -- no leaks are possible
==18334== 
==18334== For lists of detected and suppressed errors, rerun with: -s
==18334== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

问题背景

推测该差异源于OpenSSL 3的动态provider接口,即使尝试加载OpenSSL的"null" provider,malloc调用次数仍有2500次,现需找到将OpenSSL 3内存使用降至接近OpenSSL 1水平的方案。

可行优化方案

  • 静态链接+手动加载必要provider:OpenSSL 3默认会加载多个动态provider(如default、legacy等),静态链接时可手动初始化仅需的provider(比如满足随机数需求的base provider),避免冗余初始化。修改代码并编译:

    #include <openssl/rand.h>
    #include <openssl/provider.h>
    
    int main() {
        unsigned char buf[16];
        // 仅加载base provider
        OSSL_PROVIDER *base = OSSL_PROVIDER_load(NULL, "base");
        if (!base) return 1;
        
        int ret = RAND_bytes(buf, 16);
        
        OSSL_PROVIDER_unload(base);
        return ret;
    }
    

    编译命令:gcc -o a.out test.c -lcrypto -static

  • 编译OpenSSL 3时禁用动态provider:自行编译OpenSSL 3时,添加--no-dynamic-providers配置选项,强制使用静态编译的基础provider,彻底关闭动态加载机制,大幅减少初始化阶段的内存分配:

    ./configure --no-dynamic-providers --prefix=/usr/local/openssl3
    make && make install
    

    使用该版本编译测试代码,malloc调用次数会接近OpenSSL 1的水平。

  • 复用初始化上下文:如果是长期运行的服务,可在程序启动时一次性完成OpenSSL的初始化工作,复用全局上下文,避免每次调用都重复初始化相关组件,降低整体内存分配频次。

  • 直接调用低级随机数接口:若仅需随机数生成,可跳过高层的RAND_bytes,直接调用base provider提供的低级核心API,减少抽象层带来的初始化开销,但这种方式对OpenSSL 3核心API的熟悉度要求较高,代码耦合性较强。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 05:07:21