2020-06-25 23:08:05 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2020 Endless Mobile, Inc.
|
|
|
|
|
*
|
2022-05-18 10:15:38 +02:00
|
|
|
|
* SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
|
*
|
2020-06-25 23:08:05 +02:00
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 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
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*
|
|
|
|
|
* Author: Philip Withnall <withnall@endlessm.com>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The performance tracing functions allow for the performance of code using
|
|
|
|
|
* GLib to be measured by passing metrics from the current process to an
|
|
|
|
|
* external measurement process such as `sysprof-cli` or `sysprofd`.
|
|
|
|
|
*
|
|
|
|
|
* They are designed to execute quickly, especially in the common case where no
|
|
|
|
|
* measurement process is connected. They are guaranteed to not block the caller
|
|
|
|
|
* and are guaranteed to have zero runtime cost if tracing support is disabled
|
|
|
|
|
* at configure time.
|
|
|
|
|
*
|
|
|
|
|
* Tracing information can be provided as ‘marks’ with a start time and
|
|
|
|
|
* duration; or as marks with a start time and no duration. Marks with a
|
|
|
|
|
* duration are intended to show the execution time of a piece of code. Marks
|
|
|
|
|
* with no duration are intended to show an instantaneous performance problem,
|
|
|
|
|
* such as an unexpectedly large allocation, or that a slow path has been taken
|
|
|
|
|
* in some code.
|
|
|
|
|
*
|
|
|
|
|
* |[<!-- language="C" -->
|
|
|
|
|
* gint64 begin_time_nsec G_GNUC_UNUSED;
|
|
|
|
|
*
|
|
|
|
|
* begin_time_nsec = G_TRACE_CURRENT_TIME;
|
|
|
|
|
*
|
|
|
|
|
* // some code which might take a while
|
|
|
|
|
*
|
|
|
|
|
* g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec,
|
|
|
|
|
* "GLib", "GSource.dispatch",
|
|
|
|
|
* "%s ⇒ %s", g_source_get_name (source), need_destroy ? "destroy" : "keep");
|
|
|
|
|
* ]|
|
|
|
|
|
*
|
|
|
|
|
* The tracing API is currently internal to GLib.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.66
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
|
|
#include "gtrace-private.h"
|
|
|
|
|
|
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* g_trace_mark:
|
|
|
|
|
* @begin_time_nsec: start time of the mark, as returned by %G_TRACE_CURRENT_TIME
|
|
|
|
|
* @duration_nsec: duration of the mark, in nanoseconds
|
|
|
|
|
* @group: name of the group for categorising this mark
|
|
|
|
|
* @name: name of the mark
|
|
|
|
|
* @message_format: format for the detailed message for the mark, in `printf()` format
|
|
|
|
|
* @...: arguments to substitute into @message_format; none of these should have
|
|
|
|
|
* side effects
|
|
|
|
|
*
|
|
|
|
|
* Add a mark to the trace, starting at @begin_time_nsec and having length
|
|
|
|
|
* @duration_nsec (which may be zero). The @group should typically be `GLib`,
|
|
|
|
|
* and the @name should concisely describe the call site.
|
|
|
|
|
*
|
|
|
|
|
* All of the arguments to this function must not have side effects, as the
|
|
|
|
|
* entire function call may be dropped if sysprof support is not available.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.66
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
(g_trace_mark) (gint64 begin_time_nsec,
|
|
|
|
|
gint64 duration_nsec,
|
|
|
|
|
const gchar *group,
|
|
|
|
|
const gchar *name,
|
|
|
|
|
const gchar *message_format,
|
|
|
|
|
...)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SYSPROF
|
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
|
|
va_start (args, message_format);
|
|
|
|
|
sysprof_collector_mark_vprintf (begin_time_nsec, duration_nsec, group, name, message_format, args);
|
|
|
|
|
va_end (args);
|
|
|
|
|
#endif /* HAVE_SYSPROF */
|
|
|
|
|
}
|
2020-08-21 17:48:40 +02:00
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* g_trace_define_int64_counter:
|
|
|
|
|
* @group: name of the group for categorising this counter
|
|
|
|
|
* @name: name of the counter
|
|
|
|
|
* @description: description for the counter
|
|
|
|
|
*
|
|
|
|
|
* Defines a new counter with integer values.
|
|
|
|
|
*
|
|
|
|
|
* The name should be unique within all counters defined with
|
|
|
|
|
* the same @group. The description will be shown in the sysprof UI.
|
|
|
|
|
*
|
|
|
|
|
* To add entries for this counter to a trace, use
|
|
|
|
|
* g_trace_set_int64_counter().
|
|
|
|
|
*
|
|
|
|
|
* Returns: ID of the counter, for use with g_trace_set_int64_counter(),
|
|
|
|
|
* guaranteed to never be zero
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.68
|
|
|
|
|
*/
|
|
|
|
|
guint
|
|
|
|
|
(g_trace_define_int64_counter) (const char *group,
|
|
|
|
|
const char *name,
|
|
|
|
|
const char *description)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SYSPROF
|
|
|
|
|
SysprofCaptureCounter counter;
|
|
|
|
|
|
|
|
|
|
counter.id = sysprof_collector_request_counters (1);
|
|
|
|
|
|
|
|
|
|
/* sysprof not enabled? */
|
|
|
|
|
if (counter.id == 0)
|
|
|
|
|
return (guint) -1;
|
|
|
|
|
|
|
|
|
|
counter.type = SYSPROF_CAPTURE_COUNTER_INT64;
|
|
|
|
|
counter.value.v64 = 0;
|
|
|
|
|
g_strlcpy (counter.category, group, sizeof counter.category);
|
|
|
|
|
g_strlcpy (counter.name, name, sizeof counter.name);
|
|
|
|
|
g_strlcpy (counter.description, description, sizeof counter.description);
|
|
|
|
|
|
|
|
|
|
sysprof_collector_define_counters (&counter, 1);
|
|
|
|
|
|
|
|
|
|
g_assert (counter.id != 0);
|
|
|
|
|
|
|
|
|
|
return counter.id;
|
|
|
|
|
#else
|
|
|
|
|
return (guint) -1;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* g_trace_set_int64_counter:
|
|
|
|
|
* @id: ID of the counter
|
|
|
|
|
* @val: the value to set the counter to
|
|
|
|
|
*
|
|
|
|
|
* Adds a counter value to a trace.
|
|
|
|
|
*
|
|
|
|
|
* The ID must be obtained via g_trace_define_int64_counter()
|
|
|
|
|
* before using this function.
|
|
|
|
|
*
|
|
|
|
|
* Since: 2.68
|
|
|
|
|
*/
|
|
|
|
|
void
|
|
|
|
|
(g_trace_set_int64_counter) (guint id,
|
|
|
|
|
gint64 val)
|
|
|
|
|
{
|
|
|
|
|
#ifdef HAVE_SYSPROF
|
|
|
|
|
SysprofCaptureCounterValue value;
|
|
|
|
|
|
|
|
|
|
g_return_if_fail (id != 0);
|
|
|
|
|
|
|
|
|
|
/* Ignore setting the counter if we failed to define it in the first place. */
|
|
|
|
|
if (id == (guint) -1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
value.v64 = val;
|
|
|
|
|
sysprof_collector_set_counters (&id, &value, 1);
|
|
|
|
|
#endif
|
|
|
|
|
}
|