| /* |
| * Copyright © 2020 Endless Mobile, Inc. |
| * |
| * SPDX-License-Identifier: LGPL-2.1-or-later |
| * |
| * 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 */ |
| } |
| |
| /* |
| * 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 |
| } |