Add simple malloc statistics and metrics

Add some basic statistics for allocated memory based on mallinfo(),
and use that to define two metrics:

 usedAfterOverview: bytes used after the overview is shown once
 leakedAfterOverview: additional bytes used when the overview is
   shown a second time.

https://bugzilla.gnome.org/show_bug.cgi?id=618189
This commit is contained in:
Owen W. Taylor 2010-05-11 15:53:55 -04:00
parent c972ff3ab4
commit 08b8b39a5d
3 changed files with 85 additions and 2 deletions

View File

@ -12,7 +12,9 @@ let METRIC_DESCRIPTIONS = {
overviewLatencyFirst: "Time to first frame after triggering overview, first time", overviewLatencyFirst: "Time to first frame after triggering overview, first time",
overviewFramesFirst: "Frames displayed when going to overview, first time", overviewFramesFirst: "Frames displayed when going to overview, first time",
overviewLatencySubsequent: "Time to first frame after triggering overview, second time", overviewLatencySubsequent: "Time to first frame after triggering overview, second time",
overviewFramesSubsequent: "Frames displayed when going to overview, second time" overviewFramesSubsequent: "Frames displayed when going to overview, second time",
usedAfterOverview: "Malloc'ed bytes after the overview is shown once",
leakedAfterOverview: "Additional malloc'ed bytes the second time the overview is shown"
}; };
let METRICS = { let METRICS = {
@ -21,6 +23,7 @@ let METRICS = {
function run() { function run() {
Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview"); Scripting.defineScriptEvent("overviewShowStart", "Starting to show the overview");
Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing"); Scripting.defineScriptEvent("overviewShowDone", "Overview finished showing");
Scripting.defineScriptEvent("afterShowHide", "After a show/hide cycle for the overview");
yield Scripting.sleep(1000); yield Scripting.sleep(1000);
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
@ -29,8 +32,14 @@ function run() {
Main.overview.show(); Main.overview.show();
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
Scripting.scriptEvent('overviewShowDone'); Scripting.scriptEvent('overviewShowDone');
Main.overview.hide(); Main.overview.hide();
yield Scripting.waitLeisure(); yield Scripting.waitLeisure();
global.gc();
yield Scripting.sleep(1000);
Scripting.collectStatistics();
Scripting.scriptEvent('afterShowHide');
} }
} }
@ -38,6 +47,9 @@ let showingOverview = false;
let overviewShowStart; let overviewShowStart;
let overviewFrames; let overviewFrames;
let overviewLatency; let overviewLatency;
let mallocUsedSize = 0;
let overviewShowCount = 0;
let firstOverviewUsedSize;
function script_overviewShowStart(time) { function script_overviewShowStart(time) {
showingOverview = true; showingOverview = true;
@ -48,7 +60,9 @@ function script_overviewShowStart(time) {
function script_overviewShowDone(time) { function script_overviewShowDone(time) {
showingOverview = false; showingOverview = false;
if (!('overviewLatencyFirst' in METRICS)) { overviewShowCount++;
if (overviewShowCount == 1) {
METRICS.overviewLatencyFirst = overviewLatency; METRICS.overviewLatencyFirst = overviewLatency;
METRICS.overviewFramesFirst = overviewFrames; METRICS.overviewFramesFirst = overviewFrames;
} else { } else {
@ -57,6 +71,18 @@ function script_overviewShowDone(time) {
} }
} }
function script_afterShowHide(time) {
if (overviewShowCount == 1) {
METRICS.usedAfterOverview = mallocUsedSize;
} else {
METRICS.leakedAfterOverview = mallocUsedSize - METRICS.usedAfterOverview;
}
}
function malloc_usedSize(time, bytes) {
mallocUsedSize = bytes;
}
function clutter_stagePaintDone(time) { function clutter_stagePaintDone(time) {
if (showingOverview) { if (showingOverview) {
if (overviewFrames == 0) if (overviewFrames == 0)

View File

@ -94,6 +94,15 @@ function scriptEvent(name) {
Shell.PerfLog.get_default().event("script." + name); Shell.PerfLog.get_default().event("script." + name);
} }
/**
* collectStatistics
*
* Convenience function to trigger statistics collection
*/
function collectStatistics() {
Shell.PerfLog.get_default().collect_statistics();
}
function _step(g, finish, onError) { function _step(g, finish, onError) {
try { try {
let waitFunction = g.next(); let waitFunction = g.next();

View File

@ -38,12 +38,14 @@
#include <gjs/gjs.h> #include <gjs/gjs.h>
#include <girepository.h> #include <girepository.h>
#include <gmodule.h> #include <gmodule.h>
#include <malloc.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "display.h" #include "display.h"
#include "shell-global-private.h" #include "shell-global-private.h"
#include "shell-perf-log.h"
#include "shell-wm.h" #include "shell-wm.h"
#include "st.h" #include "st.h"
@ -232,6 +234,50 @@ settings_notify_cb (GtkSettings *settings,
update_font_options (settings); update_font_options (settings);
} }
static void
malloc_statistics_callback (ShellPerfLog *perf_log,
gpointer data)
{
struct mallinfo info = mallinfo ();
shell_perf_log_update_statistic_i (perf_log,
"malloc.arenaSize",
info.arena);
shell_perf_log_update_statistic_i (perf_log,
"malloc.mmapSize",
info.hblkhd);
shell_perf_log_update_statistic_i (perf_log,
"malloc.usedSize",
info.uordblks);
}
static void
add_statistics (GnomeShellPlugin *shell_plugin)
{
ShellPerfLog *perf_log = shell_perf_log_get_default ();
/* For probably historical reasons, mallinfo() defines the returned values,
* even those in bytes as int, not size_t. We're determined not to use
* more than 2G of malloc'ed memory, so are OK with that.
*/
shell_perf_log_define_statistic (perf_log,
"malloc.arenaSize",
"Amount of memory allocated by malloc() with brk(), in bytes",
"i");
shell_perf_log_define_statistic (perf_log,
"malloc.mmapSize",
"Amount of memory allocated by malloc() with mmap(), in bytes",
"i");
shell_perf_log_define_statistic (perf_log,
"malloc.usedSize",
"Amount of malloc'ed memory currently in use",
"i");
shell_perf_log_add_statistics_callback (perf_log,
malloc_statistics_callback,
NULL, NULL);
}
static void static void
gnome_shell_plugin_start (MutterPlugin *plugin) gnome_shell_plugin_start (MutterPlugin *plugin)
{ {
@ -280,6 +326,8 @@ gnome_shell_plugin_start (MutterPlugin *plugin)
_shell_global_set_plugin (global, MUTTER_PLUGIN(shell_plugin)); _shell_global_set_plugin (global, MUTTER_PLUGIN(shell_plugin));
_shell_global_set_gjs_context (global, shell_plugin->gjs_context); _shell_global_set_gjs_context (global, shell_plugin->gjs_context);
add_statistics (shell_plugin);
if (!gjs_context_eval (shell_plugin->gjs_context, if (!gjs_context_eval (shell_plugin->gjs_context,
"const Main = imports.ui.main; Main.start();", "const Main = imports.ui.main; Main.start();",
-1, -1,