Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/tools/profiler/core/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 11 kB image not shown  

Quelle  ProfileBuffer.h   Sprache: C

 
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* 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 MOZ_PROFILE_BUFFER_H
#define MOZ_PROFILE_BUFFER_H

#include "GeckoProfiler.h"
#include "ProfileBufferEntry.h"

#include "mozilla/Maybe.h"
#include "mozilla/PowerOfTwo.h"
#include "mozilla/ProfileBufferChunkManagerSingle.h"
#include "mozilla/ProfileChunkedBuffer.h"

class ProcessStreamingContext;
class RunningTimes;

// Class storing most profiling data in a ProfileChunkedBuffer.
//
// This class is used as a queue of entries which, after construction, never
// allocates. This makes it safe to use in the profiler's "critical section".
class ProfileBuffer final {
 public:
  // ProfileBuffer constructor
  // @param aBuffer The in-session ProfileChunkedBuffer to use as buffer
  // manager.
  explicit ProfileBuffer(mozilla::ProfileChunkedBuffer& aBuffer);

  mozilla::ProfileChunkedBuffer& UnderlyingChunkedBuffer() const {
    return mEntries;
  }

  bool IsThreadSafe() const { return mEntries.IsThreadSafe(); }

  // Add |aEntry| to the buffer, ignoring what kind of entry it is.
  uint64_t AddEntry(const ProfileBufferEntry& aEntry);

  // Add to the buffer a sample start (ThreadId) entry for aThreadId.
  // Returns the position of the entry.
  uint64_t AddThreadIdEntry(ProfilerThreadId aThreadId);

  void CollectCodeLocation(
      const char* aLabel, const char* aStr, uint32_t aFrameFlags,
      uint64_t aInnerWindowID, const mozilla::Maybe<uint32_t>& aLineNumber,
      const mozilla::Maybe<uint32_t>& aColumnNumber,
      const mozilla::Maybe<JS::ProfilingCategoryPair>& aCategoryPair);

  // Maximum size of a frameKey string that we'll handle.
  static const size_t kMaxFrameKeyLength = 512;

  // Add JIT frame information to aJITFrameInfo for any JitReturnAddr entries
  // that are currently in the buffer at or after aRangeStart, in samples
  // for the given thread.
  void AddJITInfoForRange(uint64_t aRangeStart, ProfilerThreadId aThreadId,
                          JSContext* aContext, JITFrameInfo& aJITFrameInfo,
                          mozilla::ProgressLogger aProgressLogger) const;

  // Stream JSON for samples in the buffer to aWriter, using the supplied
  // UniqueStacks object.
  // Only streams samples for the given thread ID and which were taken at or
  // after aSinceTime. If ID is 0, ignore the stored thread ID; this should only
  // be used when the buffer contains only one sample.
  // aUniqueStacks needs to contain information about any JIT frames that we
  // might encounter in the buffer, before this method is called. In other
  // words, you need to have called AddJITInfoForRange for every range that
  // might contain JIT frame information before calling this method.
  // Return the thread ID of the streamed sample(s), or 0.
  ProfilerThreadId StreamSamplesToJSON(
      SpliceableJSONWriter& aWriter, ProfilerThreadId aThreadId,
      double aSinceTime, UniqueStacks& aUniqueStacks,
      mozilla::ProgressLogger aProgressLogger) const;

  void StreamMarkersToJSON(SpliceableJSONWriter& aWriter,
                           ProfilerThreadId aThreadId,
                           const mozilla::TimeStamp& aProcessStartTime,
                           double aSinceTime, UniqueStacks& aUniqueStacks,
                           mozilla::ProgressLogger aProgressLogger) const;

  // Stream samples and markers from all threads that `aProcessStreamingContext`
  // accepts.
  void StreamSamplesAndMarkersToJSON(
      ProcessStreamingContext& aProcessStreamingContext,
      mozilla::ProgressLogger aProgressLogger) const;

  void StreamPausedRangesToJSON(SpliceableJSONWriter& aWriter,
                                double aSinceTime,
                                mozilla::ProgressLogger aProgressLogger) const;
  void StreamProfilerOverheadToJSON(
      SpliceableJSONWriter& aWriter,
      const mozilla::TimeStamp& aProcessStartTime, double aSinceTime,
      mozilla::ProgressLogger aProgressLogger) const;
  void StreamCountersToJSON(SpliceableJSONWriter& aWriter,
                            const mozilla::TimeStamp& aProcessStartTime,
                            double aSinceTime,
                            mozilla::ProgressLogger aProgressLogger) const;

  // Find (via |aLastSample|) the most recent sample for the thread denoted by
  // |aThreadId| and clone it, patching in the current time as appropriate.
  // Mutate |aLastSample| to point to the newly inserted sample.
  // Returns whether duplication was successful.
  bool DuplicateLastSample(ProfilerThreadId aThreadId, double aSampleTimeMs,
                           mozilla::Maybe<uint64_t>& aLastSample,
                           const RunningTimes& aRunningTimes);

  void DiscardSamplesBeforeTime(double aTime);

  // Read an entry in the buffer.
  ProfileBufferEntry GetEntry(uint64_t aPosition) const {
    return mEntries.ReadAt(
        mozilla::ProfileBufferBlockIndex::CreateFromProfileBufferIndex(
            aPosition),
        [&](mozilla::Maybe<mozilla::ProfileBufferEntryReader>&& aMER) {
          ProfileBufferEntry entry;
          if (aMER.isSome()) {
            if (aMER->CurrentBlockIndex().ConvertToProfileBufferIndex() ==
                aPosition) {
              // If we're here, it means `aPosition` pointed at a valid block.
              MOZ_RELEASE_ASSERT(aMER->RemainingBytes() <= sizeof(entry));
              aMER->ReadBytes(&entry, aMER->RemainingBytes());
            } else {
              // EntryReader at the wrong position, pretend to have read
              // everything.
              aMER->SetRemainingBytes(0);
            }
          }
          return entry;
        });
  }

  size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;
  size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const;

  void CollectOverheadStats(double aSamplingTimeMs,
                            mozilla::TimeDuration aLocking,
                            mozilla::TimeDuration aCleaning,
                            mozilla::TimeDuration aCounters,
                            mozilla::TimeDuration aThreads);

  ProfilerBufferInfo GetProfilerBufferInfo() const;

 private:
  // Add |aEntry| to the provided ProfileChunkedBuffer.
  // `static` because it may be used to add an entry to a `ProfileChunkedBuffer`
  // that is not attached to a `ProfileBuffer`.
  static mozilla::ProfileBufferBlockIndex AddEntry(
      mozilla::ProfileChunkedBuffer& aProfileChunkedBuffer,
      const ProfileBufferEntry& aEntry);

  // Add a sample start (ThreadId) entry for aThreadId to the provided
  // ProfileChunkedBuffer. Returns the position of the entry.
  // `static` because it may be used to add an entry to a `ProfileChunkedBuffer`
  // that is not attached to a `ProfileBuffer`.
  static mozilla::ProfileBufferBlockIndex AddThreadIdEntry(
      mozilla::ProfileChunkedBuffer& aProfileChunkedBuffer,
      ProfilerThreadId aThreadId);

  // The storage in which this ProfileBuffer stores its entries.
  mozilla::ProfileChunkedBuffer& mEntries;

 public:
  // `BufferRangeStart()` and `BufferRangeEnd()` return `uint64_t` values
  // corresponding to the first entry and past the last entry stored in
  // `mEntries`.
  //
  // The returned values are not guaranteed to be stable, because other threads
  // may also be accessing the buffer concurrently. But they will always
  // increase, and can therefore give an indication of how far these values have
  // *at least* reached. In particular:
  // - Entries whose index is strictly less that `BufferRangeStart()` have been
  //   discarded by now, so any related data may also be safely discarded.
  // - It is safe to try and read entries at any index strictly less than
  //   `BufferRangeEnd()` -- but note that these reads may fail by the time you
  //   request them, as old entries get overwritten by new ones.
  uint64_t BufferRangeStart() const { return mEntries.GetState().mRangeStart; }
  uint64_t BufferRangeEnd() const { return mEntries.GetState().mRangeEnd; }

 private:
  // Single pre-allocated chunk (to avoid spurious mallocs), used when:
  // - Duplicating sleeping stacks (hence scExpectedMaximumStackSize).
  // - Adding JIT info.
  // - Streaming stacks to JSON.
  // Mutable because it's accessed from non-multithreaded const methods.
  mutable mozilla::Maybe<mozilla::ProfileBufferChunkManagerSingle>
      mMaybeWorkerChunkManager;
  mozilla::ProfileBufferChunkManagerSingle& WorkerChunkManager() const {
    if (mMaybeWorkerChunkManager.isNothing()) {
      // Only actually allocate it on first use. (Some ProfileBuffers are
      // temporary and don't actually need this.)
      mMaybeWorkerChunkManager.emplace(
          mozilla::ProfileBufferChunk::SizeofChunkMetadata() +
          mozilla::ProfileBufferChunkManager::scExpectedMaximumStackSize);
    }
    return *mMaybeWorkerChunkManager;
  }

#ifdef MOZ_EXECUTION_TRACING
  template <typename GetStreamingParametersForThreadCallback>
  void MaybeStreamExecutionTraceToJSON(
      GetStreamingParametersForThreadCallback&&
          aGetStreamingParametersForThreadCallback,
      double aSinceTime) const;
#endif

  // GetStreamingParametersForThreadCallback:
  //   (ProfilerThreadId) -> Maybe<StreamingParametersForThread>
  template <typename GetStreamingParametersForThreadCallback>
  ProfilerThreadId DoStreamSamplesAndMarkersToJSON(
      mozilla::FailureLatch& aFailureLatch,
      GetStreamingParametersForThreadCallback&&
          aGetStreamingParametersForThreadCallback,
      double aSinceTime, ProcessStreamingContext* aStreamingContextForMarkers,
      mozilla::ProgressLogger aProgressLogger) const;

  double mFirstSamplingTimeUs = 0.0;
  double mLastSamplingTimeUs = 0.0;
  ProfilerStats mIntervalsUs;
  ProfilerStats mOverheadsUs;
  ProfilerStats mLockingsUs;
  ProfilerStats mCleaningsUs;
  ProfilerStats mCountersUs;
  ProfilerStats mThreadsUs;
};

/**
 * Helper type used to implement ProfilerStackCollector. This type is used as
 * the collector for MergeStacks by ProfileBuffer. It holds a reference to the
 * buffer, as well as additional feature flags which are needed to control the
 * data collection strategy
 */

class ProfileBufferCollector final : public ProfilerStackCollector {
 public:
  ProfileBufferCollector(ProfileBuffer& aBuf, uint64_t aSamplePos,
                         uint64_t aBufferRangeStart)
      : mBuf(aBuf),
        mSamplePositionInBuffer(aSamplePos),
        mBufferRangeStart(aBufferRangeStart) {
    MOZ_ASSERT(
        mSamplePositionInBuffer >= mBufferRangeStart,
        "The sample position should always be after the buffer range start");
  }

  // Position at which the sample starts in the profiler buffer (which may be
  // different from the buffer in which the sample data is collected here).
  mozilla::Maybe<uint64_t> SamplePositionInBuffer() override {
    return mozilla::Some(mSamplePositionInBuffer);
  }

  // Profiler buffer's range start (which may be different from the buffer in
  // which the sample data is collected here).
  mozilla::Maybe<uint64_t> BufferRangeStart() override {
    return mozilla::Some(mBufferRangeStart);
  }

  virtual void CollectNativeLeafAddr(void* aAddr) override;
  virtual void CollectJitReturnAddr(void* aAddr) override;
  virtual void CollectWasmFrame(JS::ProfilingCategoryPair aCategory,
                                const char* aLabel) override;
  virtual void CollectProfilingStackFrame(
      const js::ProfilingStackFrame& aFrame) override;

 private:
  ProfileBuffer& mBuf;
  uint64_t mSamplePositionInBuffer;
  uint64_t mBufferRangeStart;
};

#endif

98%


¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.