1/*
2 * Copyright © 2020 Endless Mobile, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
16 *
17 * Author: Philip Withnall <withnall@endlessm.com>
18 */
19
20/*
21 * SECTION:trace
22 * @Title: Performance tracing
23 * @Short_description: Functions for measuring and tracing performance
24 *
25 * The performance tracing functions allow for the performance of code using
26 * GLib to be measured by passing metrics from the current process to an
27 * external measurement process such as `sysprof-cli` or `sysprofd`.
28 *
29 * They are designed to execute quickly, especially in the common case where no
30 * measurement process is connected. They are guaranteed to not block the caller
31 * and are guaranteed to have zero runtime cost if tracing support is disabled
32 * at configure time.
33 *
34 * Tracing information can be provided as ‘marks’ with a start time and
35 * duration; or as marks with a start time and no duration. Marks with a
36 * duration are intended to show the execution time of a piece of code. Marks
37 * with no duration are intended to show an instantaneous performance problem,
38 * such as an unexpectedly large allocation, or that a slow path has been taken
39 * in some code.
40 *
41 * |[<!-- language="C" -->
42 * gint64 begin_time_nsec G_GNUC_UNUSED;
43 *
44 * begin_time_nsec = G_TRACE_CURRENT_TIME;
45 *
46 * // some code which might take a while
47 *
48 * g_trace_mark (begin_time_nsec, G_TRACE_CURRENT_TIME - begin_time_nsec,
49 * "GLib", "GSource.dispatch",
50 * "%s ⇒ %s", g_source_get_name (source), need_destroy ? "destroy" : "keep");
51 * ]|
52 *
53 * The tracing API is currently internal to GLib.
54 *
55 * Since: 2.66
56 */
57
58#include "config.h"
59
60#include "gtrace-private.h"
61
62#include <stdarg.h>
63
64/*
65 * g_trace_mark:
66 * @begin_time_nsec: start time of the mark, as returned by %G_TRACE_CURRENT_TIME
67 * @duration_nsec: duration of the mark, in nanoseconds
68 * @group: name of the group for categorising this mark
69 * @name: name of the mark
70 * @message_format: format for the detailed message for the mark, in `printf()` format
71 * @...: arguments to substitute into @message_format; none of these should have
72 * side effects
73 *
74 * Add a mark to the trace, starting at @begin_time_nsec and having length
75 * @duration_nsec (which may be zero). The @group should typically be `GLib`,
76 * and the @name should concisely describe the call site.
77 *
78 * All of the arguments to this function must not have side effects, as the
79 * entire function call may be dropped if sysprof support is not available.
80 *
81 * Since: 2.66
82 */
83void
84(g_trace_mark) (gint64 begin_time_nsec,
85 gint64 duration_nsec,
86 const gchar *group,
87 const gchar *name,
88 const gchar *message_format,
89 ...)
90{
91#ifdef HAVE_SYSPROF
92 va_list args;
93
94 va_start (args, message_format);
95 sysprof_collector_mark_vprintf (begin_time_nsec, duration_nsec, group, name, message_format, args);
96 va_end (args);
97#endif /* HAVE_SYSPROF */
98}
99
100/*
101 * g_trace_define_int64_counter:
102 * @group: name of the group for categorising this counter
103 * @name: name of the counter
104 * @description: description for the counter
105 *
106 * Defines a new counter with integer values.
107 *
108 * The name should be unique within all counters defined with
109 * the same @group. The description will be shown in the sysprof UI.
110 *
111 * To add entries for this counter to a trace, use
112 * g_trace_set_int64_counter().
113 *
114 * Returns: ID of the counter, for use with g_trace_set_int64_counter(),
115 * guaranteed to never be zero
116 *
117 * Since: 2.68
118 */
119guint
120(g_trace_define_int64_counter) (const char *group,
121 const char *name,
122 const char *description)
123{
124#ifdef HAVE_SYSPROF
125 SysprofCaptureCounter counter;
126
127 counter.id = sysprof_collector_request_counters (1);
128
129 /* sysprof not enabled? */
130 if (counter.id == 0)
131 return (guint) -1;
132
133 counter.type = SYSPROF_CAPTURE_COUNTER_INT64;
134 counter.value.v64 = 0;
135 g_strlcpy (counter.category, group, sizeof counter.category);
136 g_strlcpy (counter.name, name, sizeof counter.name);
137 g_strlcpy (counter.description, description, sizeof counter.description);
138
139 sysprof_collector_define_counters (&counter, 1);
140
141 g_assert (counter.id != 0);
142
143 return counter.id;
144#else
145 return (guint) -1;
146#endif
147}
148
149/*
150 * g_trace_set_int64_counter:
151 * @id: ID of the counter
152 * @val: the value to set the counter to
153 *
154 * Adds a counter value to a trace.
155 *
156 * The ID must be obtained via g_trace_define_int64_counter()
157 * before using this function.
158 *
159 * Since: 2.68
160 */
161void
162(g_trace_set_int64_counter) (guint id,
163 gint64 val)
164{
165#ifdef HAVE_SYSPROF
166 SysprofCaptureCounterValue value;
167
168 g_return_if_fail (id != 0);
169
170 /* Ignore setting the counter if we failed to define it in the first place. */
171 if (id == (guint) -1)
172 return;
173
174 value.v64 = val;
175 sysprof_collector_set_counters (&id, &value, 1);
176#endif
177}
178

source code of gtk/subprojects/glib/glib/gtrace.c