153 lines
4.4 KiB
C
153 lines
4.4 KiB
C
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
|
|
* vi:set noexpandtab tabstop=8 shiftwidth=8:
|
|
*
|
|
* Copyright (C) 2023 Endless OS Foundation LLC
|
|
*
|
|
* Authors:
|
|
* - Georges Basile Stavracas Neto <georges@endlessos.org>
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "config.h"
|
|
#include <gnome-software.h>
|
|
|
|
/**
|
|
* SECTION:gs-profiler
|
|
* @short_description: Macros for profiling
|
|
*
|
|
* GNOME Software provides a simple profiling mechanism that both plugins
|
|
* and GNOME Software itself can make use. Use the GS_PROFILER_BEGIN_SCOPED()
|
|
* macro to start profiling a specific code section; and pair it with
|
|
* GS_PROFILER_END_SCOPED() to finish profiling the section:
|
|
*
|
|
* ```
|
|
* GS_PROFILER_BEGIN_SCOPED(Flatpak, "list-installed-refs", "Description");
|
|
* ... list all installed refs ...
|
|
* GS_PROFILER_END_SCOPED(Flatpak);
|
|
*
|
|
*
|
|
* GS_PROFILER_BEGIN_SCOPED(Foo, "parse-something", "Parse some data");
|
|
* ... parse some data ...
|
|
* GS_PROFILER_END_SCOPED(Foo);
|
|
* ```
|
|
*
|
|
* The macros are scoped, so work correctly with early returns in the middle:
|
|
*
|
|
* ```
|
|
* GS_PROFILER_BEGIN_SCOPED(Foo, "list-applications", NULL);
|
|
*
|
|
* if (!foo_is_correct (foo))
|
|
* return FALSE;
|
|
*
|
|
* if (!long_async_op (foo, &error))
|
|
* return FALSE;
|
|
*
|
|
* return TRUE;
|
|
*
|
|
* GS_PROFILER_END_SCOPED(Foo);
|
|
* ```
|
|
*
|
|
* The description argument is nullable:
|
|
*
|
|
* ```
|
|
* GS_PROFILER_BEGIN_SCOPED(Flatpak, "list-installed-refs", NULL);
|
|
* ... list all installed refs ...
|
|
* GS_PROFILER_END_SCOPED(Flatpak);
|
|
*```
|
|
*
|
|
* A rather common case is to allocate new strings for the Sysprof name
|
|
* and description. The convenience macro GS_PROFILER_BEGIN_SCOPED_TAKE() is
|
|
* provided for that:
|
|
*
|
|
* ```
|
|
* GS_PROFILER_BEGIN_SCOPED_TAKE(Foo, g_strdup_printf ("list-installed-refs:%s", name), NULL);
|
|
* ... list all installed refs ...
|
|
* GS_PROFILER_END_SCOPED(Foo);
|
|
*```
|
|
*
|
|
* Asynchronous operations might need to track the start and end times in
|
|
* separate functions. The convenience macros GS_PROFILER_ADD_MARK() and
|
|
* GS_PROFILER_ADD_MARK_TAKE() allow for passing an independent begin time:
|
|
*
|
|
* ```
|
|
* GS_PROFILER_ADD_MARK(Foo, task->begin_time, "do-something", NULL);
|
|
*```
|
|
*
|
|
* Since: 44
|
|
*/
|
|
|
|
#ifdef HAVE_SYSPROF
|
|
#include <sysprof-capture.h>
|
|
|
|
typedef struct
|
|
{
|
|
int64_t begin_time;
|
|
gchar *name;
|
|
gchar *description;
|
|
} GsProfilerHead;
|
|
|
|
static inline void
|
|
gs_profiler_tracing_end (GsProfilerHead *head)
|
|
{
|
|
sysprof_collector_mark (head->begin_time,
|
|
SYSPROF_CAPTURE_CURRENT_TIME - head->begin_time,
|
|
"gnome-software",
|
|
head->name,
|
|
head->description);
|
|
|
|
g_clear_pointer (&head->name, g_free);
|
|
g_clear_pointer (&head->description, g_free);
|
|
}
|
|
static inline void
|
|
gs_profiler_auto_trace_end_helper (GsProfilerHead **head)
|
|
{
|
|
if (*head)
|
|
gs_profiler_tracing_end (*head);
|
|
}
|
|
|
|
#define GS_PROFILER_BEGIN_SCOPED_TAKE(Name, sysprof_name, sysprof_description) \
|
|
G_STMT_START { \
|
|
GsProfilerHead GsProfiler##Name; \
|
|
__attribute__((cleanup (gs_profiler_auto_trace_end_helper))) \
|
|
GsProfilerHead *ScopedGsProfilerTraceHead##Name = &GsProfiler##Name; \
|
|
GsProfiler##Name = (GsProfilerHead) { \
|
|
.begin_time = SYSPROF_CAPTURE_CURRENT_TIME, \
|
|
.name = sysprof_name, \
|
|
.description = sysprof_description, \
|
|
};
|
|
|
|
#define GS_PROFILER_BEGIN_SCOPED(Name, sysprof_name, sysprof_description) \
|
|
GS_PROFILER_BEGIN_SCOPED_TAKE (Name, g_strdup (sysprof_name), g_strdup (sysprof_description))
|
|
|
|
#define GS_PROFILER_END_SCOPED(Name) \
|
|
} G_STMT_END
|
|
|
|
#define GS_PROFILER_ADD_MARK_TAKE(Name, begin_time, sysprof_name, sysprof_description) \
|
|
G_STMT_START { \
|
|
g_autofree char *_owned_sysprof_name_##Name = sysprof_name; \
|
|
g_autofree char *_owned_sysprof_description_##Name = sysprof_description; \
|
|
sysprof_collector_mark (begin_time, \
|
|
SYSPROF_CAPTURE_CURRENT_TIME - begin_time, \
|
|
"gnome-software", \
|
|
_owned_sysprof_name_##Name, \
|
|
_owned_sysprof_description_##Name); \
|
|
} G_STMT_END
|
|
|
|
#define GS_PROFILER_ADD_MARK(Name, begin_time, sysprof_name, sysprof_description) \
|
|
GS_PROFILER_ADD_MARK_TAKE (Name, begin_time, g_strdup (sysprof_name), g_strdup (sysprof_description))
|
|
|
|
#else
|
|
|
|
#define GS_PROFILER_BEGIN_SCOPED_TAKE(Name, sysprof_name, sysprof_description) \
|
|
G_STMT_START {
|
|
#define GS_PROFILER_BEGIN_SCOPED(Name, sysprof_name, sysprof_description) \
|
|
G_STMT_START {
|
|
#define GS_PROFILER_END_SCOPED(Name) \
|
|
} G_STMT_END
|
|
#define GS_PROFILER_ADD_MARK_TAKE(Name, begin_time, sysprof_name, sysprof_description)
|
|
#define GS_PROFILER_ADD_MARK(Name, begin_time, sysprof_name, sysprof_description)
|
|
|
|
#endif
|