Skip to content

Profiling: Enable profiling in code using google-perftools #1539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,40 @@ if get_option('development') and git.found ()
branch = output.stdout().strip()
endif

# Profiler linking code taken from https://github.com/RidgeRun/gst-inference/blob/master/meson.build
# with some amendments
# 'libprofiler' and 'libtcmalloc' are provided by installing (e.g.) 'google-perftools' and 'libgoogle-pertools-dev'
# Profiling is not active unless either the correct environment variables are set at runtime
# or the profiling is switched on/off in the code using the CPU_PROFILING and HEAP_PROFILING conditional compilation flags
# with the commands Profiler.start (<path-to-profile-output>) and Profiler.stop () and the corresponding HeapProfiler functions
# It is advisable not to run cpu profiling at the same time as heap profiling
# If meson options are changed then rebuild with 'cd .. && sudo rm -R ./build && build'
# See https://github.com/gperftools/gperftools/blob/master/docs/cpuprofile.adoc
# and https://github.com/gperftools/gperftools/blob/master/docs/heapprofile.adoc
if get_option('cpu-profiling-enabled')
profiler_dep = dependency ('libprofiler')
if(profiler_dep.found())
message('CPU profiling enabled: Building with profiling support.')
add_global_link_arguments ('-lprofiler', language: 'c')
add_project_arguments ('--define=PROFILING', language: 'vala')
dependencies += profiler_dep
else
message('MESON_FAIL: CPU profiling requested but libprofiler (gperftools) not found.')
endif
endif
if get_option('heap-profiling-enabled')
heap_profiler_dep = dependency ('libtcmalloc')
if(heap_profiler_dep.found())
message('Heap profiling enabled: Building with heap profiling support.')
add_global_link_arguments ('-ltcmalloc', language: 'c')
add_project_arguments ('--define=HEAP_PROFILING', language: 'vala')
dependencies += heap_profiler_dep
else
message('MESON_FAIL: Heap profiling requested but libtcmalloc (gperftools) not found.')
endif
endif


subdir('data')
subdir('src')
if get_option('plugins')
Expand Down
2 changes: 2 additions & 0 deletions meson_options.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
option('plugins', type : 'boolean', value : true)
option('have_pkexec', type : 'boolean', value : true, description : 'Allow launching with pkexec. Should not be used in FlatPak')
option('development', type : 'boolean', value : false, description : 'Build is a development branch')
option('cpu-profiling-enabled', type : 'boolean', value : false, description: 'Enable cpu profiling')
option('heap-profiling-enabled', type : 'boolean', value : false, description: 'Enable heap profiling')
32 changes: 32 additions & 0 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,39 @@ namespace Scratch {
}

public static int main (string[] args) {
// By default, profile whole app when profiling is enabled in meson_options.txt
// These conditional statements can be moved to profile sections of code
// The gperftools library must be installed (libgoogle-perftools-dev)
// Amend the profile report paths as required
#if PROFILING
// Visualize the cpu profile with e.g. google-pprof --functions --gv /usr/bin/io.elementary.code <profile_path>
// Use --focus=<regexp> and --ignore=<regexp> to filter/prune nodes displayed
var profile_path = Path.build_filename (Environment.get_home_dir (), "CpuProfileCodeApplication.prof");
// Start CPU profiling
Profiler.start (profile_path);
warning ("start cpu profiling - output to %s", profile_path);
#endif
#if HEAP_PROFILING
// NOTE: Heap profiling at this point slows the program down **a lot** It will take tens of seconds to load.
// The output path will have the suffix '.NNNN.heap' appended
// Visualize the profile with e.g. google-pprof --gv /usr/bin/io.elementary.code <profile_path>
// Use --focus=<regexp> and --ignore=<regexp> to filter/prune nodes displayed
var heap_profile_path = Path.build_filename (Environment.get_home_dir (), "HeapProfileCodeApplication");
// Start heap profiling
HeapProfiler.start (heap_profile_path);
warning ("start heap profiling - output to %s", heap_profile_path);
#endif

return new Application ().run (args);

#if PROFILING
Profiler.stop ();
warning ("stop cpu profiling");
#endif
#if HEAP_PROFILING
HeapProfiler.stop ();
warning ("stop heap profiling");
#endif
}
}
}
9 changes: 9 additions & 0 deletions vapi/libprofiler.vapi
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[CCode (cheader_filename = "gperftools/profiler.h")]
namespace Profiler {
[CCode (cname = "ProfilerStart")]
public static void start (string path_to_output_file);
[CCode (cname = "ProfilerStop")]
public static void stop ();
[CCode (cname = "ProfilerFlush")]
public static void flush ();
}
9 changes: 9 additions & 0 deletions vapi/libtcmalloc.vapi
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
[CCode (cheader_filename = "gperftools/heap-profiler.h")]
namespace HeapProfiler {
[CCode (cname = "HeapProfilerStart")]
public static void start (string path_to_output_file_profix);
[CCode (cname = "HeapProfilerStop")]
public static void stop ();
[CCode (cname = "HeapProfilerDump")]
public static void dump (string reason);
}