##// END OF EJS Templates
merge with stable
Gregory Szorc -
r39183:b95b48a5 merge default
parent child Browse files
Show More
@@ -790,6 +790,63 b' def perfphases(ui, repo, **opts):'
790 timer(d)
790 timer(d)
791 fm.end()
791 fm.end()
792
792
793 @command('perfphasesremote',
794 [], "[DEST]")
795 def perfphasesremote(ui, repo, dest=None, **opts):
796 """benchmark time needed to analyse phases of the remote server"""
797 from mercurial.node import (
798 bin,
799 )
800 from mercurial import (
801 exchange,
802 hg,
803 phases,
804 )
805 timer, fm = gettimer(ui, opts)
806
807 path = ui.paths.getpath(dest, default=('default-push', 'default'))
808 if not path:
809 raise error.abort(('default repository not configured!'),
810 hint=("see 'hg help config.paths'"))
811 dest = path.pushloc or path.loc
812 branches = (path.branch, opts.get('branch') or [])
813 ui.status(('analysing phase of %s\n') % util.hidepassword(dest))
814 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
815 other = hg.peer(repo, opts, dest)
816
817 # easier to perform discovery through the operation
818 op = exchange.pushoperation(repo, other)
819 exchange._pushdiscoverychangeset(op)
820
821 remotesubset = op.fallbackheads
822
823 with other.commandexecutor() as e:
824 remotephases = e.callcommand('listkeys',
825 {'namespace': 'phases'}).result()
826 del other
827 publishing = remotephases.get('publishing', False)
828 if publishing:
829 ui.status(('publishing: yes\n'))
830 else:
831 ui.status(('publishing: no\n'))
832
833 nodemap = repo.changelog.nodemap
834 nonpublishroots = 0
835 for nhex, phase in remotephases.iteritems():
836 if nhex == 'publishing': # ignore data related to publish option
837 continue
838 node = bin(nhex)
839 if node in nodemap and int(phase):
840 nonpublishroots += 1
841 ui.status(('number of roots: %d\n') % len(remotephases))
842 ui.status(('number of known non public roots: %d\n') % nonpublishroots)
843 def d():
844 phases.remotephasessummary(repo,
845 remotesubset,
846 remotephases)
847 timer(d)
848 fm.end()
849
793 @command('perfmanifest',[
850 @command('perfmanifest',[
794 ('m', 'manifest-rev', False, 'Look up a manifest node revision'),
851 ('m', 'manifest-rev', False, 'Look up a manifest node revision'),
795 ('', 'clear-disk', False, 'clear on-disk caches too'),
852 ('', 'clear-disk', False, 'clear on-disk caches too'),
@@ -664,9 +664,39 b' def newheads(repo, heads, roots):'
664
664
665 * `heads`: define the first subset
665 * `heads`: define the first subset
666 * `roots`: define the second we subtract from the first"""
666 * `roots`: define the second we subtract from the first"""
667 # prevent an import cycle
668 # phases > dagop > patch > copies > scmutil > obsolete > obsutil > phases
669 from . import dagop
670
667 repo = repo.unfiltered()
671 repo = repo.unfiltered()
668 revs = repo.revs('heads(::%ln - (%ln::%ln))', heads, roots, heads)
672 cl = repo.changelog
669 return pycompat.maplist(repo.changelog.node, revs)
673 rev = cl.nodemap.get
674 if not roots:
675 return heads
676 if not heads or heads == [nullrev]:
677 return []
678 # The logic operated on revisions, convert arguments early for convenience
679 new_heads = set(rev(n) for n in heads if n != nullid)
680 roots = [rev(n) for n in roots]
681 if not heads or not roots:
682 return heads
683 # compute the area we need to remove
684 affected_zone = repo.revs("(%ld::%ld)", roots, new_heads)
685 # heads in the area are no longer heads
686 new_heads.difference_update(affected_zone)
687 # revisions in the area have children outside of it,
688 # They might be new heads
689 candidates = repo.revs("parents(%ld + (%ld and merge())) and not null",
690 roots, affected_zone)
691 candidates -= affected_zone
692 if new_heads or candidates:
693 # remove candidate that are ancestors of other heads
694 new_heads.update(candidates)
695 prunestart = repo.revs("parents(%ld) and not null", new_heads)
696 pruned = dagop.reachableroots(repo, candidates, prunestart)
697 new_heads.difference_update(pruned)
698
699 return pycompat.maplist(cl.node, sorted(new_heads))
670
700
671 def newcommitphase(ui):
701 def newcommitphase(ui):
672 """helper to get the target phase of new commit
702 """helper to get the target phase of new commit
@@ -263,13 +263,17 b' def _trimchunk(revlog, revs, startidx, e'
263 if endidx is None:
263 if endidx is None:
264 endidx = len(revs)
264 endidx = len(revs)
265
265
266 # Trim empty revs at the end, but never the very first revision of a chain
266 # If we have a non-emtpy delta candidate, there are nothing to trim
267 while endidx > 1 and endidx > startidx and length(revs[endidx - 1]) == 0:
267 if revs[endidx - 1] < len(revlog):
268 # Trim empty revs at the end, except the very first revision of a chain
269 while (endidx > 1
270 and endidx > startidx
271 and length(revs[endidx - 1]) == 0):
268 endidx -= 1
272 endidx -= 1
269
273
270 return revs[startidx:endidx]
274 return revs[startidx:endidx]
271
275
272 def _segmentspan(revlog, revs):
276 def _segmentspan(revlog, revs, deltainfo=None):
273 """Get the byte span of a segment of revisions
277 """Get the byte span of a segment of revisions
274
278
275 revs is a sorted array of revision numbers
279 revs is a sorted array of revision numbers
@@ -295,7 +299,14 b' def _segmentspan(revlog, revs):'
295 """
299 """
296 if not revs:
300 if not revs:
297 return 0
301 return 0
298 return revlog.end(revs[-1]) - revlog.start(revs[0])
302 if deltainfo is not None and len(revlog) <= revs[-1]:
303 if len(revs) == 1:
304 return deltainfo.deltalen
305 offset = revlog.end(len(revlog) - 1)
306 end = deltainfo.deltalen + offset
307 else:
308 end = revlog.end(revs[-1])
309 return end - revlog.start(revs[0])
299
310
300 def _slicechunk(revlog, revs, deltainfo=None, targetsize=None):
311 def _slicechunk(revlog, revs, deltainfo=None, targetsize=None):
301 """slice revs to reduce the amount of unrelated data to be read from disk.
312 """slice revs to reduce the amount of unrelated data to be read from disk.
@@ -527,7 +538,7 b' def _slicechunktodensity(revlog, revs, d'
527 yield revs
538 yield revs
528 return
539 return
529
540
530 if deltainfo is not None:
541 if deltainfo is not None and deltainfo.deltalen:
531 revs = list(revs)
542 revs = list(revs)
532 revs.append(nextrev)
543 revs.append(nextrev)
533
544
@@ -2471,7 +2482,8 b' class revlog(object):'
2471 deltachain = []
2482 deltachain = []
2472
2483
2473 chunks = _slicechunk(self, deltachain, deltainfo)
2484 chunks = _slicechunk(self, deltachain, deltainfo)
2474 distance = max(map(lambda revs:_segmentspan(self, revs), chunks))
2485 all_span = [_segmentspan(self, revs, deltainfo) for revs in chunks]
2486 distance = max(all_span)
2475 else:
2487 else:
2476 distance = deltainfo.distance
2488 distance = deltainfo.distance
2477
2489
@@ -141,10 +141,10 b' delete a remote bookmark'
141 bundle2-output: payload chunk size: 23
141 bundle2-output: payload chunk size: 23
142 bundle2-output: closing payload chunk
142 bundle2-output: closing payload chunk
143 bundle2-output: bundle part: "check:phases"
143 bundle2-output: bundle part: "check:phases"
144 bundle2-output-part: "check:phases" 48 bytes payload
144 bundle2-output-part: "check:phases" 24 bytes payload
145 bundle2-output: part 2: "CHECK:PHASES"
145 bundle2-output: part 2: "CHECK:PHASES"
146 bundle2-output: header chunk size: 19
146 bundle2-output: header chunk size: 19
147 bundle2-output: payload chunk size: 48
147 bundle2-output: payload chunk size: 24
148 bundle2-output: closing payload chunk
148 bundle2-output: closing payload chunk
149 bundle2-output: bundle part: "pushkey"
149 bundle2-output: bundle part: "pushkey"
150 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
150 bundle2-output-part: "pushkey" (params: 4 mandatory) empty payload
@@ -180,9 +180,9 b' delete a remote bookmark'
180 bundle2-input: part parameters: 0
180 bundle2-input: part parameters: 0
181 bundle2-input: found a handler for part check:phases
181 bundle2-input: found a handler for part check:phases
182 bundle2-input-part: "check:phases" supported
182 bundle2-input-part: "check:phases" supported
183 bundle2-input: payload chunk size: 48
183 bundle2-input: payload chunk size: 24
184 bundle2-input: payload chunk size: 0
184 bundle2-input: payload chunk size: 0
185 bundle2-input-part: total payload size 48
185 bundle2-input-part: total payload size 24
186 bundle2-input: part header size: 90
186 bundle2-input: part header size: 90
187 bundle2-input: part type: "PUSHKEY"
187 bundle2-input: part type: "PUSHKEY"
188 bundle2-input: part id: "3"
188 bundle2-input: part id: "3"
@@ -253,10 +253,10 b' delete a remote bookmark'
253 bundle2-output: payload chunk size: 23
253 bundle2-output: payload chunk size: 23
254 bundle2-output: closing payload chunk
254 bundle2-output: closing payload chunk
255 bundle2-output: bundle part: "check:phases"
255 bundle2-output: bundle part: "check:phases"
256 bundle2-output-part: "check:phases" 48 bytes payload
256 bundle2-output-part: "check:phases" 24 bytes payload
257 bundle2-output: part 2: "CHECK:PHASES"
257 bundle2-output: part 2: "CHECK:PHASES"
258 bundle2-output: header chunk size: 19
258 bundle2-output: header chunk size: 19
259 bundle2-output: payload chunk size: 48
259 bundle2-output: payload chunk size: 24
260 bundle2-output: closing payload chunk
260 bundle2-output: closing payload chunk
261 bundle2-output: bundle part: "bookmarks"
261 bundle2-output: bundle part: "bookmarks"
262 bundle2-output-part: "bookmarks" 23 bytes payload
262 bundle2-output-part: "bookmarks" 23 bytes payload
@@ -293,9 +293,9 b' delete a remote bookmark'
293 bundle2-input: part parameters: 0
293 bundle2-input: part parameters: 0
294 bundle2-input: found a handler for part check:phases
294 bundle2-input: found a handler for part check:phases
295 bundle2-input-part: "check:phases" supported
295 bundle2-input-part: "check:phases" supported
296 bundle2-input: payload chunk size: 48
296 bundle2-input: payload chunk size: 24
297 bundle2-input: payload chunk size: 0
297 bundle2-input: payload chunk size: 0
298 bundle2-input-part: total payload size 48
298 bundle2-input-part: total payload size 24
299 bundle2-input: part header size: 16
299 bundle2-input: part header size: 16
300 bundle2-input: part type: "BOOKMARKS"
300 bundle2-input: part type: "BOOKMARKS"
301 bundle2-input: part id: "3"
301 bundle2-input: part id: "3"
@@ -103,6 +103,8 b' perfstatus'
103 perfpathcopies
103 perfpathcopies
104 (no help text available)
104 (no help text available)
105 perfphases benchmark phasesets computation
105 perfphases benchmark phasesets computation
106 perfphasesremote
107 benchmark time needed to analyse phases of the remote server
106 perfrawfiles (no help text available)
108 perfrawfiles (no help text available)
107 perfrevlogchunks
109 perfrevlogchunks
108 Benchmark operations on revlog chunks.
110 Benchmark operations on revlog chunks.
@@ -212,4 +214,7 b' Check perf.py for historical portability'
212 contrib/perf.py:\d+: (re)
214 contrib/perf.py:\d+: (re)
213 > from mercurial import (
215 > from mercurial import (
214 import newer module separately in try clause for early Mercurial
216 import newer module separately in try clause for early Mercurial
217 contrib/perf.py:\d+: (re)
218 > from mercurial import (
219 import newer module separately in try clause for early Mercurial
215 [1]
220 [1]
General Comments 0
You need to be logged in to leave comments. Login now