diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.cpp b/Libraries/WebPerformance/PerformanceEntryReporter.cpp index daf673e908d..959b1c454f0 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.cpp +++ b/Libraries/WebPerformance/PerformanceEntryReporter.cpp @@ -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( diff --git a/Libraries/WebPerformance/PerformanceEntryReporter.h b/Libraries/WebPerformance/PerformanceEntryReporter.h index 44e067f881a..7f7a014fade 100644 --- a/Libraries/WebPerformance/PerformanceEntryReporter.h +++ b/Libraries/WebPerformance/PerformanceEntryReporter.h @@ -183,7 +183,7 @@ class PerformanceEntryReporter : public EventLogger { size_t bufferPosition, const char *entryName = nullptr) const { std::vector 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 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; } }; diff --git a/Libraries/WebPerformance/__tests__/PerformanceEntryReporterTest.cpp b/Libraries/WebPerformance/__tests__/PerformanceEntryReporterTest.cpp index 0c596c465c6..badf5396ff5 100644 --- a/Libraries/WebPerformance/__tests__/PerformanceEntryReporterTest.cpp +++ b/Libraries/WebPerformance/__tests__/PerformanceEntryReporterTest.cpp @@ -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 getNames( + const std::vector &entries) { + std::vector res; + std::transform( + entries.begin(), + entries.end(), + std::back_inserter(res), + [](const RawPerformanceEntry &e) { return e.name; }); + return res; +} + +static std::vector getTypes( + const std::vector &entries) { + std::vector 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({2, 2, 2, 2, 2}), getTypes(measures)); + ASSERT_EQ(std::vector({1, 2}), getTypes(common_name)); + ASSERT_EQ(std::vector({1, 1, 1, 2, 2, 2, 2, 2}), getTypes(all)); + ASSERT_EQ(std::vector({1, 1, 1}), getTypes(marks)); + + ASSERT_EQ( + std::vector({"common_name", "mark1", "mark2"}), + getNames(marks)); + + ASSERT_EQ( + std::vector({"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( + {"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( + {"mark2", "measure1", "measure2", "measure3", "measure4"}), + getNames(e2)); + + reporter.clearEntries(PerformanceEntryType::MEASURE); + auto e3 = reporter.getEntries(); + + ASSERT_EQ(1, e3.size()); + ASSERT_EQ(std::vector({"mark2"}), getNames(e3)); + + reporter.clearEntries(); + auto e4 = reporter.getEntries(); + + ASSERT_EQ(0, e4.size()); +}