PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/react/performance/timeline
Просмотр файла: PerformanceEntryReporter.cpp
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include "PerformanceEntryReporter.h"
#include <jsinspector-modern/tracing/PerformanceTracer.h>
#include <react/featureflags/ReactNativeFeatureFlags.h>
#include <react/timing/primitives.h>
#include <reactperflogger/ReactPerfettoLogger.h>
#ifdef WITH_PERFETTO
#include <reactperflogger/ReactPerfetto.h>
#endif
#include <variant>
namespace facebook::react {
namespace {
std::vector<PerformanceEntryType> getSupportedEntryTypesInternal() {
std::vector<PerformanceEntryType> supportedEntryTypes{
PerformanceEntryType::MARK,
PerformanceEntryType::MEASURE,
PerformanceEntryType::EVENT,
PerformanceEntryType::LONGTASK,
};
if (ReactNativeFeatureFlags::enableResourceTimingAPI()) {
supportedEntryTypes.emplace_back(PerformanceEntryType::RESOURCE);
}
return supportedEntryTypes;
}
#if defined(__clang__)
#define NO_DESTROY [[clang::no_destroy]]
#else
#define NO_DESTROY
#endif
NO_DESTROY const std::string TRACK_PREFIX = "Track:";
std::tuple<std::optional<std::string>, std::string_view> parseTrackName(
const std::string& name) {
// Until there's a standard way to pass through track information, parse it
// manually, e.g., "Track:Foo:Event name"
// https://github.com/w3c/user-timing/issues/109
std::optional<std::string> trackName;
std::string_view eventName(name);
if (name.starts_with(TRACK_PREFIX)) {
const auto trackNameDelimiter = name.find(':', TRACK_PREFIX.length());
if (trackNameDelimiter != std::string::npos) {
trackName = name.substr(
TRACK_PREFIX.length(), trackNameDelimiter - TRACK_PREFIX.length());
eventName = std::string_view(name).substr(trackNameDelimiter + 1);
}
}
return std::make_tuple(trackName, eventName);
}
} // namespace
std::shared_ptr<PerformanceEntryReporter>&
PerformanceEntryReporter::getInstance() {
static auto instance = std::make_shared<PerformanceEntryReporter>();
return instance;
}
PerformanceEntryReporter::PerformanceEntryReporter()
: observerRegistry_(std::make_unique<PerformanceObserverRegistry>()) {
#ifdef WITH_PERFETTO
initializePerfetto();
#endif
}
HighResTimeStamp PerformanceEntryReporter::getCurrentTimeStamp() const {
return timeStampProvider_ != nullptr ? timeStampProvider_()
: HighResTimeStamp::now();
}
std::vector<PerformanceEntryType>
PerformanceEntryReporter::getSupportedEntryTypes() {
static std::vector<PerformanceEntryType> supportedEntries =
getSupportedEntryTypesInternal();
return supportedEntries;
}
uint32_t PerformanceEntryReporter::getDroppedEntriesCount(
PerformanceEntryType entryType) const noexcept {
std::shared_lock lock(buffersMutex_);
return (uint32_t)getBuffer(entryType).droppedEntriesCount;
}
std::vector<PerformanceEntry> PerformanceEntryReporter::getEntries() const {
std::vector<PerformanceEntry> entries;
getEntries(entries);
return entries;
}
void PerformanceEntryReporter::getEntries(
std::vector<PerformanceEntry>& dest) const {
std::shared_lock lock(buffersMutex_);
for (auto entryType : getSupportedEntryTypes()) {
getBuffer(entryType).getEntries(dest);
}
}
std::vector<PerformanceEntry> PerformanceEntryReporter::getEntries(
PerformanceEntryType entryType) const {
std::vector<PerformanceEntry> dest;
getEntries(dest, entryType);
return dest;
}
void PerformanceEntryReporter::getEntries(
std::vector<PerformanceEntry>& dest,
PerformanceEntryType entryType) const {
std::shared_lock lock(buffersMutex_);
getBuffer(entryType).getEntries(dest);
}
std::vector<PerformanceEntry> PerformanceEntryReporter::getEntries(
PerformanceEntryType entryType,
const std::string& entryName) const {
std::vector<PerformanceEntry> entries;
getEntries(entries, entryType, entryName);
return entries;
}
void PerformanceEntryReporter::getEntries(
std::vector<PerformanceEntry>& dest,
PerformanceEntryType entryType,
const std::string& entryName) const {
std::shared_lock lock(buffersMutex_);
getBuffer(entryType).getEntries(dest, entryName);
}
void PerformanceEntryReporter::clearEntries() {
std::unique_lock lock(buffersMutex_);
for (auto entryType : getSupportedEntryTypes()) {
getBufferRef(entryType).clear();
}
}
void PerformanceEntryReporter::clearEntries(PerformanceEntryType entryType) {
std::unique_lock lock(buffersMutex_);
getBufferRef(entryType).clear();
}
void PerformanceEntryReporter::clearEntries(
PerformanceEntryType entryType,
const std::string& entryName) {
std::unique_lock lock(buffersMutex_);
getBufferRef(entryType).clear(entryName);
}
PerformanceMark PerformanceEntryReporter::reportMark(
const std::string& name,
const std::optional<HighResTimeStamp>& startTime) {
// Resolve timings
auto startTimeVal = startTime ? *startTime : getCurrentTimeStamp();
const auto entry = PerformanceMark{{.name = name, .startTime = startTimeVal}};
traceMark(entry);
// Add to buffers & notify observers
{
std::unique_lock lock(buffersMutex_);
markBuffer_.add(entry);
}
observerRegistry_->queuePerformanceEntry(entry);
return entry;
}
PerformanceMeasure PerformanceEntryReporter::reportMeasure(
const std::string& name,
HighResTimeStamp startTime,
HighResTimeStamp endTime,
const std::optional<jsinspector_modern::DevToolsTrackEntryPayload>&
trackMetadata) {
HighResDuration duration = endTime - startTime;
const auto entry = PerformanceMeasure{
{.name = std::string(name),
.startTime = startTime,
.duration = duration}};
traceMeasure(entry);
// Add to buffers & notify observers
{
std::unique_lock lock(buffersMutex_);
measureBuffer_.add(entry);
}
observerRegistry_->queuePerformanceEntry(entry);
return entry;
}
std::optional<HighResTimeStamp> PerformanceEntryReporter::getMarkTime(
const std::string& markName) const {
std::shared_lock lock(buffersMutex_);
if (auto it = markBuffer_.find(markName); it) {
return std::visit(
[](const auto& entryData) { return entryData.startTime; }, *it);
}
return std::nullopt;
}
void PerformanceEntryReporter::reportEvent(
std::string name,
HighResTimeStamp startTime,
HighResDuration duration,
HighResTimeStamp processingStart,
HighResTimeStamp processingEnd,
uint32_t interactionId) {
eventCounts_[name]++;
if (duration < eventBuffer_.durationThreshold) {
// The entries duration is lower than the desired reporting threshold,
// skip
return;
}
const auto entry = PerformanceEventTiming{
{.name = std::move(name), .startTime = startTime, .duration = duration},
processingStart,
processingEnd,
interactionId};
{
std::unique_lock lock(buffersMutex_);
eventBuffer_.add(entry);
}
// TODO(T198982346): Log interaction events to jsinspector_modern
observerRegistry_->queuePerformanceEntry(entry);
}
void PerformanceEntryReporter::reportLongTask(
HighResTimeStamp startTime,
HighResDuration duration) {
const auto entry = PerformanceLongTaskTiming{
{.name = std::string{"self"},
.startTime = startTime,
.duration = duration}};
{
std::unique_lock lock(buffersMutex_);
longTaskBuffer_.add(entry);
}
observerRegistry_->queuePerformanceEntry(entry);
}
PerformanceResourceTiming PerformanceEntryReporter::reportResourceTiming(
const std::string& url,
HighResTimeStamp fetchStart,
HighResTimeStamp requestStart,
std::optional<HighResTimeStamp> connectStart,
std::optional<HighResTimeStamp> connectEnd,
HighResTimeStamp responseStart,
HighResTimeStamp responseEnd,
const std::optional<int>& responseStatus) {
const auto entry = PerformanceResourceTiming{
{.name = url, .startTime = fetchStart},
fetchStart,
requestStart,
connectStart,
connectEnd,
responseStart,
responseEnd,
responseStatus,
};
// Add to buffers & notify observers
{
std::unique_lock lock(buffersMutex_);
resourceTimingBuffer_.add(entry);
}
observerRegistry_->queuePerformanceEntry(entry);
return entry;
}
void PerformanceEntryReporter::traceMark(const PerformanceMark& entry) const {
auto& performanceTracer =
jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (ReactPerfettoLogger::isTracing() || performanceTracer.isTracing()) {
auto [trackName, eventName] = parseTrackName(entry.name);
if (performanceTracer.isTracing()) {
performanceTracer.reportMark(entry.name, entry.startTime);
}
if (ReactPerfettoLogger::isTracing()) {
ReactPerfettoLogger::mark(eventName, entry.startTime, trackName);
}
}
}
void PerformanceEntryReporter::traceMeasure(
const PerformanceMeasure& entry) const {
auto& performanceTracer =
jsinspector_modern::tracing::PerformanceTracer::getInstance();
if (performanceTracer.isTracing() || ReactPerfettoLogger::isTracing()) {
auto [trackName, eventName] = parseTrackName(entry.name);
if (performanceTracer.isTracing()) {
std::optional<jsinspector_modern::DevToolsTrackEntryPayload>
trackMetadata;
if (trackName.has_value()) {
trackMetadata = {.track = trackName.value()};
}
performanceTracer.reportMeasure(
eventName, entry.startTime, entry.duration, trackMetadata);
}
if (ReactPerfettoLogger::isTracing()) {
ReactPerfettoLogger::measure(
eventName,
entry.startTime,
entry.startTime + entry.duration,
trackName);
}
}
}
} // namespace facebook::react
Выполнить команду
Для локальной разработки. Не используйте в интернете!