# HG changeset patch # User Gregory Szorc # Date 2017-03-24 02:54:59 # Node ID ed5b25874d998ababb181a939dd37a16ea644435 # Parent 2915cc1d3429f9b11c9cf48d45990f982fff8e7a 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 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. diff --git a/mercurial/changegroup.py b/mercurial/changegroup.py --- a/mercurial/changegroup.py +++ b/mercurial/changegroup.py @@ -293,7 +293,7 @@ class cg1unpacker(object): # 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