[diffoscope] 01/05: Add a simple profiling framework.

Chris Lamb chris at chris-lamb.co.uk
Fri Dec 23 12:46:22 CET 2016


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

lamby pushed a commit to branch master
in repository diffoscope.

commit b50c7d9db84191172493eea0584f4aa2a5f2eaf1
Author: Chris Lamb <lamby at debian.org>
Date:   Fri Dec 23 11:35:58 2016 +0000

    Add a simple profiling framework.
---
 diffoscope/main.py      |  6 +++++
 diffoscope/profiling.py | 66 +++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 72 insertions(+)

diff --git a/diffoscope/main.py b/diffoscope/main.py
index 456a82d..7775d46 100644
--- a/diffoscope/main.py
+++ b/diffoscope/main.py
@@ -35,6 +35,7 @@ from diffoscope.exc import RequiredToolNotFound
 from diffoscope.config import Config
 from diffoscope.difference import Difference
 from diffoscope.progress import ProgressManager, Progress
+from diffoscope.profiling import ProfileManager
 from diffoscope.presenters.html import output_html, output_html_directory, \
     JQUERY_SYSTEM_LOCATIONS
 from diffoscope.presenters.text import output_text
@@ -92,6 +93,8 @@ def create_parser():
                         '"disable" to disable JavaScript. When omitted '
                         'diffoscope will try to create a symlink to a system '
                         'installation. Known locations: %s' % ', '.join(JQUERY_SYSTEM_LOCATIONS))
+    group1.add_argument('--profile', metavar='OUTPUT_FILE', dest='profile_output',
+                        help='Write profiling info to given file (use - for stdout)')
 
     group2 = parser.add_argument_group('output limits')
     group2.add_argument('--no-default-limits', action='store_true', default=False,
@@ -270,6 +273,9 @@ def run_diffoscope(parsed_args):
         if parsed_args.html_output_directory:
             output_html_directory(parsed_args.html_output_directory, difference,
                 css_url=parsed_args.css_url, jquery_url=parsed_args.jquery_url)
+    if parsed_args.profile_output:
+        with make_printer(parsed_args.profile_output) as print_func:
+            ProfileManager().output(print_func)
     return retcode
 
 
diff --git a/diffoscope/profiling.py b/diffoscope/profiling.py
new file mode 100644
index 0000000..9b2f2fe
--- /dev/null
+++ b/diffoscope/profiling.py
@@ -0,0 +1,66 @@
+# -*- coding: utf-8 -*-
+#
+# diffoscope: in-depth comparison of files, archives, and directories
+#
+# Copyright © 2016 Chris Lamb <lamby at debian.org>
+#
+# diffoscope is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# diffoscope is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with diffoscope.  If not, see <https://www.gnu.org/licenses/>.
+
+import sys
+import time
+import contextlib
+import collections
+
+ at contextlib.contextmanager
+def profile(namespace, key):
+    start = time.time()
+    yield
+    ProfileManager().increment(start, namespace, key)
+
+class ProfileManager(object):
+    _singleton = {}
+
+    def __init__(self):
+        self.__dict__ = self._singleton
+
+        if not self._singleton:
+            self.data = collections.defaultdict(
+                lambda: collections.defaultdict(float),
+            )
+
+    def increment(self, start, namespace, key):
+        if not isinstance(key, str):
+            key = '{}.{}'.format(
+                key.__class__.__module__,
+                key.__class__.__name__,
+            )
+
+        self.data[namespace][key] += time.time() - start
+
+    def output(self, print):
+        title = "Profiling output for: {}".format(' '.join(sys.argv))
+
+        print(title)
+        print("=" * len(title))
+
+        for namespace, keys in sorted(self.data.items(), key=lambda x: x[0]):
+            subtitle = "{} (total: {:.3f}s)".format(
+                namespace,
+                sum(keys.values()),
+            )
+
+            print("\n{}\n{}\n".format(subtitle, "-" * len(subtitle)))
+
+            for value, total in sorted(keys.items(), key=lambda x: x[1], reverse=True):
+                print("  {:10.3f}s  {}".format(total, value))

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/reproducible/diffoscope.git


More information about the diffoscope mailing list