DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Implementation

Mercurial (9823cd4c602e)

VCS Links

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
 * You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef TRACING_H
#define TRACING_H

#include <algorithm>
#include <cstdint>
#include <cstdio>

#include "AsyncLogger.h"

#include "mozilla/Attributes.h"
#include "mozilla/UniquePtr.h"

#if defined(_WIN32)
#  include <process.h>
#  define getpid() _getpid()
#else
#  include <unistd.h>
#endif

#if defined(_MSC_VER)
// MSVC
#  define FUNCTION_SIGNATURE __FUNCSIG__
#elif defined(__GNUC__)
// gcc, clang
#  define FUNCTION_SIGNATURE __PRETTY_FUNCTION__
#endif

#ifdef TRACING
/* TRACE is for use in the real-time audio rendering thread.
 * It would be better to always pass in the thread id. However, the thread an
 * audio callback runs on can change when the underlying audio device change,
 * and also it seems to be called from a thread pool in a round-robin fashion
 * when audio remoting is activated, making the traces unreadable.
 * The thread on which the AudioCallbackDriver::DataCallback is to always
 * be thread 0, and the budget is set to always be thread 1. This allows
 * displaying those elements in two separate lanes.
 * The other thread have "normal" tid. Hashing allows being able to get a
 * string representation that is unique and guaranteed to be portable. */
#  define TRACE_AUDIO_CALLBACK() \
    AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), 0);
#  define TRACE_AUDIO_CALLBACK_BUDGET(aFrames, aSampleRate)             \
    AutoTracer budget(gMSGTraceLogger, "Real-time budget", getpid(), 1, \
                      AutoTracer::EventType::BUDGET, aFrames, aSampleRate);
#  define TRACE_AUDIO_CALLBACK_COMMENT(aFmt, ...)                      \
    AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), 0, \
                     AutoTracer::EventType::DURATION, aFmt, ##__VA_ARGS__);
#  define TRACE()                                      \
    AutoTracer trace(                                  \
        gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(), \
        std::hash<std::thread::id>{}(std::this_thread::get_id()));
#  define TRACE_COMMENT(aFmt, ...)                                             \
    AutoTracer trace(gMSGTraceLogger, FUNCTION_SIGNATURE, getpid(),            \
                     std::hash<std::thread::id>{}(std::this_thread::get_id()), \
                     AutoTracer::EventType::DURATION, aFmt, ##__VA_ARGS__);
#else
#  define TRACE_AUDIO_CALLBACK()
#  define TRACE_AUDIO_CALLBACK_BUDGET(aFrames, aSampleRate)
#  define TRACE_AUDIO_CALLBACK_COMMENT(aFmt, ...)
#  define TRACE()
#  define TRACE_COMMENT(aFmt, ...)
#endif

class MOZ_RAII AutoTracer {
 public:
  static const int32_t BUFFER_SIZE =
      mozilla::AsyncLogger::MAX_MESSAGE_LENGTH / 2;

  enum class EventType { DURATION, BUDGET };

  AutoTracer(mozilla::AsyncLogger& aLogger, const char* aLocation,
             uint64_t aPID, uint64_t aTID,
             EventType aEventType = EventType::DURATION,
             const char* aComment = nullptr);

  template <typename... Args>
  AutoTracer(mozilla::AsyncLogger& aLogger, const char* aLocation,
             uint64_t aPID, uint64_t aTID, EventType aEventType,
             const char* aFormat, Args... aArgs)
      : mLogger(aLogger),
        mLocation(aLocation),
        mComment(mBuffer),
        mEventType(aEventType),
        mPID(aPID),
        mTID(aTID) {
    MOZ_ASSERT(aEventType == EventType::DURATION);
    if (aLogger.Enabled()) {
      int32_t size = snprintf(mBuffer, BUFFER_SIZE, aFormat, aArgs...);
      size = std::min(size, BUFFER_SIZE - 1);
      mBuffer[size] = 0;
      PrintEvent(aLocation, "perf", mComment, TracingPhase::BEGIN, NowInUs(),
                 aPID, aTID);
    }
  }

  AutoTracer(mozilla::AsyncLogger& aLogger, const char* aLocation,
             uint64_t aPID, uint64_t aTID, EventType aEventType,
             uint64_t aFrames, uint64_t aSampleRate);

  ~AutoTracer();

 private:
  uint64_t NowInUs();

  enum class TracingPhase { BEGIN, END, COMPLETE };

  const char TRACING_PHASE_STRINGS[3] = {'B', 'E', 'X'};

  void PrintEvent(const char* aName, const char* aCategory,
                  const char* aComment, TracingPhase aPhase, uint64_t aTime,
                  uint64_t aPID, uint64_t aThread);

  void PrintBudget(const char* aName, const char* aCategory, uint64_t aDuration,
                   uint64_t aPID, uint64_t aThread, uint64_t aFrames,
                   uint64_t aSampleRate);

  // The logger to use. It musdt have a lifetime longer than the block an
  // instance of this class traces.
  mozilla::AsyncLogger& mLogger;
  // The location for this trace point, arbitrary string literal, often the
  // name of the calling function, with a static lifetime.
  const char* mLocation;
  // A comment for this trace point, abitrary string literal with a static
  // lifetime.
  const char* mComment;
  // A buffer used to hold string-formatted traces.
  char mBuffer[BUFFER_SIZE];
  // The event type, for now either a budget or a duration.
  const EventType mEventType;
  // The process ID of the calling process. Traces are grouped by PID in the
  // vizualizer.
  const uint64_t mPID;
  // The thread ID of the calling thread, will be displayed in a separate
  // section in the trace visualizer.
  const uint64_t mTID;
};

#if defined(_WIN32)
#  undef getpid
#endif

#endif /* TRACING_H */