mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-10 02:40:11 +00:00
Prototype a sysprof helper
This is an attempt to see how we can use sysprof data in our tests to extract useful performance numbers. Use it as a wrapper around any GTK+ process: ./testperf ./gtk4-widget-factory Currently, it repeatedly runs the given commandline, extracts the first css validation time from the resulting syscap file, and prints out the min/max/avg of the runs at the end. This relies on the environment variable GTK_DEBUG_AUTO_QUIT to cause the process to exit soon after launch.
This commit is contained in:
parent
a6f300cefd
commit
ea17728ee5
@ -150,4 +150,9 @@ foreach t: gtk_tests
|
||||
dependencies: [libgtk_dep, libm])
|
||||
endforeach
|
||||
|
||||
|
||||
|
||||
executable('testperf', 'testperf.c',
|
||||
dependencies: [profiler_dep, platform_gio_dep, libm])
|
||||
|
||||
subdir('visuals')
|
||||
|
140
tests/testperf.c
Normal file
140
tests/testperf.c
Normal file
@ -0,0 +1,140 @@
|
||||
#include <stdio.h>
|
||||
#include <sysprof-capture.h>
|
||||
#include <gio/gio.h>
|
||||
|
||||
typedef struct {
|
||||
const char *group;
|
||||
gint64 value;
|
||||
} Data;
|
||||
|
||||
static gboolean
|
||||
callback (const SysprofCaptureFrame *frame,
|
||||
gpointer user_data)
|
||||
{
|
||||
Data *data = user_data;
|
||||
|
||||
if (frame->type == SYSPROF_CAPTURE_FRAME_MARK)
|
||||
{
|
||||
SysprofCaptureMark *mark = (SysprofCaptureMark *)frame;
|
||||
if (strcmp (mark->group, "gtk") == 0 &&
|
||||
strcmp (mark->name, data->group) == 0)
|
||||
{
|
||||
data->value = mark->duration;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define MILLISECONDS(v) ((v) / (1000.0 * G_TIME_SPAN_MILLISECOND))
|
||||
|
||||
static int opt_rep = 10;
|
||||
|
||||
static GOptionEntry options[] = {
|
||||
{ "runs", 'r', G_OPTION_FLAG_NONE, G_OPTION_ARG_INT, &opt_rep, "Number of runs", "COUNT" },
|
||||
{ NULL, }
|
||||
};
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GOptionContext *context;
|
||||
GError *error = NULL;
|
||||
Data data;
|
||||
SysprofCaptureFrameType type;
|
||||
char fd_str[20];
|
||||
gint64 *values;
|
||||
gint64 min, max, total;
|
||||
int i;
|
||||
|
||||
context = g_option_context_new ("COMMANDLINE");
|
||||
g_option_context_add_main_entries (context, options, NULL);
|
||||
if (!g_option_context_parse (context, &argc, &argv, &error))
|
||||
g_error ("Parsing options: %s", error->message);
|
||||
|
||||
if (argc < 2)
|
||||
{
|
||||
g_print ("Usage: testperf [OPTIONS] COMMANDLINE\n");
|
||||
exit (1);
|
||||
}
|
||||
|
||||
if (opt_rep < 1)
|
||||
g_error ("COUNT must be a positive number");
|
||||
|
||||
values = g_new (gint64, opt_rep);
|
||||
|
||||
for (i = 0; i < opt_rep; i++)
|
||||
{
|
||||
GSubprocessLauncher *launcher;
|
||||
GSubprocess *subprocess;
|
||||
int fd;
|
||||
gchar *name;
|
||||
SysprofCaptureReader *reader;
|
||||
SysprofCaptureCursor *cursor;
|
||||
SysprofCaptureCondition *condition;
|
||||
|
||||
fd = g_file_open_tmp ("gtk.XXXXXX.syscap", &name, &error);
|
||||
if (error)
|
||||
g_error ("Create syscap file: %s", error->message);
|
||||
|
||||
launcher = g_subprocess_launcher_new (0);
|
||||
g_subprocess_launcher_take_fd (launcher, fd, fd);
|
||||
g_snprintf (fd_str, sizeof (fd_str), "%d", fd);
|
||||
g_subprocess_launcher_setenv (launcher, "GTK_TRACE_FD", fd_str, TRUE);
|
||||
g_subprocess_launcher_setenv (launcher, "GTK_DEBUG_AUTO_QUIT", "1", TRUE);
|
||||
|
||||
subprocess = g_subprocess_launcher_spawnv (launcher, (const char *const *)argv + 1, &error);
|
||||
if (error)
|
||||
g_error ("Launch child: %s", error->message);
|
||||
|
||||
if (!g_subprocess_wait (subprocess, NULL, &error))
|
||||
g_error ("Run child: %s", error->message);
|
||||
|
||||
g_object_unref (subprocess);
|
||||
g_object_unref (launcher);
|
||||
|
||||
reader = sysprof_capture_reader_new (name, &error);
|
||||
if (error)
|
||||
g_error ("Opening syscap file: %s", error->message);
|
||||
|
||||
data.group = "style";
|
||||
data.value = 0;
|
||||
|
||||
cursor = sysprof_capture_cursor_new (reader);
|
||||
|
||||
type = SYSPROF_CAPTURE_FRAME_MARK;
|
||||
condition = sysprof_capture_condition_new_where_type_in (1, &type);
|
||||
sysprof_capture_cursor_add_condition (cursor, condition);
|
||||
|
||||
sysprof_capture_cursor_foreach (cursor, callback, &data);
|
||||
|
||||
values[i] = data.value;
|
||||
|
||||
sysprof_capture_cursor_unref (cursor);
|
||||
sysprof_capture_reader_unref (reader);
|
||||
|
||||
remove (name);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
min = G_MAXINT64;
|
||||
max = 0;
|
||||
total = 0;
|
||||
|
||||
for (i = 0; i < opt_rep; i++)
|
||||
{
|
||||
if (min > values[i])
|
||||
min = values[i];
|
||||
if (max < values[i])
|
||||
max = values[i];
|
||||
total += values[i];
|
||||
}
|
||||
|
||||
g_print ("%d runs, min %g, max %g, avg %g\n",
|
||||
opt_rep,
|
||||
MILLISECONDS (min),
|
||||
MILLISECONDS (max),
|
||||
MILLISECONDS (total / opt_rep));
|
||||
}
|
Loading…
Reference in New Issue
Block a user