• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  */
83 void
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  */
guint(g_trace_define_int64_counter)119 guint
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  */
161 void
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