Unit tests/fixes for PerformanceEntryObserver::get/clearEntries (#36384)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/36384

## Changelog:
[Internal] - Adds more test coverage to PerformanceEntryObserver functionality related to buffering of the marks/measures, as well as making fixes for certain corner cases handled incorrectly (which are now covered by tests).

Reviewed By: rubennorte

Differential Revision: D43835928

fbshipit-source-id: fc8adbd6c2a2b6b201f1f14bdf51245268c5eabd
This commit is contained in:
Ruslan Shestopalyuk
2023-03-06 15:23:02 -08:00
committed by Facebook GitHub Bot
parent 24dbb5df0a
commit ea354d4e22
3 changed files with 131 additions and 5 deletions
@@ -164,8 +164,9 @@ void PerformanceEntryReporter::clearEntries(
marksCount_ = 0;
marksRegistry_.clear();
}
} else if (
entryType == PerformanceEntryType::MEASURE ||
}
if (entryType == PerformanceEntryType::MEASURE ||
entryType == PerformanceEntryType::UNDEFINED) {
if (entryName != nullptr) {
clearCircularBuffer(
@@ -183,7 +183,7 @@ class PerformanceEntryReporter : public EventLogger {
size_t bufferPosition,
const char *entryName = nullptr) const {
std::vector<RawPerformanceEntry> res;
size_t pos = bufferPosition;
size_t pos = (bufferPosition - entryCount + buffer.size()) % buffer.size();
for (size_t i = 0; i < entryCount; i++) {
if (entryName == nullptr || buffer[pos].name == entryName) {
res.push_back(buffer[pos].toRawPerformanceEntry());
@@ -202,7 +202,7 @@ class PerformanceEntryReporter : public EventLogger {
std::array<T, N> newBuffer;
size_t newEntryCount = 0;
size_t pos = bufferPosition;
size_t pos = (bufferPosition - entryCount + buffer.size()) % buffer.size();
for (size_t i = 0; i < entryCount; i++) {
if (buffer[pos].name != entryName) {
newBuffer[newEntryCount++] = buffer[pos];
@@ -211,7 +211,7 @@ class PerformanceEntryReporter : public EventLogger {
}
buffer = newBuffer;
bufferPosition = 0;
bufferPosition = newEntryCount;
entryCount = newEntryCount;
}
};
@@ -12,6 +12,7 @@
#include "../PerformanceEntryReporter.h"
namespace facebook::react {
static std::ostream &operator<<(
std::ostream &os,
const RawPerformanceEntry &entry) {
@@ -222,3 +223,127 @@ TEST(PerformanceEntryReporter, PerformanceEntryReporterTestReportMeasures) {
ASSERT_EQ(expected, entries);
}
static std::vector<std::string> getNames(
const std::vector<RawPerformanceEntry> &entries) {
std::vector<std::string> res;
std::transform(
entries.begin(),
entries.end(),
std::back_inserter(res),
[](const RawPerformanceEntry &e) { return e.name; });
return res;
}
static std::vector<int32_t> getTypes(
const std::vector<RawPerformanceEntry> &entries) {
std::vector<int32_t> res;
std::transform(
entries.begin(),
entries.end(),
std::back_inserter(res),
[](const RawPerformanceEntry &e) { return e.entryType; });
return res;
}
TEST(PerformanceEntryReporter, PerformanceEntryReporterTestGetEntries) {
auto &reporter = PerformanceEntryReporter::getInstance();
reporter.stopReporting();
reporter.clearEntries();
auto res = reporter.popPendingEntries();
const auto &entries = res.entries;
ASSERT_EQ(0, res.droppedEntriesCount);
ASSERT_EQ(0, entries.size());
reporter.startReporting(PerformanceEntryType::MARK);
reporter.startReporting(PerformanceEntryType::MEASURE);
reporter.mark("common_name", 0.0, 1.0);
reporter.mark("mark1", 1.0, 3.0);
reporter.mark("mark2", 2.0, 4.0);
reporter.measure("common_name", 0.0, 2.0);
reporter.measure("measure1", 0.0, 2.0, 4.0);
reporter.measure("measure2", 0.0, 0.0, std::nullopt, "mark1", "mark2");
reporter.measure("measure3", 0.0, 0.0, 5.0, "mark1");
reporter.measure("measure4", 1.5, 0.0, std::nullopt, std::nullopt, "mark2");
res = reporter.popPendingEntries();
ASSERT_EQ(0, res.droppedEntriesCount);
ASSERT_EQ(8, res.entries.size());
reporter.getEntries(PerformanceEntryType::MARK);
const auto marks = reporter.getEntries(PerformanceEntryType::MARK);
const auto measures = reporter.getEntries(PerformanceEntryType::MEASURE);
const auto common_name =
reporter.getEntries(PerformanceEntryType::UNDEFINED, "common_name");
reporter.getEntries();
const auto all = reporter.getEntries();
ASSERT_EQ(std::vector<int32_t>({2, 2, 2, 2, 2}), getTypes(measures));
ASSERT_EQ(std::vector<int32_t>({1, 2}), getTypes(common_name));
ASSERT_EQ(std::vector<int32_t>({1, 1, 1, 2, 2, 2, 2, 2}), getTypes(all));
ASSERT_EQ(std::vector<int32_t>({1, 1, 1}), getTypes(marks));
ASSERT_EQ(
std::vector<std::string>({"common_name", "mark1", "mark2"}),
getNames(marks));
ASSERT_EQ(
std::vector<std::string>({"common_name", "common_name"}),
getNames(common_name));
}
TEST(PerformanceEntryReporter, PerformanceEntryReporterTestClearEntries) {
auto &reporter = PerformanceEntryReporter::getInstance();
reporter.stopReporting();
reporter.clearEntries();
reporter.startReporting(PerformanceEntryType::MARK);
reporter.startReporting(PerformanceEntryType::MEASURE);
reporter.mark("common_name", 0.0, 1.0);
reporter.mark("mark1", 1.0, 3.0);
reporter.mark("mark2", 2.0, 4.0);
reporter.measure("common_name", 0.0, 2.0);
reporter.measure("measure1", 0.0, 2.0, 4.0);
reporter.measure("measure2", 0.0, 0.0, std::nullopt, "mark1", "mark2");
reporter.measure("measure3", 0.0, 0.0, 5.0, "mark1");
reporter.measure("measure4", 1.5, 0.0, std::nullopt, std::nullopt, "mark2");
reporter.clearEntries(PerformanceEntryType::UNDEFINED, "common_name");
auto e1 = reporter.getEntries();
ASSERT_EQ(6, e1.size());
ASSERT_EQ(
std::vector<std::string>(
{"mark1", "mark2", "measure1", "measure2", "measure3", "measure4"}),
getNames(e1));
reporter.clearEntries(PerformanceEntryType::MARK, "mark1");
auto e2 = reporter.getEntries();
ASSERT_EQ(5, e2.size());
ASSERT_EQ(
std::vector<std::string>(
{"mark2", "measure1", "measure2", "measure3", "measure4"}),
getNames(e2));
reporter.clearEntries(PerformanceEntryType::MEASURE);
auto e3 = reporter.getEntries();
ASSERT_EQ(1, e3.size());
ASSERT_EQ(std::vector<std::string>({"mark2"}), getNames(e3));
reporter.clearEntries();
auto e4 = reporter.getEntries();
ASSERT_EQ(0, e4.size());
}