#include #include #include 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)); }