From 8c96ae6765aa708a3569f96cfaf19c751e0855e5 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 25 May 2020 23:24:05 -0400 Subject: [PATCH] Updates for examples/performance added --sort option and also --raw option from 6b3513f56c2a5d3ba45215b2438c47dba4336740 Change-Id: I42ef2135db08c87f33b51faed9c8bbff510c9e9b --- .../changelog/unreleased_13/perf_suite.rst | 7 +++ examples/performance/__init__.py | 63 ++++++++++--------- 2 files changed, 39 insertions(+), 31 deletions(-) create mode 100644 doc/build/changelog/unreleased_13/perf_suite.rst diff --git a/doc/build/changelog/unreleased_13/perf_suite.rst b/doc/build/changelog/unreleased_13/perf_suite.rst new file mode 100644 index 0000000000..f928cd3ed3 --- /dev/null +++ b/doc/build/changelog/unreleased_13/perf_suite.rst @@ -0,0 +1,7 @@ +.. change:: + :tags: change, examples + + Added new option ``--raw`` to the examples.performance suite + which will dump the raw profile test for consumption by any + number of profiling visualizer tools. Removed the "runsnake" + option as runsnake is very hard to build at this point; diff --git a/examples/performance/__init__.py b/examples/performance/__init__.py index c6244554fa..f4f53f0d50 100644 --- a/examples/performance/__init__.py +++ b/examples/performance/__init__.py @@ -107,15 +107,6 @@ individual tests:: ... -Using RunSnake --------------- - -This option requires the `RunSnake `_ -command line tool be installed:: - - $ python -m examples.performance single_inserts --test test_core --num 1000 --runsnake - -A graphical RunSnake output will be displayed. .. _examples_profiling_writeyourown: @@ -213,9 +204,6 @@ We can run our new script directly:: test_joinedload : load everything, joined eager loading. (1000 iterations); total time 2.754592 sec test_subqueryload : load everything, subquery eager loading. (1000 iterations); total time 2.977696 sec -As well as see RunSnake output for an individual test:: - - $ python test_loads.py --num 100 --runsnake --test test_joinedload """ # noqa import argparse @@ -238,12 +226,13 @@ class Profiler(object): def __init__(self, options): self.test = options.test self.dburl = options.dburl - self.runsnake = options.runsnake self.profile = options.profile self.dump = options.dump + self.raw = options.raw self.callers = options.callers self.num = options.num self.echo = options.echo + self.sort = options.sort self.stats = [] @classmethod @@ -292,7 +281,7 @@ class Profiler(object): self._run_test(test) self.stats[-1].report() - def _run_with_profile(self, fn): + def _run_with_profile(self, fn, sort): pr = cProfile.Profile() pr.enable() try: @@ -300,9 +289,9 @@ class Profiler(object): finally: pr.disable() - stats = pstats.Stats(pr).sort_stats("cumulative") + stats = pstats.Stats(pr) - self.stats.append(TestResult(self, fn, stats=stats)) + self.stats.append(TestResult(self, fn, stats=stats, sort=sort)) return result def _run_with_time(self, fn): @@ -316,8 +305,8 @@ class Profiler(object): def _run_test(self, fn): if self._setup: self._setup(self.dburl, self.echo, self.num) - if self.profile or self.runsnake or self.dump: - self._run_with_profile(fn) + if self.profile or self.dump: + self._run_with_profile(fn, self.sort) else: self._run_with_time(fn) @@ -358,20 +347,26 @@ class Profiler(object): action="store_true", help="run profiling and dump call counts", ) + parser.add_argument( + "--sort", + type=str, + default="cumulative", + help="profiling sort, defaults to cumulative", + ) parser.add_argument( "--dump", action="store_true", help="dump full call profile (implies --profile)", ) parser.add_argument( - "--callers", - action="store_true", - help="print callers as well (implies --dump)", + "--raw", + type=str, + help="dump raw profile data to file (implies --profile)", ) parser.add_argument( - "--runsnake", + "--callers", action="store_true", - help="invoke runsnakerun (implies --profile)", + help="print callers as well (implies --dump)", ) parser.add_argument( "--echo", action="store_true", help="Echo SQL output" @@ -379,7 +374,7 @@ class Profiler(object): args = parser.parse_args() args.dump = args.dump or args.callers - args.profile = args.profile or args.dump or args.runsnake + args.profile = args.profile or args.dump or args.raw if cls.name is None: __import__(__name__ + "." + args.name) @@ -397,11 +392,14 @@ class Profiler(object): class TestResult(object): - def __init__(self, profile, test, stats=None, total_time=None): + def __init__( + self, profile, test, stats=None, total_time=None, sort="cumulative" + ): self.profile = profile self.test = test self.stats = stats self.total_time = total_time + self.sort = sort def report(self): print(self._summary()) @@ -421,17 +419,20 @@ class TestResult(object): return summary def report_stats(self): - if self.profile.runsnake: - self._runsnake() - elif self.profile.dump: - self._dump() + if self.profile.dump: + self._dump(self.sort) + elif self.profile.raw: + self._dump_raw() - def _dump(self): - self.stats.sort_stats("time", "calls") + def _dump(self, sort): + self.stats.sort_stats(*re.split(r"[ ,]", self.sort)) self.stats.print_stats() if self.profile.callers: self.stats.print_callers() + def _dump_raw(self): + self.stats.dump_stats(self.profile.raw) + def _runsnake(self): filename = "%s.profile" % self.test.__name__ try: -- 2.39.5