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

Quelle  ProfilerIOInterposeObserver.cpp   Sprache: C

 
/* 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/. */


#include "ProfilerIOInterposeObserver.h"
#include "GeckoProfiler.h"

using namespace mozilla;

/* static */
ProfilerIOInterposeObserver& ProfilerIOInterposeObserver::GetInstance() {
  static ProfilerIOInterposeObserver sProfilerIOInterposeObserver;
  return sProfilerIOInterposeObserver;
}

namespace geckoprofiler::markers {
struct FileIOMarker {
  static constexpr Span<const char> MarkerTypeName() {
    return MakeStringSpan("FileIO");
  }
  static void StreamJSONMarkerData(baseprofiler::SpliceableJSONWriter& aWriter,
                                   const ProfilerString8View& aOperation,
                                   const ProfilerString8View& aSource,
                                   const ProfilerString8View& aFilename,
                                   MarkerThreadId aOperationThreadId) {
    aWriter.StringProperty("operation", aOperation);
    aWriter.StringProperty("source", aSource);
    if (aFilename.Length() != 0) {
      aWriter.StringProperty("filename", aFilename);
    }
    if (!aOperationThreadId.IsUnspecified()) {
      // Tech note: If `ToNumber()` returns a uint64_t, the conversion to
      // int64_t is "implementation-defined" before C++20. This is acceptable
      // here, because this is a one-way conversion to a unique identifier
      // that's used to visually separate data by thread on the front-end.
      aWriter.IntProperty(
          "threadId",
          static_cast<int64_t>(aOperationThreadId.ThreadId().ToNumber()));
    }
  }
  static MarkerSchema MarkerTypeDisplay() {
    using MS = MarkerSchema;
    MS schema{MS::Location::MarkerChart, MS::Location::MarkerTable,
              MS::Location::TimelineFileIO};
    schema.AddKeyLabelFormatSearchable("operation""Operation",
                                       MS::Format::String,
                                       MS::Searchable::Searchable);
    schema.AddKeyLabelFormatSearchable("source""Source", MS::Format::String,
                                       MS::Searchable::Searchable);
    schema.AddKeyLabelFormatSearchable("filename""Filename",
                                       MS::Format::FilePath,
                                       MS::Searchable::Searchable);
    schema.AddKeyLabelFormatSearchable("threadId""Thread ID",
                                       MS::Format::String,
                                       MS::Searchable::Searchable);
    return schema;
  }
};
}  // namespace geckoprofiler::markers

static auto GetFilename(IOInterposeObserver::Observation& aObservation) {
  AUTO_PROFILER_STATS(IO_filename);
  constexpr size_t scExpectedMaxFilename = 512;
  nsAutoStringN<scExpectedMaxFilename> filename16;
  aObservation.Filename(filename16);
  nsAutoCStringN<scExpectedMaxFilename> filename8;
  if (!filename16.IsEmpty()) {
    CopyUTF16toUTF8(filename16, filename8);
  }
  return filename8;
}

void ProfilerIOInterposeObserver::Observe(Observation& aObservation) {
  if (profiler_is_locked_on_current_thread()) {
    // Don't observe I/Os originating from the profiler itself (when internally
    // locked) to avoid deadlocks when calling profiler functions.
    AUTO_PROFILER_STATS(IO_profiler_locked);
    return;
  }

  Maybe<uint32_t> maybeFeatures = profiler_features_if_active_and_unpaused();
  if (maybeFeatures.isNothing()) {
    return;
  }
  uint32_t features = *maybeFeatures;

  if (!profiler_thread_is_being_profiled_for_markers(
          profiler_main_thread_id()) &&
      !profiler_thread_is_being_profiled_for_markers()) {
    return;
  }

  AUTO_PROFILER_LABEL("ProfilerIOInterposeObserver", PROFILER);
  if (IsMainThread()) {
    // This is the main thread.
    // Capture a marker if any "IO" feature is on.
    // If it's not being profiled, we have nowhere to store FileIO markers.
    if (!profiler_thread_is_being_profiled_for_markers() ||
        !(features & ProfilerFeature::MainThreadIO)) {
      return;
    }
    AUTO_PROFILER_STATS(IO_MT);
    nsAutoCString type{aObservation.FileType()};
    type.AppendLiteral("IO");

    // Store the marker in the current thread.
    PROFILER_MARKER(
        type, OTHER,
        MarkerOptions(
            MarkerTiming::Interval(aObservation.Start(), aObservation.End()),
            MarkerStack::Capture()),
        FileIOMarker,
        // aOperation
        ProfilerString8View::WrapNullTerminatedString(
            aObservation.ObservedOperationString()),
        // aSource
        ProfilerString8View::WrapNullTerminatedString(aObservation.Reference()),
        // aFilename
        GetFilename(aObservation),
        // aOperationThreadId - Do not include a thread ID, as it's the same as
        // the markers. Only include this field when the marker is being sent
        // from another thread.
        MarkerThreadId{});

  } else if (profiler_thread_is_being_profiled_for_markers()) {
    // This is a non-main thread that is being profiled.
    if (!(features & ProfilerFeature::FileIO)) {
      return;
    }
    AUTO_PROFILER_STATS(IO_off_MT);

    nsAutoCString type{aObservation.FileType()};
    type.AppendLiteral("IO");

    // Share a backtrace between the marker on this thread, and the marker on
    // the main thread.
    UniquePtr<ProfileChunkedBuffer> backtrace = profiler_capture_backtrace();

    // Store the marker in the current thread.
    PROFILER_MARKER(
        type, OTHER,
        MarkerOptions(
            MarkerTiming::Interval(aObservation.Start(), aObservation.End()),
            backtrace ? MarkerStack::UseBacktrace(*backtrace)
                      : MarkerStack::NoStack()),
        FileIOMarker,
        // aOperation
        ProfilerString8View::WrapNullTerminatedString(
            aObservation.ObservedOperationString()),
        // aSource
        ProfilerString8View::WrapNullTerminatedString(aObservation.Reference()),
        // aFilename
        GetFilename(aObservation),
        // aOperationThreadId - Do not include a thread ID, as it's the same as
        // the markers. Only include this field when the marker is being sent
        // from another thread.
        MarkerThreadId{});

    // Store the marker in the main thread as well, with a distinct marker name
    // and thread id.
    type.AppendLiteral(" (non-main thread)");
    PROFILER_MARKER(
        type, OTHER,
        MarkerOptions(
            MarkerTiming::Interval(aObservation.Start(), aObservation.End()),
            backtrace ? MarkerStack::UseBacktrace(*backtrace)
                      : MarkerStack::NoStack(),
            // This is the important piece that changed.
            // It will send a marker to the main thread.
            MarkerThreadId::MainThread()),
        FileIOMarker,
        // aOperation
        ProfilerString8View::WrapNullTerminatedString(
            aObservation.ObservedOperationString()),
        // aSource
        ProfilerString8View::WrapNullTerminatedString(aObservation.Reference()),
        // aFilename
        GetFilename(aObservation),
        // aOperationThreadId - Include the thread ID in the payload.
        MarkerThreadId::CurrentThread());

  } else {
    // This is a thread that is not being profiled. We still want to capture
    // file I/Os (to the main thread) if the "FileIOAll" feature is on.
    if (!(features & ProfilerFeature::FileIOAll)) {
      return;
    }
    AUTO_PROFILER_STATS(IO_other);
    nsAutoCString type{aObservation.FileType()};
    if (profiler_is_active_and_thread_is_registered()) {
      type.AppendLiteral("IO (non-profiled thread)");
    } else {
      type.AppendLiteral("IO (unregistered thread)");
    }

    // Only store this marker on the main thread, as this thread was not being
    // profiled.
    PROFILER_MARKER(
        type, OTHER,
        MarkerOptions(
            MarkerTiming::Interval(aObservation.Start(), aObservation.End()),
            MarkerStack::Capture(),
            // Store this marker on the main thread.
            MarkerThreadId::MainThread()),
        FileIOMarker,
        // aOperation
        ProfilerString8View::WrapNullTerminatedString(
            aObservation.ObservedOperationString()),
        // aSource
        ProfilerString8View::WrapNullTerminatedString(aObservation.Reference()),
        // aFilename
        GetFilename(aObservation),
        // aOperationThreadId - Note which thread this marker is coming from.
        MarkerThreadId::CurrentThread());
  }
}

Messung V0.5
C=85 H=95 G=90

¤ 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 und die Messung sind noch experimentell.