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