summaryrefslogtreecommitdiff
path: root/perf
diff options
context:
space:
mode:
Diffstat (limited to 'perf')
-rw-r--r--perf/bug397.py54
-rw-r--r--perf/perf_measure.py188
-rw-r--r--perf/solve_poly.py246
3 files changed, 0 insertions, 488 deletions
diff --git a/perf/bug397.py b/perf/bug397.py
deleted file mode 100644
index 18c979b8..00000000
--- a/perf/bug397.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/env python
-"""
-Run this file two ways under coverage and see that the times are the same:
-
- $ coverage run lab/bug397.py slow
- Runtime per example: 130.96 +/- 3.70 us
- $ coverage run lab/bug397.py fast
- Runtime per example: 131.34 +/- 4.48 us
-
-Written by David MacIver as part of https://github.com/nedbat/coveragepy/issues/397
-
-"""
-
-import sys
-import random
-import time
-import math
-
-if sys.argv[1] == "slow":
- sys.settrace(sys.gettrace())
-
-random.seed(1)
-
-
-def hash_str(s):
- h = 0
- for c in s:
- h = (h * 31 + ord(c)) & (2 ** 64 - 1)
- return h
-
-data = [
- hex(random.getrandbits(1024)) for _ in range(500)
-]
-
-N_SAMPLES = 100
-
-
-def mean(xs):
- xs = list(xs)
- return sum(xs) / len(xs)
-
-
-def sd(xs):
- return math.sqrt(mean(x ** 2 for x in xs) - mean(xs) ** 2)
-
-
-if __name__ == '__main__':
- timing = []
- for _ in range(N_SAMPLES):
- start = time.time()
- for d in data:
- hash_str(d)
- timing.append(1000000 * (time.time() - start) / len(data))
- print("Runtime per example:", f"{mean(timing):.2f} +/- {sd(timing):.2f} us")
diff --git a/perf/perf_measure.py b/perf/perf_measure.py
deleted file mode 100644
index e8f9ea98..00000000
--- a/perf/perf_measure.py
+++ /dev/null
@@ -1,188 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
-
-# Run like this:
-# .tox/py36/bin/python perf/perf_measure.py
-
-from collections import namedtuple
-import os
-import statistics
-import sys
-import tempfile
-import time
-
-from unittest_mixins.mixins import make_file
-
-import coverage
-from coverage.misc import import_local_file
-
-from tests.helpers import SuperModuleCleaner
-
-
-class StressResult(namedtuple('StressResult', ['files', 'calls', 'lines', 'baseline', 'covered'])):
- @property
- def overhead(self):
- return self.covered - self.baseline
-
-
-TEST_FILE = """\
-def parent(call_count, line_count):
- for _ in range(call_count):
- child(line_count)
-
-def child(line_count):
- for i in range(line_count):
- x = 1
-"""
-
-def mk_main(file_count, call_count, line_count):
- lines = []
- lines.extend(
- f"import test{idx}" for idx in range(file_count)
- )
- lines.extend(
- f"test{idx}.parent({call_count}, {line_count})" for idx in range(file_count)
- )
- return "\n".join(lines)
-
-
-class StressTest:
-
- def __init__(self):
- self.module_cleaner = SuperModuleCleaner()
-
- def _run_scenario(self, file_count, call_count, line_count):
- self.module_cleaner.clean_local_file_imports()
-
- for idx in range(file_count):
- make_file(f'test{idx}.py', TEST_FILE)
- make_file('testmain.py', mk_main(file_count, call_count, line_count))
-
- # Run it once just to get the disk caches loaded up.
- import_local_file("testmain")
- self.module_cleaner.clean_local_file_imports()
-
- # Run it to get the baseline time.
- start = time.perf_counter()
- import_local_file("testmain")
- baseline = time.perf_counter() - start
- self.module_cleaner.clean_local_file_imports()
-
- # Run it to get the covered time.
- start = time.perf_counter()
- cov = coverage.Coverage()
- cov.start()
- try: # pragma: nested
- # Import the Python file, executing it.
- import_local_file("testmain")
- finally: # pragma: nested
- # Stop coverage.py.
- covered = time.perf_counter() - start
- stats = cov._collector.tracers[0].get_stats()
- if stats:
- stats = stats.copy()
- cov.stop()
-
- return baseline, covered, stats
-
- def _compute_overhead(self, file_count, call_count, line_count):
- baseline, covered, stats = self._run_scenario(file_count, call_count, line_count)
-
- #print("baseline = {:.2f}, covered = {:.2f}".format(baseline, covered))
- # Empirically determined to produce the same numbers as the collected
- # stats from get_stats(), with Python 3.6.
- actual_file_count = 17 + file_count
- actual_call_count = file_count * call_count + 156 * file_count + 85
- actual_line_count = (
- 2 * file_count * call_count * line_count +
- 3 * file_count * call_count +
- 769 * file_count +
- 345
- )
-
- if stats is not None:
- assert actual_file_count == stats['files']
- assert actual_call_count == stats['calls']
- assert actual_line_count == stats['lines']
- print("File counts", file_count, actual_file_count, stats['files'])
- print("Call counts", call_count, actual_call_count, stats['calls'])
- print("Line counts", line_count, actual_line_count, stats['lines'])
- print()
-
- return StressResult(
- actual_file_count,
- actual_call_count,
- actual_line_count,
- baseline,
- covered,
- )
-
- fixed = 200
- numlo = 100
- numhi = 100
- step = 50
- runs = 5
-
- def count_operations(self):
-
- def operations(thing):
- for _ in range(self.runs):
- for n in range(self.numlo, self.numhi+1, self.step):
- kwargs = {
- "file_count": self.fixed,
- "call_count": self.fixed,
- "line_count": self.fixed,
- }
- kwargs[thing+"_count"] = n
- yield kwargs['file_count'] * kwargs['call_count'] * kwargs['line_count']
-
- ops = sum(sum(operations(thing)) for thing in ["file", "call", "line"])
- print(f"{ops/1e6:.1f}M operations")
-
- def check_coefficients(self):
- # For checking the calculation of actual stats:
- for f in range(1, 6):
- for c in range(1, 6):
- for l in range(1, 6):
- _, _, stats = self._run_scenario(f, c, l)
- print("{0},{1},{2},{3[files]},{3[calls]},{3[lines]}".format(f, c, l, stats))
-
- def stress_test(self):
- # For checking the overhead for each component:
- def time_thing(thing):
- per_thing = []
- pct_thing = []
- for _ in range(self.runs):
- for n in range(self.numlo, self.numhi+1, self.step):
- kwargs = {
- "file_count": self.fixed,
- "call_count": self.fixed,
- "line_count": self.fixed,
- }
- kwargs[thing+"_count"] = n
- res = self._compute_overhead(**kwargs)
- per_thing.append(res.overhead / getattr(res, f"{thing}s"))
- pct_thing.append(res.covered / res.baseline * 100)
-
- out = f"Per {thing}: "
- out += "mean = {:9.3f}us, stddev = {:8.3f}us, ".format(
- statistics.mean(per_thing)*1e6, statistics.stdev(per_thing)*1e6
- )
- out += f"min = {min(per_thing)*1e6:9.3f}us, "
- out += "pct = {:6.1f}%, stddev = {:6.1f}%".format(
- statistics.mean(pct_thing), statistics.stdev(pct_thing)
- )
- print(out)
-
- time_thing("file")
- time_thing("call")
- time_thing("line")
-
-
-if __name__ == '__main__':
- with tempfile.TemporaryDirectory(prefix="coverage_stress_") as tempdir:
- print(f"Working in {tempdir}")
- os.chdir(tempdir)
- sys.path.insert(0, ".")
-
- StressTest().stress_test()
diff --git a/perf/solve_poly.py b/perf/solve_poly.py
deleted file mode 100644
index 083dc544..00000000
--- a/perf/solve_poly.py
+++ /dev/null
@@ -1,246 +0,0 @@
-# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0
-# For details: https://github.com/nedbat/coveragepy/blob/master/NOTICE.txt
-
-# Given empirical data from perf_measure.py, calculate the coefficients of the
-# polynomials for file, call, and line operation counts.
-#
-# Written by Kyle Altendorf.
-
-import attr
-import itertools
-import numpy
-import scipy.optimize
-
-
-def f(*args, simplify=False):
- p = ((),)
- for l in range(len(args)):
- l += 1
- p = itertools.chain(p, itertools.product(*(args,), repeat=l))
-
- if simplify:
- p = {tuple(sorted(set(x))) for x in p}
- p = sorted(p, key=lambda x: (len(x), x))
-
- return p
-
-def m(*args):
- if len(args) == 0:
- return 0
-
- r = 1
- for arg in args:
- r *= arg
-
- return r
-
-
-class Poly:
- def __init__(self, *names):
- self.names = names
-
- self.terms = f(*self.names, simplify=True)
-
- def calculate(self, coefficients, **name_values):
- for name in name_values:
- if name not in self.names:
- raise Exception('bad parameter')
-
- substituted_terms = []
- for term in self.terms:
- substituted_terms.append(tuple(name_values[name] for name in term))
-
- c_tuples = ((c,) for c in coefficients)
-
- terms = tuple(a + b for a, b in zip(c_tuples, substituted_terms))
-
- multiplied = tuple(m(*t) for t in terms)
- total = sum(multiplied)
-
- return total
-
-
-poly = Poly('f', 'c', 'l')
-
-#print('\n'.join(str(t) for t in poly.terms))
-
-@attr.s
-class FCL:
- f = attr.ib()
- c = attr.ib()
- l = attr.ib()
-
-INPUT = """\
-1,1,1,18,242,1119
-1,1,2,18,242,1121
-1,1,3,18,242,1123
-1,1,4,18,242,1125
-1,1,5,18,242,1127
-1,2,1,18,243,1124
-1,2,2,18,243,1128
-1,2,3,18,243,1132
-1,2,4,18,243,1136
-1,2,5,18,243,1140
-1,3,1,18,244,1129
-1,3,2,18,244,1135
-1,3,3,18,244,1141
-1,3,4,18,244,1147
-1,3,5,18,244,1153
-1,4,1,18,245,1134
-1,4,2,18,245,1142
-1,4,3,18,245,1150
-1,4,4,18,245,1158
-1,4,5,18,245,1166
-1,5,1,18,246,1139
-1,5,2,18,246,1149
-1,5,3,18,246,1159
-1,5,4,18,246,1169
-1,5,5,18,246,1179
-2,1,1,19,399,1893
-2,1,2,19,399,1897
-2,1,3,19,399,1901
-2,1,4,19,399,1905
-2,1,5,19,399,1909
-2,2,1,19,401,1903
-2,2,2,19,401,1911
-2,2,3,19,401,1919
-2,2,4,19,401,1927
-2,2,5,19,401,1935
-2,3,1,19,403,1913
-2,3,2,19,403,1925
-2,3,3,19,403,1937
-2,3,4,19,403,1949
-2,3,5,19,403,1961
-2,4,1,19,405,1923
-2,4,2,19,405,1939
-2,4,3,19,405,1955
-2,4,4,19,405,1971
-2,4,5,19,405,1987
-2,5,1,19,407,1933
-2,5,2,19,407,1953
-2,5,3,19,407,1973
-2,5,4,19,407,1993
-2,5,5,19,407,2013
-3,1,1,20,556,2667
-3,1,2,20,556,2673
-3,1,3,20,556,2679
-3,1,4,20,556,2685
-3,1,5,20,556,2691
-3,2,1,20,559,2682
-3,2,2,20,559,2694
-3,2,3,20,559,2706
-3,2,4,20,559,2718
-3,2,5,20,559,2730
-3,3,1,20,562,2697
-3,3,2,20,562,2715
-3,3,3,20,562,2733
-3,3,4,20,562,2751
-3,3,5,20,562,2769
-3,4,1,20,565,2712
-3,4,2,20,565,2736
-3,4,3,20,565,2760
-3,4,4,20,565,2784
-3,4,5,20,565,2808
-3,5,1,20,568,2727
-3,5,2,20,568,2757
-3,5,3,20,568,2787
-3,5,4,20,568,2817
-3,5,5,20,568,2847
-4,1,1,21,713,3441
-4,1,2,21,713,3449
-4,1,3,21,713,3457
-4,1,4,21,713,3465
-4,1,5,21,713,3473
-4,2,1,21,717,3461
-4,2,2,21,717,3477
-4,2,3,21,717,3493
-4,2,4,21,717,3509
-4,2,5,21,717,3525
-4,3,1,21,721,3481
-4,3,2,21,721,3505
-4,3,3,21,721,3529
-4,3,4,21,721,3553
-4,3,5,21,721,3577
-4,4,1,21,725,3501
-4,4,2,21,725,3533
-4,4,3,21,725,3565
-4,4,4,21,725,3597
-4,4,5,21,725,3629
-4,5,1,21,729,3521
-4,5,2,21,729,3561
-4,5,3,21,729,3601
-4,5,4,21,729,3641
-4,5,5,21,729,3681
-5,1,1,22,870,4215
-5,1,2,22,870,4225
-5,1,3,22,870,4235
-5,1,4,22,870,4245
-5,1,5,22,870,4255
-5,2,1,22,875,4240
-5,2,2,22,875,4260
-5,2,3,22,875,4280
-5,2,4,22,875,4300
-5,2,5,22,875,4320
-5,3,1,22,880,4265
-5,3,2,22,880,4295
-5,3,3,22,880,4325
-5,3,4,22,880,4355
-5,3,5,22,880,4385
-5,4,1,22,885,4290
-5,4,2,22,885,4330
-5,4,3,22,885,4370
-5,4,4,22,885,4410
-5,4,5,22,885,4450
-5,5,1,22,890,4315
-5,5,2,22,890,4365
-5,5,3,22,890,4415
-5,5,4,22,890,4465
-5,5,5,22,890,4515
-"""
-
-inputs_outputs = {}
-for row in INPUT.splitlines():
- row = [int(v) for v in row.split(",")]
- inputs_outputs[FCL(*row[:3])] = FCL(*row[3:])
-
-#print('\n'.join(str(t) for t in inputs_outputs.items()))
-
-def calc_poly_coeff(poly, coefficients):
- c_tuples = list((c,) for c in coefficients)
- poly = list(f(*poly))
- poly = list(a + b for a, b in zip(c_tuples, poly))
- multiplied = list(m(*t) for t in poly)
- total = sum(multiplied)
- return total
-
-def calc_error(inputs, output, coefficients):
- result = poly.calculate(coefficients, **inputs)
- return result - output
-
-
-def calc_total_error(inputs_outputs, coefficients, name):
- total_error = 0
- for inputs, outputs in inputs_outputs.items():
- total_error += abs(calc_error(attr.asdict(inputs), attr.asdict(outputs)[name], coefficients))
-
- return total_error
-
-coefficient_count = len(poly.terms)
-#print('count: {}'.format(coefficient_count))
-x0 = numpy.array((0,) * coefficient_count)
-
-#print(x0)
-
-with open('results', 'w') as f:
- for name in sorted(attr.asdict(FCL(0,0,0))):
- c = scipy.optimize.minimize(
- fun=lambda c: calc_total_error(inputs_outputs, c, name),
- x0=x0
- )
-
- coefficients = [int(round(x)) for x in c.x]
- terms = [''.join(t) for t in poly.terms]
- message = f"{name}' = "
- message += ' + '.join("{}{}".format(coeff if coeff != 1 else '', term) for coeff, term in reversed(list(zip(coefficients, terms))) if coeff != 0)
- print(message)
- f.write(message)