/* GDK - The GIMP Drawing Kit * * gdkprofiler.c: A simple profiler * * Copyright © 2018 Matthias Clasen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library. If not, see . */ #include "config.h" #include #include #ifdef HAVE_UNISTD_H #include #endif #include "gdkversionmacros.h" #include "gdkprofilerprivate.h" #include "gdkframeclockprivate.h" #ifdef HAVE_SYSPROF_CAPTURE #include static SysprofCaptureWriter *writer = NULL; static gboolean running = FALSE; static void profiler_stop (int s) { if (writer) sysprof_capture_writer_unref (writer); } void gdk_profiler_start (int fd) { if (writer) return; sysprof_clock_init (); if (fd == -1) { char *filename; filename = g_strdup_printf ("gtk.%d.syscap", getpid ()); g_print ("Writing profiling data to %s\n", filename); writer = sysprof_capture_writer_new (filename, 16*1024); g_free (filename); } else if (fd > 2) writer = sysprof_capture_writer_new_from_fd (fd, 16*1024); if (writer) running = TRUE; atexit (G_CALLBACK (profiler_stop)); signal (SIGTERM, profiler_stop); } void gdk_profiler_stop (void) { running = FALSE; } gboolean gdk_profiler_is_running (void) { return running; } void gdk_profiler_add_mark (gint64 start, guint64 duration, const char *name, const char *message) { if (!running) return; sysprof_capture_writer_add_mark (writer, start * 1000L, -1, getpid (), duration * 1000L, "gtk", name, message); } static void add_markvf (gint64 start, guint64 duration, const char *name, const char *format, va_list args) G_GNUC_PRINTF(4, 0); static void add_markvf (gint64 start, guint64 duration, const char *name, const char *format, va_list args) { char *message; message = g_strdup_vprintf (format, args); sysprof_capture_writer_add_mark (writer, start * 1000L, -1, getpid (), duration * 1000L, "gtk", name, message); g_free (message); } void gdk_profiler_add_markf (gint64 start, guint64 duration, const char *name, const char *format, ...) { va_list args; if (!running) return; va_start (args, format); add_markvf (start, duration, name, format, args); va_end (args); } void gdk_profiler_end_mark (gint64 start, const char *name, const char *message) { if (!running) return; sysprof_capture_writer_add_mark (writer, start * 1000L, -1, getpid (), (g_get_monotonic_time () - start) * 1000L, "gtk", name, message); } void gdk_profiler_end_markf (gint64 start, const char *name, const char *format, ...) { va_list args; if (!running) return; va_start (args, format); add_markvf (start, g_get_monotonic_time () - start, name, format, args); va_end (args); } static guint define_counter (const char *name, const char *description, int type) { SysprofCaptureCounter counter; if (!writer) return 0; counter.id = (guint) sysprof_capture_writer_request_counter (writer, 1); counter.type = type; counter.value.vdbl = 0; g_strlcpy (counter.category, "gtk", sizeof counter.category); g_strlcpy (counter.name, name, sizeof counter.name); g_strlcpy (counter.description, description, sizeof counter.name); sysprof_capture_writer_define_counters (writer, SYSPROF_CAPTURE_CURRENT_TIME, -1, getpid (), &counter, 1); return counter.id; } guint gdk_profiler_define_counter (const char *name, const char *description) { return define_counter (name, description, SYSPROF_CAPTURE_COUNTER_DOUBLE); } guint gdk_profiler_define_int_counter (const char *name, const char *description) { return define_counter (name, description, SYSPROF_CAPTURE_COUNTER_INT64); } void gdk_profiler_set_counter (guint id, gint64 time, double val) { SysprofCaptureCounterValue value; if (!running) return; value.vdbl = val; sysprof_capture_writer_set_counters (writer, time * 1000L, -1, getpid (), &id, &value, 1); } void gdk_profiler_set_int_counter (guint id, gint64 time, gint64 val) { SysprofCaptureCounterValue value; if (!running) return; value.v64 = val; sysprof_capture_writer_set_counters (writer, time * 1000L, -1, getpid (), &id, &value, 1); } #else void gdk_profiler_start (int fd) { } void gdk_profiler_stop (void) { } gboolean gdk_profiler_is_running (void) { return FALSE; } void gdk_profiler_add_mark (gint64 start, guint64 duration, const char *name, const char *message) { } void gdk_profiler_add_markf (gint64 start, guint64 duration, const char *name, const char *format, ...) { } void gdk_profiler_end_mark (gint64 start, const char *name, const char *message) { } void gdk_profiler_end_markf (gint64 start, const char *name, const char *format, ...) { } guint gdk_profiler_define_counter (const char *name, const char *description) { return 0; } void gdk_profiler_set_counter (guint id, gint64 time, double value) { } guint gdk_profiler_define_int_counter (const char *name, const char *description) { return 0; } void gdk_profiler_set_int_counter (guint id, gint64 time, gint64 value) { } #endif /* G_OS_WIN32 */