gtk/gdk/gdkprofiler.c

329 lines
7.5 KiB
C
Raw Normal View History

/* 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 <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <sys/types.h>
#include <signal.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "gdkversionmacros.h"
#include "gdkprofilerprivate.h"
#include "gdkframeclockprivate.h"
#ifdef HAVE_SYSPROF_CAPTURE
#include <sysprof-capture.h>
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)
{
gchar *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 */