joerg.sonnenberger created this revision.
Herald added a subscriber: mercurial-devel.
Herald added a reviewer: hg-reviewers.

REVISION SUMMARY
  For ``hg diff``, ui.write appears as super hot in the profile with up to
  60% time spend in it for larger diffs. Introduce two predicates to
  decide if label processing is active at all and if it is, whether the
  result can still be simply batched up. If either case is true, process
  all chunks of a file in one go and use ``ui.write`` once. This reduces
  the time of ``hg diff`` from 3m54s to 2m26s for the test case.

REPOSITORY
  rHG Mercurial

REVISION DETAIL
  https://phab.mercurial-scm.org/D1938

AFFECTED FILES
  mercurial/cmdutil.py
  mercurial/ui.py

CHANGE DETAILS

diff --git a/mercurial/ui.py b/mercurial/ui.py
--- a/mercurial/ui.py
+++ b/mercurial/ui.py
@@ -878,6 +878,18 @@
 
         return "".join(self._buffers.pop())
 
+    def writenolabels(self, **opts):
+        '''check if write actually uses the label'''
+        if self._buffers and not opts.get(r'prompt', False):
+            if not self._bufferapplylabels:
+                return True
+        return self._colormode is None
+    def canbatchlabelwrites(self, **opts):
+        '''check if write calls with labels are batchable'''
+        assert not self.writenolabels()
+        # Windows color printing is special, see ``write``.
+        return self._colormode != 'win32'
+
     def write(self, *args, **opts):
         '''write args to output
 
diff --git a/mercurial/cmdutil.py b/mercurial/cmdutil.py
--- a/mercurial/cmdutil.py
+++ b/mercurial/cmdutil.py
@@ -1615,14 +1615,21 @@
         chunks = patch.diff(repo, node1, node2, match, changes, opts=diffopts,
                             prefix=prefix, relroot=relroot,
                             hunksfilterfn=hunksfilterfn)
-        for chunk, label in patch.diffstatui(util.iterlines(chunks),
-                                             width=width):
-            write(chunk, label=label)
+        chunksiter = patch.diffstatui(util.iterlines(chunks), width=width)
     else:
-        for chunk, label in patch.diffui(repo, node1, node2, match,
-                                         changes, opts=diffopts, prefix=prefix,
-                                         relroot=relroot,
-                                         hunksfilterfn=hunksfilterfn):
+        chunksiter = patch.diffui(repo, node1, node2, match, changes,
+                                  opts=diffopts, prefix=prefix,
+                                  relroot=relroot, hunksfilterfn=hunksfilterfn)
+
+    if fp is None and ui.writenolabels():
+        write(*(chunk for chunk, label in chunksiter))
+    elif fp is None and ui.canbatchlabelwrites():
+        output = []
+        for chunk, label in chunksiter:
+            output.append(ui.label(chunk, label=label))
+        write(*output)
+    else:
+        for chunk, label in chunksiter:
             write(chunk, label=label)
 
     if listsubrepos:



To: joerg.sonnenberger, #hg-reviewers
Cc: mercurial-devel
_______________________________________________
Mercurial-devel mailing list
Mercurial-devel@mercurial-scm.org
https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel

Reply via email to