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

如何通过LD_PRELOAD统一为C++进程启用gperftools CPU分析,排除Python进程?

问题

我想通过设置LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so.0 CPUPROFILE=/tmp/myprofile.out,用gperftools做CPU分析。这个配置在纯C++环境下正常,但在Python环境里会生成空文件。

我的环境调用链受约束无法修改:

  • executor program → python program → C++ subprocess
  • 或 executor program → C++ program

所有程序都通过executor program调用subprocess.Popen启动,没法区分要执行的是Python还是C程序。更糟的是,Python程序会生成自己的C子进程并传递环境变量,导致Python和C++进程往同一个位置写分析文件,可能因为竞争导致文件为空。

我试过在Python主函数里取消设置相关环境变量,但Python还是会生成分析文件。想请教有没有办法通过LD_PRELOAD和CPUPROFILE统一给所有C++进程启用CPU分析,但排除Python进程?

解决方案

方法1:用自定义Shell脚本区分进程类型

写一个简单的Shell脚本作为启动入口,替换掉executor program里直接调用目标程序的逻辑:

#!/bin/bash
TARGET="$1"
shift

# 判断目标程序是否为Python(匹配python/python3等名称)
if [[ "$TARGET" == *python* ]]; then
    # 清除gperftools相关环境变量后启动Python
    unset LD_PRELOAD CPUPROFILE
    exec "$TARGET" "$@"
else
    # 保留环境变量,直接启动C++程序
    exec "$TARGET" "$@"
fi

修改executor program中的subprocess.Popen调用,把原目标程序路径作为第一个参数传给这个脚本,后续参数保持不变。这样Python进程启动时会自动清除环境变量,不会生成分析文件,C++进程则正常启用profiler。

方法2:自定义过滤版preload库

如果无法修改启动脚本,可以写一个轻量的包装库,代替直接加载libprofiler.so.0,让它自动跳过Python进程:

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

static const char* get_proc_name() {
    static char buf[1024];
    ssize_t len = readlink("/proc/self/exe", buf, sizeof(buf)-1);
    if (len != -1) {
        buf[len] = '\0';
        char* last_slash = strrchr(buf, '/');
        return last_slash ? last_slash + 1 : buf;
    }
    return NULL;
}

__attribute__((constructor))
void init_profiler() {
    const char* name = get_proc_name();
    // 匹配Python进程名,直接返回不加载profiler
    if (name && (!strcmp(name, "python") || !strcmp(name, "python3"))) {
        return;
    }
    // 加载真正的gperftools profiler库
    void* lib = dlopen("/usr/lib/x86_64-linux-gnu/libprofiler.so.0", RTLD_NOW | RTLD_GLOBAL);
    if (!lib) {
        fprintf(stderr, "Failed to load libprofiler: %s\n", dlerror());
    }
}

编译这个库:

gcc -shared -fPIC -o libprofiler_filter.so profiler_filter.c -ldl

然后把LD_PRELOAD设置为这个自定义库的路径:export LD_PRELOAD=/path/to/libprofiler_filter.so。Python进程加载该库后会直接跳过profiler初始化,C++进程则正常启用分析。

方法3:给CPUPROFILE添加进程ID避免竞争

如果只是想解决多进程写同一个文件导致的空文件问题,可以把CPUPROFILE设置为包含进程ID的专属路径:

export CPUPROFILE="/tmp/myprofile_$$.out"

或者在executor program启动进程时,动态给每个进程分配唯一的CPUPROFILE路径(比如包含子进程PID)。这个方法不能排除Python进程,但能避免文件竞争导致的空文件问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 02:16:09