mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Implement Performance.getEntries* W3C extension for Performance Timeline API (#36314)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/36314 ## Changelog: [Internal] - Added support for W3C Performance API extension (Performance,getEntries*) See [here for the details](https://www.w3.org/TR/performance-timeline/#extensions-to-the-performance-interface). This only supports `mark` and `measure` performance entry types (not `events`, as those are not supported by browsers either, they recommend using the `PerformanceObserver` API instead). From the implementation perspective, we already maintained persistent buffer for `mark` entry types, which was required in order to look up measures. The buffer is circular, limited to 1K entries by default. I basically mimic the same behavior for `measure` entry types as well, since it's the simplest way of doing it at this point, If we happen to want adding some other entry types that would be available via `Performance.getEntries*` API in the future, we may want to iterate on the internal data structures representation inside `PerformanceEntryReporter`, but for now I believe this approach should work just fine, and whatever changes we may want to do will be purely internal implementation detail. Reviewed By: rubennorte Differential Revision: D43625488 fbshipit-source-id: dd315b3f8488e910749a8e2a4158246e94d76f99
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3997fc1c66
commit
bc56f66b8d
@@ -20,6 +20,28 @@ static constexpr size_t MAX_ENTRY_BUFFER_SIZE = 1024;
|
||||
namespace facebook::react {
|
||||
EventTag PerformanceEntryReporter::sCurrentEventTag_{0};
|
||||
|
||||
RawPerformanceEntry PerformanceMark::toRawPerformanceEntry() const {
|
||||
return {
|
||||
name,
|
||||
static_cast<int>(PerformanceEntryType::MARK),
|
||||
timeStamp,
|
||||
0.0,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt};
|
||||
}
|
||||
|
||||
RawPerformanceEntry PerformanceMeasure::toRawPerformanceEntry() const {
|
||||
return {
|
||||
name,
|
||||
static_cast<int>(PerformanceEntryType::MEASURE),
|
||||
timeStamp,
|
||||
duration,
|
||||
std::nullopt,
|
||||
std::nullopt,
|
||||
std::nullopt};
|
||||
}
|
||||
|
||||
PerformanceEntryReporter &PerformanceEntryReporter::getInstance() {
|
||||
static PerformanceEntryReporter instance;
|
||||
return instance;
|
||||
@@ -97,6 +119,7 @@ void PerformanceEntryReporter::mark(
|
||||
// it to a circular buffer:
|
||||
PerformanceMark &mark = marksBuffer_[marksBufferPosition_];
|
||||
marksBufferPosition_ = (marksBufferPosition_ + 1) % marksBuffer_.size();
|
||||
marksCount_ = std::min(marksBuffer_.size(), marksCount_ + 1);
|
||||
|
||||
if (!mark.name.empty()) {
|
||||
// Drop off the oldest mark out of the queue, but only if that's indeed the
|
||||
@@ -124,10 +147,24 @@ void PerformanceEntryReporter::mark(
|
||||
void PerformanceEntryReporter::clearEntries(
|
||||
PerformanceEntryType entryType,
|
||||
const char *entryName) {
|
||||
if (entryName != nullptr && entryType == PerformanceEntryType::MARK) {
|
||||
// remove a named mark from the mark/measure registry
|
||||
PerformanceMark mark{{entryName, 0}};
|
||||
marksRegistry_.erase(&mark);
|
||||
if (entryType == PerformanceEntryType::MARK) {
|
||||
if (entryName != nullptr) {
|
||||
// remove a named mark from the mark/measure registry
|
||||
PerformanceMark mark{{entryName, 0}};
|
||||
marksRegistry_.erase(&mark);
|
||||
|
||||
clearCircularBuffer(
|
||||
marksBuffer_, marksCount_, marksBufferPosition_, entryName);
|
||||
} else {
|
||||
marksCount_ = 0;
|
||||
}
|
||||
} else if (entryType == PerformanceEntryType::MEASURE) {
|
||||
if (entryName != nullptr) {
|
||||
clearCircularBuffer(
|
||||
measuresBuffer_, measuresCount_, measuresBufferPosition_, entryName);
|
||||
} else {
|
||||
measuresCount_ = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int lastPos = entries_.size() - 1;
|
||||
@@ -144,6 +181,26 @@ void PerformanceEntryReporter::clearEntries(
|
||||
entries_.resize(lastPos + 1);
|
||||
}
|
||||
|
||||
std::vector<RawPerformanceEntry> PerformanceEntryReporter::getEntries(
|
||||
PerformanceEntryType entryType,
|
||||
const char *entryName) const {
|
||||
if (entryType == PerformanceEntryType::MARK) {
|
||||
return getCircularBufferContents(
|
||||
marksBuffer_, marksCount_, marksBufferPosition_, entryName);
|
||||
} else if (entryType == PerformanceEntryType::MEASURE) {
|
||||
return getCircularBufferContents(
|
||||
measuresBuffer_, measuresCount_, measuresBufferPosition_, entryName);
|
||||
} else if (entryType == PerformanceEntryType::UNDEFINED) {
|
||||
auto marks = getCircularBufferContents(
|
||||
marksBuffer_, marksCount_, marksBufferPosition_, entryName);
|
||||
auto measures = getCircularBufferContents(
|
||||
measuresBuffer_, measuresCount_, measuresBufferPosition_, entryName);
|
||||
marks.insert(marks.end(), measures.begin(), measures.end());
|
||||
return marks;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void PerformanceEntryReporter::measure(
|
||||
const std::string &name,
|
||||
double startTime,
|
||||
@@ -154,6 +211,13 @@ void PerformanceEntryReporter::measure(
|
||||
double startTimeVal = startMark ? getMarkTime(*startMark) : startTime;
|
||||
double endTimeVal = endMark ? getMarkTime(*endMark) : endTime;
|
||||
double durationVal = duration ? *duration : endTimeVal - startTimeVal;
|
||||
|
||||
measuresBuffer_[measuresBufferPosition_] =
|
||||
PerformanceMeasure{name, startTime, endTime};
|
||||
measuresBufferPosition_ =
|
||||
(measuresBufferPosition_ + 1) % measuresBuffer_.size();
|
||||
measuresCount_ = std::min(measuresBuffer_.size(), measuresCount_ + 1);
|
||||
|
||||
logEntry(
|
||||
{name,
|
||||
static_cast<int>(PerformanceEntryType::MEASURE),
|
||||
|
||||
Reference in New Issue
Block a user