changegroup: store old heads as a set stable 4.1.2
authorGregory Szorc <gregory.szorc@gmail.com>
Thu, 23 Mar 2017 19:54:59 -0700
branchstable
changeset 31587 ed5b25874d99
parent 31516 2915cc1d3429
child 31608 4baf79a77afa
child 31759 8076499d292a
changegroup: store old heads as a set Previously, the "oldheads" variable was a list. On a repository at Mozilla with 46,492 heads, profiling revealed that list membership testing was dominating execution time of applying small changegroups. This patch converts the list of old heads to a set. This makes membership testing significantly faster. On the aforementioned repository with 46,492 heads: $ hg unbundle <file with 1 changeset> before: 18.535s wall after: 1.303s Consumers of this variable only check for truthiness (`if oldheads`), length (`len(oldheads)`), and (most importantly) item membership (`h not in oldheads` - which occurs twice). So, the change to a set should be safe and suitable for stable. The practical effect of this change is that changegroup application and related operations (like `hg push`) no longer exhibit an O(n^2) CPU explosion as the number of heads grows.
mercurial/changegroup.py
--- a/mercurial/changegroup.py	Mon Mar 20 04:36:55 2017 -0700
+++ b/mercurial/changegroup.py	Thu Mar 23 19:54:59 2017 -0700
@@ -293,7 +293,7 @@
                 # will not see an inconsistent view
                 cl = repo.changelog
                 cl.delayupdate(tr)
-                oldheads = cl.heads()
+                oldheads = set(cl.heads())
 
                 trp = weakref.proxy(tr)
                 # pull off the changeset group