[X2Go-Commits] [pale-moon] 46/102: Reduce number of allocations in AutoStopwatch

git-admin at x2go.org git-admin at x2go.org
Mon Feb 25 23:25:49 CET 2019


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch upstream/28.4.0
in repository pale-moon.

commit b55d41c240df13812760a2a77f086a477f450fd0
Author: David Teller <dteller at mozilla.com>
Date:   Tue Jan 29 03:11:39 2019 +0100

    Reduce number of allocations in AutoStopwatch
    
    This patch fixes two related issues.
    1. The AutoStopwatch uses a stack-allocated `mozilla::Vector` to
    communicate with its callback during each compartment switch.
    This vector was designed to allow its contents to be stack-allocated
    but they turned out to be accidentally heap-allocated.
    
    2. During each tick, the stopwatch fills a vector `recentGroups_`.
    This vector always started with minimal capacity and had to grow
    repeatedly as groups were added, causing repeated reallocations.
    This patch preallocates `recentGroups_` to have the same capacity as the
    previous tick. We expect that this should eventually reach a stable size
    that closely matches the actual needs of the process.
---
 js/src/jsapi.h                                     |  2 +-
 js/src/vm/Stopwatch.cpp                            | 25 +++++++++++++++++-----
 .../perfmonitoring/nsPerformanceStats.cpp          | 11 ++++++++--
 .../components/perfmonitoring/nsPerformanceStats.h |  2 +-
 4 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index 0983f03..799396a 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 7a6acb9..5b5ec61 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 6c47035..59d84ce 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 6902c84..661a78a 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

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/pale-moon.git


More information about the x2go-commits mailing list