(root)/
glib-2.79.0/
glib/
gtrace.c
       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  (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  }
      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  (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    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  (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  }