使用jemalloc实现信号驱动的程序堆栈信息打印

使用jemalloc实现信号驱动的程序堆栈信息打印

本文介绍应用如何集成jemalloc,在接收到SIGUSR1信号10时打印程序的堆栈信息。

1. 编译jemalloc

首先,确保你已经编译并安装了启用prof功能的jemalloc。以下是ubuntu18.04上的编译步骤:

git clone https://github.com/jemalloc/jemalloc.git  # 本文测试的版本是jemalloc-5.3.0
cd jemalloc
./configure --prefix=/usr/local --enable-prof
make -j10
make install

2. 测试

假如你的需要集成的程序为example,通过LD_PRELOAD同时加载jemalloc和钩子库,按照以下步骤运行和测试:

  • 设置环境变量:

    export MALLOC_CONF="prof:true,prof_active:true,lg_prof_sample:0,tcache:false,prof_prefix:jeprof.out"
    
    • prof:true 启用配置文件
    • prof_active:true 启用性能分析
    • lg_prof_sample:0 设置采样率为最频繁
    • tcache:false:禁用线程缓存(Thread Cache)。
      • 禁用线程缓存可能会影响性能,但在进行性能分析时,可以提供更准确的内存分配数据。
    • prof_prefix:jeprof.out 指定性能分析输出文件前缀
  • 使用killall -10 example发送SIGUSR1信号以触发堆栈信息打印:

    killall -10 example # 或者 killall -SIGUSR1 example
    
  • 通过以上步骤,你可以在接收到SIGUSR1信号时打印jemalloc的堆栈信息,并将其输出到本地目录。

    本文得到的堆栈信息文件名为jeprof.out.60571.0.m0.heap ,通过如下命令分析该堆栈信息文件:

    jeprof --show_bytes --text --lines ./example ./jeprof.out.60571.0.m0.heap
    
  • 解析的结果为:

    $ jeprof --show_bytes --text --lines ./example ./jeprof.out.60571.0.m0.heap 
    Using local file ./example.
    Using local file ./jeprof.out.60571.0.m0.heap.
    Total: 83512 B
       83512 100.0% 100.0%    83512 100.0% prof_backtrace_impl /home/test/jemalloc-5.3.0/src/prof_sys.c:103
           0   0.0% 100.0%     1024   1.2% _IO_new_file_overflow /build/glibc-2ORdQG/glibc-2.27/libio/fileops.c:759
           0   0.0% 100.0%     1024   1.2% _IO_new_file_xsputn /build/glibc-2ORdQG/glibc-2.27/libio/fileops.c:1266
           0   0.0% 100.0%     1024   1.2% __GI__IO_doallocbuf /build/glibc-2ORdQG/glibc-2.27/libio/genops.c:365
           0   0.0% 100.0%     1024   1.2% __GI__IO_file_doallocate /build/glibc-2ORdQG/glibc-2.27/libio/filedoalloc.c:101
           0   0.0% 100.0%     1024   1.2% __GI__IO_fwrite /build/glibc-2ORdQG/glibc-2.27/libio/iofwrite.c:39
           0   0.0% 100.0%     1592   1.9% __libc_start_main /build/glibc-2ORdQG/glibc-2.27/csu/../csu/libc-start.c:310
           0   0.0% 100.0%    81920  98.1% _dl_start_user :?
           0   0.0% 100.0%     1592   1.9% _start ??:?
           0   0.0% 100.0%        8   0.0% allocateDouble /home/test/jemalloc_test/example.cpp:19
           0   0.0% 100.0%       80   0.1% allocateDynamicArray /home/test/jemalloc_test/example.cpp:32 (discriminator 1)
           0   0.0% 100.0%      448   0.5% allocateIntArray /home/test/jemalloc_test/example.cpp:13
           0   0.0% 100.0%     1024   1.2% allocateIntArray /home/test/jemalloc_test/example.cpp:14
           0   0.0% 100.0%     1472   1.8% allocateMemory /home/test/jemalloc_test/example.cpp:51
           0   0.0% 100.0%        8   0.0% allocateMemory /home/test/jemalloc_test/example.cpp:52
           0   0.0% 100.0%       32   0.0% allocateMemory /home/test/jemalloc_test/example.cpp:53
           0   0.0% 100.0%       80   0.1% allocateMemory /home/test/jemalloc_test/example.cpp:54
           0   0.0% 100.0%       32   0.0% allocateString /home/test/jemalloc_test/example.cpp:25
           0   0.0% 100.0%    81920  98.1% call_init /build/glibc-2ORdQG/glibc-2.27/elf/dl-init.c:72
           0   0.0% 100.0%    83512 100.0% imalloc (inline) /home/test/jemalloc-5.3.0/src/jemalloc.c:2694
           0   0.0% 100.0%    83512 100.0% imalloc_body (inline) /home/test/jemalloc-5.3.0/src/jemalloc.c:2550
           0   0.0% 100.0%    83512 100.0% je_malloc_default /home/test/jemalloc-5.3.0/src/jemalloc.c:2722
           0   0.0% 100.0%    83512 100.0% je_prof_backtrace /home/test/jemalloc-5.3.0/src/prof_sys.c:284
           0   0.0% 100.0%    83512 100.0% je_prof_tctx_create /home/test/jemalloc-5.3.0/src/prof.c:195
           0   0.0% 100.0%     1592   1.9% main /home/test/jemalloc_test/example.cpp:73
           0   0.0% 100.0%    83512 100.0% prof_alloc_prep (inline) /home/test/jemalloc-5.3.0/include/jemalloc/internal/prof_inlines.h:141
           0   0.0% 100.0%    81920  98.1% std::__once_callable ??:0
           0   0.0% 100.0%     1024   1.2% std::__ostream_insert ??:?
           0   0.0% 100.0%     1024   1.2% std::operator<<  ??:?
           0   0.0% 100.0%      568   0.7% void* fallback_impl /home/test/jemalloc-5.3.0/src/jemalloc_cpp.cpp:98
    
    

3. 本人测试的example.cpp代码

以下是完整的example.cpp代码,编译方法: g++ -g -o example example.cpp

// g++ -g -o example example.cpp
#include <jemalloc/jemalloc.h>  // jemalloc
#include <sys/mman.h>           // mmap, munmap
#include <unistd.h>             // usleep
#include <csignal>              // signal, sigaction
#include <cstdlib>              // rand()和srand()
#include <ctime>                // time()
#include <iostream>
#include <string>
#include <vector>

// 分配int数组
void allocateIntArray() {
  const int* intPtr = new int[100];
  std::cout << "Allocated int array at: " << intPtr << std::endl;
}

// 分配double
void allocateDouble() {
  const double* doublePtr = new double(3.14);
  std::cout << "Allocated double at: " << doublePtr << ", value: " << *doublePtr << std::endl;
}

// 分配字符串
void allocateString() {
  const std::string* strPtr = new std::string("Hello, World!");
  std::cout << "Allocated string at: " << strPtr << ", value: " << *strPtr << std::endl;
}

// 分配动态数组
void allocateDynamicArray() {
  size_t arraySize = 10;
  size_t* const arrayPtr = new size_t[arraySize];
  std::cout << "Allocated array of " << arraySize << " ints at: " << arrayPtr << std::endl;
  for (size_t i = 0; i < arraySize; ++i) {
    arrayPtr[i] = i;
  }
}

// 使用mmap分配内存
void allocateMmap() {
  size_t mmapSize = 4096;  // 4KB
  const void* mmapPtr = mmap(nullptr, mmapSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
  if (mmapPtr == MAP_FAILED) {
    perror("mmap failed");
  } else {
    std::cout << "Allocated mmap at: " << mmapPtr << ", size: " << mmapSize << " bytes" << std::endl;
  }
}

void allocateMemory() {
  allocateIntArray();
  allocateDouble();
  allocateString();
  allocateDynamicArray();
  allocateMmap();
}

// 信号处理函数
void signalHandler(int signum) {
  std::cout << "Signal (" << signum << ") received, printing heap profile:" << std::endl;
  mallctl("prof.dump", nullptr, nullptr, nullptr, 0);
}

int main() {
  // 设置信号处理函数
  struct sigaction action;
  action.sa_handler = signalHandler;
  sigemptyset(&action.sa_mask);
  action.sa_flags = 0;
  sigaction(SIGUSR1, &action, nullptr);

  usleep(100000);  // 100ms
  allocateMemory();
  while (true) {
    usleep(100000);  // 100ms
  }

  return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

橘色的喵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值