PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/react/nativemodule/webperformance
Просмотр файла: NativePerformance.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 "NativePerformance.h"
#include <memory>
#include <unordered_map>
#include <variant>
#include <cxxreact/JSExecutor.h>
#include <cxxreact/ReactMarker.h>
#include <jsi/instrumentation.h>
#include <react/performance/timeline/PerformanceEntryReporter.h>
#include <react/performance/timeline/PerformanceObserver.h>
#include "NativePerformance.h"
#ifdef RN_DISABLE_OSS_PLUGIN_HEADER
#include "Plugins.h"
#endif
std::shared_ptr<facebook::react::TurboModule> NativePerformanceModuleProvider(
std::shared_ptr<facebook::react::CallInvoker> jsInvoker) {
return std::make_shared<facebook::react::NativePerformance>(
std::move(jsInvoker));
}
namespace facebook::react {
namespace {
class PerformanceObserverWrapper : public jsi::NativeState {
public:
explicit PerformanceObserverWrapper(
const std::shared_ptr<PerformanceObserver> observer)
: observer(observer) {}
const std::shared_ptr<PerformanceObserver> observer;
};
void sortEntries(std::vector<PerformanceEntry>& entries) {
return std::stable_sort(
entries.begin(), entries.end(), PerformanceEntrySorter{});
}
NativePerformanceEntry toNativePerformanceEntry(const PerformanceEntry& entry) {
auto nativeEntry = std::visit(
[](const auto& entryData) -> NativePerformanceEntry {
return {
.name = entryData.name,
.entryType = entryData.entryType,
.startTime = entryData.startTime,
.duration = entryData.duration,
};
},
entry);
if (std::holds_alternative<PerformanceEventTiming>(entry)) {
auto eventEntry = std::get<PerformanceEventTiming>(entry);
nativeEntry.processingStart = eventEntry.processingStart;
nativeEntry.processingEnd = eventEntry.processingEnd;
nativeEntry.interactionId = eventEntry.interactionId;
}
if (std::holds_alternative<PerformanceResourceTiming>(entry)) {
auto resourceEntry = std::get<PerformanceResourceTiming>(entry);
nativeEntry.fetchStart = resourceEntry.fetchStart;
nativeEntry.requestStart = resourceEntry.requestStart;
nativeEntry.connectStart = resourceEntry.connectStart;
nativeEntry.connectEnd = resourceEntry.connectEnd;
nativeEntry.responseStart = resourceEntry.responseStart;
nativeEntry.responseEnd = resourceEntry.responseEnd;
nativeEntry.responseStatus = resourceEntry.responseStatus;
}
return nativeEntry;
}
std::vector<NativePerformanceEntry> toNativePerformanceEntries(
std::vector<PerformanceEntry>& entries) {
std::vector<NativePerformanceEntry> result;
result.reserve(entries.size());
for (auto& entry : entries) {
result.emplace_back(toNativePerformanceEntry(entry));
}
return result;
}
const std::array<PerformanceEntryType, 2> ENTRY_TYPES_AVAILABLE_FROM_TIMELINE{
{PerformanceEntryType::MARK, PerformanceEntryType::MEASURE}};
bool isAvailableFromTimeline(PerformanceEntryType entryType) {
return entryType == PerformanceEntryType::MARK ||
entryType == PerformanceEntryType::MEASURE;
}
std::shared_ptr<PerformanceObserver> tryGetObserver(
jsi::Runtime& rt,
jsi::Object& observerObj) {
if (!observerObj.hasNativeState(rt)) {
return nullptr;
}
auto observerWrapper = std::dynamic_pointer_cast<PerformanceObserverWrapper>(
observerObj.getNativeState(rt));
return observerWrapper ? observerWrapper->observer : nullptr;
}
} // namespace
NativePerformance::NativePerformance(std::shared_ptr<CallInvoker> jsInvoker)
: NativePerformanceCxxSpec(std::move(jsInvoker)) {}
HighResTimeStamp NativePerformance::now(jsi::Runtime& /*rt*/) {
return HighResTimeStamp::now();
}
HighResTimeStamp NativePerformance::markWithResult(
jsi::Runtime& rt,
std::string name,
std::optional<HighResTimeStamp> startTime) {
auto entry =
PerformanceEntryReporter::getInstance()->reportMark(name, startTime);
return entry.startTime;
}
std::tuple<HighResTimeStamp, HighResDuration>
NativePerformance::measureWithResult(
jsi::Runtime& runtime,
std::string name,
HighResTimeStamp startTime,
HighResTimeStamp endTime,
std::optional<HighResDuration> duration,
std::optional<std::string> startMark,
std::optional<std::string> endMark) {
auto reporter = PerformanceEntryReporter::getInstance();
HighResTimeStamp startTimeValue = startTime;
// If the start time mark name is specified, it takes precedence over the
// startTime parameter, which can be set to 0 by default from JavaScript.
if (startMark) {
if (auto startMarkBufferedTime = reporter->getMarkTime(*startMark)) {
startTimeValue = *startMarkBufferedTime;
} else {
throw jsi::JSError(
runtime, "The mark '" + *startMark + "' does not exist.");
}
}
HighResTimeStamp endTimeValue = endTime;
// If the end time mark name is specified, it takes precedence over the
// startTime parameter, which can be set to 0 by default from JavaScript.
if (endMark) {
if (auto endMarkBufferedTime = reporter->getMarkTime(*endMark)) {
endTimeValue = *endMarkBufferedTime;
} else {
throw jsi::JSError(
runtime, "The mark '" + *endMark + "' does not exist.");
}
} else if (duration) {
endTimeValue = startTimeValue + *duration;
} else if (endTimeValue < startTimeValue) {
// The end time is not specified, take the current time, according to the
// standard
endTimeValue = reporter->getCurrentTimeStamp();
}
auto entry = reporter->reportMeasure(name, startTime, endTime);
return std::tuple{entry.startTime, entry.duration};
}
void NativePerformance::clearMarks(
jsi::Runtime& /*rt*/,
std::optional<std::string> entryName) {
if (entryName) {
PerformanceEntryReporter::getInstance()->clearEntries(
PerformanceEntryType::MARK, *entryName);
} else {
PerformanceEntryReporter::getInstance()->clearEntries(
PerformanceEntryType::MARK);
}
}
void NativePerformance::clearMeasures(
jsi::Runtime& /*rt*/,
std::optional<std::string> entryName) {
if (entryName) {
PerformanceEntryReporter::getInstance()->clearEntries(
PerformanceEntryType::MEASURE, *entryName);
} else {
PerformanceEntryReporter::getInstance()->clearEntries(
PerformanceEntryType::MEASURE);
}
}
std::vector<NativePerformanceEntry> NativePerformance::getEntries(
jsi::Runtime& /*rt*/) {
std::vector<PerformanceEntry> entries;
for (auto entryType : ENTRY_TYPES_AVAILABLE_FROM_TIMELINE) {
PerformanceEntryReporter::getInstance()->getEntries(entries, entryType);
}
sortEntries(entries);
return toNativePerformanceEntries(entries);
}
std::vector<NativePerformanceEntry> NativePerformance::getEntriesByName(
jsi::Runtime& /*rt*/,
std::string entryName,
std::optional<PerformanceEntryType> entryType) {
std::vector<PerformanceEntry> entries;
if (entryType) {
if (isAvailableFromTimeline(*entryType)) {
PerformanceEntryReporter::getInstance()->getEntries(
entries, *entryType, entryName);
}
} else {
for (auto type : ENTRY_TYPES_AVAILABLE_FROM_TIMELINE) {
PerformanceEntryReporter::getInstance()->getEntries(
entries, type, entryName);
}
}
sortEntries(entries);
return toNativePerformanceEntries(entries);
}
std::vector<NativePerformanceEntry> NativePerformance::getEntriesByType(
jsi::Runtime& /*rt*/,
PerformanceEntryType entryType) {
std::vector<PerformanceEntry> entries;
if (isAvailableFromTimeline(entryType)) {
PerformanceEntryReporter::getInstance()->getEntries(entries, entryType);
}
sortEntries(entries);
return toNativePerformanceEntries(entries);
}
std::vector<std::pair<std::string, uint32_t>> NativePerformance::getEventCounts(
jsi::Runtime& /*rt*/) {
const auto& eventCounts =
PerformanceEntryReporter::getInstance()->getEventCounts();
return {eventCounts.begin(), eventCounts.end()};
}
std::unordered_map<std::string, double> NativePerformance::getSimpleMemoryInfo(
jsi::Runtime& rt) {
auto heapInfo = rt.instrumentation().getHeapInfo(false);
std::unordered_map<std::string, double> heapInfoToJs;
for (auto& entry : heapInfo) {
heapInfoToJs[entry.first] = static_cast<double>(entry.second);
}
return heapInfoToJs;
}
std::unordered_map<std::string, double>
NativePerformance::getReactNativeStartupTiming(jsi::Runtime& rt) {
std::unordered_map<std::string, double> result;
ReactMarker::StartupLogger& startupLogger =
ReactMarker::StartupLogger::getInstance();
if (!std::isnan(startupLogger.getAppStartupStartTime())) {
result["startTime"] = startupLogger.getAppStartupStartTime();
} else if (!std::isnan(startupLogger.getInitReactRuntimeStartTime())) {
result["startTime"] = startupLogger.getInitReactRuntimeStartTime();
}
if (!std::isnan(startupLogger.getInitReactRuntimeStartTime())) {
result["initializeRuntimeStart"] =
startupLogger.getInitReactRuntimeStartTime();
}
if (!std::isnan(startupLogger.getRunJSBundleStartTime())) {
result["executeJavaScriptBundleEntryPointStart"] =
startupLogger.getRunJSBundleStartTime();
}
if (!std::isnan(startupLogger.getRunJSBundleEndTime())) {
result["executeJavaScriptBundleEntryPointEnd"] =
startupLogger.getRunJSBundleEndTime();
}
if (!std::isnan(startupLogger.getInitReactRuntimeEndTime())) {
result["initializeRuntimeEnd"] = startupLogger.getInitReactRuntimeEndTime();
}
if (!std::isnan(startupLogger.getAppStartupEndTime())) {
result["endTime"] = startupLogger.getAppStartupEndTime();
}
return result;
}
jsi::Object NativePerformance::createObserver(
jsi::Runtime& rt,
NativePerformancePerformanceObserverCallback callback) {
// The way we dispatch performance observer callbacks is a bit different from
// the spec. The specification requires us to queue a single task that
// dispatches observer callbacks. Instead, we are queuing all callbacks as
// separate tasks in the scheduler.
PerformanceObserverCallback cb = [callback = std::move(callback)]() {
callback.callWithPriority(SchedulerPriority::IdlePriority);
};
auto& registry =
PerformanceEntryReporter::getInstance()->getObserverRegistry();
auto observer = PerformanceObserver::create(registry, std::move(cb));
auto observerWrapper = std::make_shared<PerformanceObserverWrapper>(observer);
jsi::Object observerObj{rt};
observerObj.setNativeState(rt, observerWrapper);
return observerObj;
}
double NativePerformance::getDroppedEntriesCount(
jsi::Runtime& rt,
jsi::Object observerObj) {
auto observer = tryGetObserver(rt, observerObj);
if (!observer) {
return 0;
}
return observer->getDroppedEntriesCount();
}
void NativePerformance::observe(
jsi::Runtime& rt,
jsi::Object observerObj,
NativePerformancePerformanceObserverObserveOptions options) {
auto observer = tryGetObserver(rt, observerObj);
if (!observer) {
return;
}
auto durationThreshold =
options.durationThreshold.value_or(HighResDuration::zero());
// observer of type multiple
if (options.entryTypes.has_value()) {
std::unordered_set<PerformanceEntryType> entryTypes;
auto rawTypes = options.entryTypes.value();
for (auto rawType : rawTypes) {
entryTypes.insert(Bridging<PerformanceEntryType>::fromJs(rt, rawType));
}
observer->observe(entryTypes);
} else { // single
auto buffered = options.buffered.value_or(false);
if (options.type.has_value()) {
observer->observe(
static_cast<PerformanceEntryType>(options.type.value()),
{.buffered = buffered, .durationThreshold = durationThreshold});
}
}
}
void NativePerformance::disconnect(jsi::Runtime& rt, jsi::Object observerObj) {
auto observerWrapper = std::dynamic_pointer_cast<PerformanceObserverWrapper>(
observerObj.getNativeState(rt));
if (!observerWrapper) {
return;
}
auto observer = observerWrapper->observer;
observer->disconnect();
}
std::vector<NativePerformanceEntry> NativePerformance::takeRecords(
jsi::Runtime& rt,
jsi::Object observerObj,
bool sort) {
auto observerWrapper = std::dynamic_pointer_cast<PerformanceObserverWrapper>(
observerObj.getNativeState(rt));
if (!observerWrapper) {
return {};
}
auto observer = observerWrapper->observer;
auto records = observer->takeRecords();
if (sort) {
sortEntries(records);
}
return toNativePerformanceEntries(records);
}
std::vector<PerformanceEntryType>
NativePerformance::getSupportedPerformanceEntryTypes(jsi::Runtime& /*rt*/) {
auto supportedEntryTypes = PerformanceEntryReporter::getSupportedEntryTypes();
return {supportedEntryTypes.begin(), supportedEntryTypes.end()};
}
} // namespace facebook::react
Выполнить команду
Для локальной разработки. Не используйте в интернете!