Skip to content

Commit

Permalink
Add additional profiling tools
Browse files Browse the repository at this point in the history
  • Loading branch information
Davinco authored Jul 21, 2020
1 parent 866386c commit 211ebcc
Show file tree
Hide file tree
Showing 6 changed files with 475 additions and 0 deletions.
165 changes: 165 additions & 0 deletions Bloaty.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
#
# OVERVIEW
#
# Bloaty is a static memory profiling tool which measures the size utilization
# of a target binary and outputs the result to a file.
#
# USAGE
#
# swift_add_bloaty(<target>
# [OPTIONS]
# [WORKING_DIRECTORY working_directory]
# )
#
# Call this function to create a new cmake target which runs the `target`'s
# executable binary with bloaty applied. All created cmake targets can be
# invoked by calling the common target 'do-all-bloaty'.
#
# BLOATY OPTIONS
#
# * SEGMENTS: Outputs what the run-time loader uses to determine what
# parts of the binary needs to be loaded/mapped into memory.
# * SECTIONS: Outputs the binary in finer details structured in different sections.
# * SYMBOLS: Outputs individual functions or variables.
# * COMPILEUNITS: Outputs what compile unit (and corresponding source file)
# each bit of the binary came from.
#
# * NUM: Set how many rows to show per level before collapsing into '[other]'.
# Set to '0' for unlimited, default: '20'.
#
# * SORT:
# vm - Sort the vm size column from largest to smallest and tells you
# how much space the binary will take when loaded into memory.
# file - Sort the file size column from largest to smallest and tells you
# how much space the binary is taking on disk.
# both - Default, sorts by max(vm, file).
#
# WORKING_DIRECTORY
# This variable changes the output directory for the tool from the default folder
# `${CMAKE_BINARY_DIR}/profiling/bloaty-reports` to the given argument.
# Example, using argument `/tmp`, outputs the results to `/tmp/bloaty-reports/
#
# NOTE
#
# * A cmake option is available to control whether targets should be built,
# with the name ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING.
#
# Running
#
# cmake -D<project>_ENABLE_MEMORY_PROFILING=ON ..
#
# will explicitly enable these targets from the command line at configure time
#

option(${PROJECT_NAME}_ENABLE_MEMORY_PROFILING "Builds targets with memory profiling" OFF)

find_package(Bloaty)

if (NOT Bloaty_FOUND AND ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING)
message(STATUS "Bloaty is not installed on system, will fetch content from source")

cmake_minimum_required(VERSION 3.14.0)
include(FetchContent)

FetchContent_Declare(
bloaty
GIT_REPOSITORY https://github.com/google/bloaty.git
GIT_TAG v1.1
GIT_SHALLOW TRUE
)
FetchContent_MakeAvailable(bloaty)
endif()

macro(eval_bloaty_target target)
if (NOT TARGET ${target})
message(FATAL_ERROR "Specified target \"${target}\" does not exist")
endif()

get_target_property(target_type ${target} TYPE)
if (NOT target_type STREQUAL EXECUTABLE)
message(FATAL_ERROR "Specified target \"${target}\" must be an executable type to register for profiling with bloaty")
endif()

if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
return()
endif()

if (NOT ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING)
return()
endif()
endmacro()

function(swift_add_bloaty target)
eval_bloaty_target(${target})

set(argOption SEGMENTS SECTIONS SYMBOLS COMPILEUNITS)
set(argSingle NUM SORT WORKING_DIRECTORY)
set(argMulti "")

cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN})

if (x_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unparsed arguments ${x_UNPARSED_ARGUMENTS}")
endif()

set(target_name bloaty-${target})
set(working_directory ${CMAKE_BINARY_DIR}/profiling)
if (x_WORKING_DIRECTORY)
set(working_directory ${x_WORKING_DIRECTORY})
endif()
set(reports_directory ${working_directory}/bloaty-reports)
set(output_file ${target_name}.txt)

unset(resource_options)
if (x_SEGMENTS)
list(APPEND resource_options segments)
endif()

if (x_SECTIONS)
list(APPEND resource_options sections)
endif()

if (x_SYMBOLS)
list(APPEND resource_options symbols)
endif()

if (x_COMPILEUNITS)
list(APPEND resource_options compileunits)
endif()

if (DEFINED resource_options)
string(REPLACE ";" "," resource_options "${resource_options}")
set(resource_options -d ${resource_options})
endif()

if (DEFINED x_NUM)
list(APPEND resource_options -n ${x_NUM})
endif()

if (x_SORT)
list(APPEND resource_options -s ${x_SORT})
endif()

if (NOT Bloaty_FOUND)
add_custom_target(${target_name}
COMMENT "bloaty is running on ${target}\ (output: \"${reports_directory}/${output_file}\")"
COMMAND ${CMAKE_COMMAND} -E make_directory ${reports_directory}
COMMAND ${CMAKE_COMMAND} -E chdir ${reports_directory} echo \"bloaty with options: ${resource_options}\" > ${reports_directory}/${output_file}
COMMAND ${CMAKE_COMMAND} -E env $<TARGET_FILE:bloaty> ${resource_options} $<TARGET_FILE:${target}> >> ${reports_directory}/${output_file}
DEPENDS ${target}
)
else()
add_custom_target(${target_name}
COMMENT "bloaty is running on ${target}\ (output: \"${reports_directory}/${output_file}\")"
COMMAND ${CMAKE_COMMAND} -E make_directory ${reports_directory}
COMMAND ${CMAKE_COMMAND} -E chdir ${reports_directory} echo \"bloaty with options: ${resource_options}\" > ${reports_directory}/${output_file}
COMMAND ${CMAKE_COMMAND} -E env ${Bloaty_EXECUTABLE} ${resource_options} $<TARGET_FILE:${target}> >> ${reports_directory}/${output_file}
DEPENDS ${target}
)
endif()

if (NOT TARGET do-all-bloaty)
add_custom_target(do-all-bloaty)
endif()
add_dependencies(do-all-bloaty ${target_name})
endfunction()
11 changes: 11 additions & 0 deletions FindBloaty.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if(NOT Bloaty_FOUND)

find_program(Bloaty_EXECUTABLE bloaty)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Bloaty DEFAULT_MSG Bloaty_EXECUTABLE)

set(Bloaty_FOUND ${Bloaty_FOUND} CACHE BOOL "Flag whether Bloaty package was found")
mark_as_advanced(Bloaty_FOUND Bloaty_EXECUTABLE)

endif()
11 changes: 11 additions & 0 deletions FindHeaptrack.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if(NOT Heaptrack_FOUND)

find_program(Heaptrack_EXECUTABLE NAMES heaptrack)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Heaptrack DEFAULT_MSG Heaptrack_EXECUTABLE)

set(Heaptrack_FOUND ${Heaptrack_FOUND} CACHE BOOL "Flag whether Heaptrack package was found")
mark_as_advanced(Heaptrack_FOUND Heaptrack_EXECUTABLE)

endif()
11 changes: 11 additions & 0 deletions FindStackusage.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
if(NOT Stackusage_FOUND)

find_program(Stackusage_EXECUTABLE NAMES stackusage)

include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Stackusage DEFAULT_MSG Stackusage_EXECUTABLE)

set(Stackusage_FOUND ${Stackusage_FOUND} CACHE BOOL "Flag whether Stackusage package was found")
mark_as_advanced(Stackusage_FOUND Stackusage_EXECUTABLE)

endif()
140 changes: 140 additions & 0 deletions Heaptrack.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#
# OVERVIEW
#
# Heaptrack is a dynamic memory profiling tool which measures the heap utilization
# of a target binary and outputs the result to a file.
#
# USAGE
#
# swift_add_heaptrack(<target>
# [NAME name]
# [WORKING_DIRECTORY working_directory]
# [PROGRAM_ARGS arg1 arg2 ...]
# )
#
# Call this function to create a new cmake target which runs the `target`'s
# executable binary with heaptrack applied. All created cmake targets can be
# invoked by calling the common target 'do-all-heaptrack'.
#
# NAME
# This variable makes it possible to choose a custom name for the target, which
# is useful in situations using Google Test.
#
# WORKING_DIRECTORY
# This variable changes the output directory for the tool from the default folder
# `${CMAKE_BINARY_DIR}/profiling/heaptrack-reports` to the given argument.
# Example, using argument `/tmp`, outputs the results to `/tmp/heaptrack-reports/
#
# PROGRAM_ARGS
# This variable specifies target arguments. Example, using a yaml-config
# with "--config example.yaml"
#
# NOTE
#
# * Target needs to be run with a config-file.
# * A cmake option is available to control whether targets should be built,
# with the name ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING.
#
# Running
#
# cmake -D<project>_ENABLE_MEMORY_PROFILING=ON ..
#
# will explicitly enable these targets from the command line at configure time
#

option(${PROJECT_NAME}_ENABLE_MEMORY_PROFILING "Builds targets with memory profiling" OFF)

find_package(Heaptrack)

if (NOT Heaptrack_FOUND AND ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING)
message(STATUS "Heaptrack is not installed on system, will fetch content from source")

cmake_minimum_required(VERSION 3.11.0)
include(FetchContent)

FetchContent_Declare(
heaptrack
GIT_REPOSITORY https://github.com/KDE/heaptrack.git
GIT_TAG v1.1.0
GIT_SHALLOW TRUE
)
FetchContent_GetProperties(heaptrack)
if(NOT heaptrack_POPULATED)
FetchContent_Populate(heaptrack)
set(current_build_test_state ${BUILD_TESTING})
set(BUILD_TESTING OFF)
add_subdirectory(${heaptrack_SOURCE_DIR} ${heaptrack_BINARY_DIR})
set(BUILD_TESTING ${current_build_test_state})
endif()
endif()

macro(eval_heaptrack_target target)
if (NOT TARGET ${target})
message(FATAL_ERROR "Specified target \"${target}\" does not exist")
endif()

get_target_property(target_type ${target} TYPE)
if (NOT target_type STREQUAL EXECUTABLE)
message(FATAL_ERROR "Specified target \"${target}\" must be an executable type to register for profiling with heaptrack")
endif()

if (NOT ${PROJECT_NAME} STREQUAL ${CMAKE_PROJECT_NAME})
return()
endif()

if (CMAKE_CROSSCOMPILING)
return()
endif()

if (NOT ${PROJECT_NAME}_ENABLE_MEMORY_PROFILING)
return()
endif()
endmacro()

function(swift_add_heaptrack target)
eval_heaptrack_target(${target})

set(argOption "")
set(argSingle NAME WORKING_DIRECTORY)
set(argMulti PROGRAM_ARGS)

cmake_parse_arguments(x "${argOption}" "${argSingle}" "${argMulti}" ${ARGN})

if (x_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unparsed arguments ${x_UNPARSED_ARGUMENTS}")
endif()

set(target_name heaptrack-${target})
if (x_NAME)
set(target_name heaptrack-${x_NAME})
endif()

set(working_directory ${CMAKE_BINARY_DIR}/profiling)
if (x_WORKING_DIRECTORY)
set(working_directory ${x_WORKING_DIRECTORY})
endif()
set(reports_directory ${working_directory}/heaptrack-reports)

if (NOT Heaptrack_FOUND)
add_custom_target(${target_name}
COMMENT "heaptrack is running on ${target}\ (output: \"${reports_directory}\")"
COMMAND $(MAKE)
WORKING_DIRECTORY ${heaptrack_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -E make_directory ${reports_directory}
COMMAND ${CMAKE_COMMAND} -E chdir ${reports_directory} ${heaptrack_BINARY_DIR}/bin/heaptrack $<TARGET_FILE:${target}> ${x_PROGRAM_ARGS}
DEPENDS ${target}
)
else()
add_custom_target(${target_name}
COMMENT "heaptrack is running on ${target}\ (output: \"${reports_directory}\")"
COMMAND ${CMAKE_COMMAND} -E make_directory ${reports_directory}
COMMAND ${CMAKE_COMMAND} -E chdir ${reports_directory} ${Heaptrack_EXECUTABLE} $<TARGET_FILE:${target}> ${x_PROGRAM_ARGS}
DEPENDS ${target}
)
endif()

if (NOT TARGET do-all-heaptrack)
add_custom_target(do-all-heaptrack)
endif()
add_dependencies(do-all-heaptrack ${target_name})
endfunction()
Loading

0 comments on commit 211ebcc

Please sign in to comment.