summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--js/src/jsapi.h2
-rw-r--r--js/src/vm/Stopwatch.cpp25
-rw-r--r--toolkit/components/perfmonitoring/nsPerformanceStats.cpp11
-rw-r--r--toolkit/components/perfmonitoring/nsPerformanceStats.h2
4 files changed, 31 insertions, 9 deletions
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 0983f034f..799396a0a 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -6566,7 +6566,7 @@ struct JS_PUBLIC_API(PerformanceGroup) {
uint64_t refCount_;
};
-using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 0, SystemAllocPolicy>;
+using PerformanceGroupVector = mozilla::Vector<RefPtr<js::PerformanceGroup>, 8, SystemAllocPolicy>;
/**
* Commit any Performance Monitoring data.
diff --git a/js/src/vm/Stopwatch.cpp b/js/src/vm/Stopwatch.cpp
index 7a6acb970..5b5ec6196 100644
--- a/js/src/vm/Stopwatch.cpp
+++ b/js/src/vm/Stopwatch.cpp
@@ -20,6 +20,7 @@
#include "gc/Zone.h"
#include "vm/Runtime.h"
+
namespace js {
bool
@@ -136,6 +137,9 @@ PerformanceMonitoring::start()
bool
PerformanceMonitoring::commit()
{
+ // Maximal initialization size, in elements for the vector of groups.
+ static const size_t MAX_GROUPS_INIT_CAPACITY = 1024;
+
#if !defined(MOZ_HAVE_RDTSC)
// The AutoStopwatch is only executed if `MOZ_HAVE_RDTSC`.
return false;
@@ -152,13 +156,24 @@ PerformanceMonitoring::commit()
return true;
}
- PerformanceGroupVector recentGroups;
- recentGroups_.swap(recentGroups);
+ // The move operation is generally constant time, unless
+ // `recentGroups_.length()` is very small, in which case
+ // it's fast just because it's small.
+ PerformanceGroupVector recentGroups(Move(recentGroups_));
+ recentGroups_ = PerformanceGroupVector(); // Reconstruct after `Move`.
bool success = true;
if (stopwatchCommitCallback)
success = stopwatchCommitCallback(iteration_, recentGroups, stopwatchCommitClosure);
+ // Heuristic: we expect to have roughly the same number of groups as in
+ // the previous iteration.
+ const size_t capacity = recentGroups.capacity() < MAX_GROUPS_INIT_CAPACITY ?
+ recentGroups.capacity() :
+ MAX_GROUPS_INIT_CAPACITY;
+ success = recentGroups_.reserve(capacity)
+ && success;
+
// Reset immediately, to make sure that we're not hit by the end
// of a nested event loop (which would cause `commit` to be called
// twice in succession).
@@ -227,7 +242,7 @@ AutoStopwatch::AutoStopwatch(JSContext* cx MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IM
MOZ_GUARD_OBJECT_NOTIFIER_INIT;
JSCompartment* compartment = cx_->compartment();
- if (compartment->scheduledForDestruction)
+ if (MOZ_UNLIKELY(compartment->scheduledForDestruction))
return;
JSRuntime* runtime = cx_->runtime();
@@ -266,11 +281,11 @@ AutoStopwatch::~AutoStopwatch()
}
JSCompartment* compartment = cx_->compartment();
- if (compartment->scheduledForDestruction)
+ if (MOZ_UNLIKELY(compartment->scheduledForDestruction))
return;
JSRuntime* runtime = cx_->runtime();
- if (iteration_ != runtime->performanceMonitoring.iteration()) {
+ if (MOZ_UNLIKELY(iteration_ != runtime->performanceMonitoring.iteration())) {
// We have entered a nested event loop at some point.
// Any information we may have is obsolete.
return;
diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
index 6c470356a..59d84ced1 100644
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.cpp
@@ -1082,6 +1082,9 @@ nsPerformanceStatsService::GetPerformanceGroups(JSContext* cx,
return false;
}
+ // Returning a vector that is too large would cause allocations all over the
+ // place in the JS engine. We want to be sure that all data is stored inline.
+ MOZ_ASSERT(out.length() <= out.sMaxInlineStorage);
return true;
}
@@ -1310,8 +1313,12 @@ nsPerformanceStatsService::GetResources(uint64_t* userTime,
void
nsPerformanceStatsService::NotifyJankObservers(const mozilla::Vector<uint64_t>& aPreviousJankLevels) {
- GroupVector alerts;
- mPendingAlerts.swap(alerts);
+
+ // The move operation is generally constant time, unless
+ // `mPendingAlerts.length()` is very small, in which case it's fast anyway.
+ GroupVector alerts(Move(mPendingAlerts));
+ mPendingAlerts = GroupVector(); // Reconstruct after `Move`.
+
if (!mPendingAlertsCollector) {
// We are shutting down.
return;
diff --git a/toolkit/components/perfmonitoring/nsPerformanceStats.h b/toolkit/components/perfmonitoring/nsPerformanceStats.h
index 6902c840d..661a78a1a 100644
--- a/toolkit/components/perfmonitoring/nsPerformanceStats.h
+++ b/toolkit/components/perfmonitoring/nsPerformanceStats.h
@@ -19,7 +19,7 @@
class nsPerformanceGroup;
class nsPerformanceGroupDetails;
-typedef mozilla::Vector<RefPtr<nsPerformanceGroup>> GroupVector;
+typedef mozilla::Vector<RefPtr<nsPerformanceGroup>, 8> GroupVector;
/**
* A data structure for registering observers interested in