GoogleCPUProfiler在CMake项目中的使用

本文介绍了如何在CMake项目中集成并使用GoogleCPUProfiler进行资源占用分析。首先,详细说明了gperftools的下载、编译及在CMake中的配置方法。然后,展示了如何通过ProfilerStart和ProfilerStop函数在代码中插入分析点,并生成资源占用的.prof文件。最后,提到了使用pprof工具以不同格式查看分析结果。

GoogleCPUProfiler使用

  • gperftools-2.7下载与编译

将gperftools-2.7下载解压之后,进行编译make && make install

  • gperftools适用cmake项目

1)gperftools没有提供官方的查找profiler库的cmake脚本,所以在基于cmake管理的项目中如果要查找libprofiler库需要自己写FindPROFILER.cmake脚本:

# - Find libprofiler

# - This module determines the libprofiler library of the system

# the vairable can be set

#   LIBPROFILER_STATIC_LINK set true for static link library 为TRUE是要求静态连接

# The following variables are set if the library found:

# LIBPROFILER_FOUND - If false do nnt try to use libprofiler.

# LIBPROFILER_INCLUDE_DIRS - where to find the headfile of library.include文件夹位置

# LIBPROFILER_LIBRARY_DIRS - where to find the libprofiler library.profiler库所在位置

# LIBPROFILER_LIBRARIES, the library file name needed to use libprofiler.profiler库及所有依赖库列表

# LIBPROFILER_LIBRARY - the library needed to use libprofiler. profiler库全路径

# imported target

#   gperftools::profiler



if(LIBPROFILER_FOUND)

    return()

endif()

include (depcommon)

# linux系统下调用pkg-config查找profiler

if (NOT WIN32)

    include(FindPkgConfig)

    unset(_verexp)

    if(LIBPROFILER_FIND_VERSION)

        if(LIBPROFILER_FIND_VERSION_EXACT)        

              set(_verexp "=${LIBPROFILER_FIND_VERSION}")

        else()

              set(_verexp ">=${LIBPROFILER_FIND_VERSION}")

        endif()

    endif()

    pkg_check_modules (LIBPROFILER libprofiler${_verexp})

endif()



if (NOT LIBPROFILER_FOUND)

# windows系统下通过查找头文件 gperftools/profiler.h和find_library 查找profiler来实现

    # find the headfile of library

    set (PROFILER_HEADS gperftools/profiler.h)

    find_path (LIBPROFILER_INCLUDE_DIRS ${PROFILER_HEADS})



    set (PROFILER_NAMES ${PROFILER_NAMES} profiler)

    find_library (LIBPROFILER_LIBRARY NAMES ${PROFILER_NAMES})



    # just find one of dependency, guess other one.

    if (NOT LIBPROFILER_LIBRARY AND LIBPROFILER_INCLUDE_DIRS)

        message ("We just find the headfile, try to guess the library location.")

        set (LIBPROFILER_LIBRARY_DIRS "${LIBPROFILER_INCLUDE_DIRS}/../lib")

        find_library (LIBPROFILER_LIBRARY NAMES ${PROFILER_NAMES} PATHS ${LIBPROFILER_LIBRARY_DIRS})

    elseif (NOT LIBPROFILER_INCLUDE_DIRS AND LIBPROFILER_LIBRARY)

        message ("We just find the lib file, try to guess the include location.")

                get_filename_component(LIBPROFILER_LIBRARY_DIRS ${LIBPROFILER_LIBRARY} DIRECTORY)

        find_path (LIBPROFILER_INCLUDE_DIRS ${PROFILER_HEADS} "${LIBPROFILER_LIBRARY_DIRS}../included")

    endif()



    # find the library.

    if (LIBPROFILER_INCLUDE_DIRS AND LIBPROFILER_LIBRARY)

        if (NOT LIBPROFILER_LIBRARY_DIRS)                        

            get_filename_component(LIBPROFILER_LIBRARY_DIRS ${LIBPROFILER_LIBRARY} DIRECTORY)

        endif ()

        list(APPEND profiler pthread)

    endif()

else ()

        list(GET MGNCS_LIBRARIES 0 _name)

    find_library (LIBPROFILER_LIBRARY NAMES ${LIBPROFILER_LIBRARIES} PATHS ${LIBPROFILER_LIBRARY_DIRS})

endif()

# handle the QUIETLY and REQUIRED arguments and set LIBPROFILER_FOUND to TRUE if

# all listed variables are TRUE

include(FindPackageHandleStandardArgs)

FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBPROFILER DEFAULT_MSG    LIBPROFILER_LIBRARIES LIBPROFILER_INCLUDE_DIRS)



if(LIBPROFILER_FOUND)

    set(_static_libname libtcmalloc_and_profiler.a)

    find_library (LIBPROFILER_STATIC_LIBRARY NAMES ${_static_libname} PATHS ${LIBPROFILER_LIBRARY_DIRS})

    if(NOT LIBPROFILER_FIND_QUIETLY)

        message(STATUS "  -I: ${LIBPROFILER_INCLUDE_DIRS}")

        message(STATUS "  -L: ${LIBPROFILER_LIBRARY_DIRS}")

        message(STATUS "  -l: ${LIBPROFILER_LIBRARIES}")

    endif()

    find_library (LIBPROFILER_LIBRARY NAMES ${LIBPROFILER_LIBRARIES} PATHS ${LIBPROFILER_LIBRARY_DIRS})



    # create imported target

    if (NOT TARGET gperftools::profiler)

        add_library(gperftools::profiler INTERFACE IMPORTED)

        if(LIBPROFILER_STATIC_LINK)

            # for linking static profiler,must use libtcmalloc_and_profiler.a,see also README gperftools

            set(_link_libs ${LIBPROFILER_STATIC_LDFLAGS})

            if(NOT LIBPROFILER_STATIC_LIBRARY)

                message(FATAL_ERROR "NOT FOUND static library for profiler:${_static_libname} ")

            endif()

      # 替换 profiler 为 :libtcmalloc_and_profiler.a

            string(REPLACE profiler :${_static_libname} _link_libs "${_link_libs}")

        else()

            set(_link_libs ${LIBPROFILER_LDFLAGS})

        endif()

        set_target_properties(gperftools::profiler PROPERTIES

            INTERFACE_COMPILE_OPTIONS "${LIBPROFILER_CFLAGS_OTHER}"

            INTERFACE_INCLUDE_DIRECTORIES "${LIBPROFILER_INCLUDE_DIRS}"

            INTERFACE_LINK_LIBRARIES   "${_link_libs}"

            )

        if(NOT LIBPROFILER_FIND_QUIETLY)

            message(STATUS "IMPORTED TARGET: gperftools::profiler,link libraies ${_link_libs}")

        endif()

    endif ()

    

endif(LIBPROFILER_FOUND)

#end

2)将该脚本所在的文件夹加入CMAKE_MODULE_PATH中(放到/usr/share/cmake-3.5/Modules文件夹中)

3)在需要使用gperftools的包CMakeLists.txt中添加find_package(PROFILER REQUIRED),在节点的target_link_libraries中添加${LIBPROFILER_LIBRARY}

三、使用gperftools收集程序资源占用情况

在需要分析资源占用情况的程序段的首尾分别添加ProfilerStart(program_temp);和ProfilerStop();其中program_temp代表生成的资源占用分析文件所在的路径。如:

int main(int argc, char** argv){

  char program_temp [1024]={0};

  snprintf(program_temp,1023,"%s_%d.prof",argv[0],getpid());

  ROS_INFO("Using plugin $$$$$$$ \"%s\" ", program_temp);

  ProfilerStart(program_temp);

  ros::init(argc, argv, "move_base_node");

  tf::TransformListener tf(ros::Duration(10));

  move_base::MoveBase move_base( tf );

  //ros::MultiThreadedSpinner s;

  ros::spin();

  ProfilerStop();

  return(0);

}

程序运行结束会生成一个以.prof为后缀的二进制文件。

四、使用pprof展示.prof文件内容

命令:

% pprof  /bin/ls ls.prof

% pprof  /bin/ls ls.prof  --text

% pprof  /bin/ls ls.prof  --gv

% pprof  /bin/ls ls.prof  --web

上述命令中/bin/ls代表运行的节点名称,ls.prof代表之前生成的资源占用分析文件,--后面跟随不同的指令可以使文件以不同方式打开。

如--text:

图片中每行对应一个函数的统计。第一,二列是该函数的本地采样(不包括被该函数调用的函数中的采样次数)次数和比例,第三列是该函数本地采样次数占当前所有已统计函数的采样次数之和的比例。第四,五列是该函数的累计采样次数(包括其调用的函数中的采样次数)和比例。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值