From 176711bd1fde814e9c441ae44132eb600063ec7a Mon Sep 17 00:00:00 2001 From: William Deegan Date: Thu, 13 Apr 2023 14:51:01 -0700 Subject: updated copyright and added csv results output to bench.py --- bench/bench.py | 113 +++++++++++++++++++++++++++++++++++++++------------ bench/lvars-gvars.py | 33 ++++++++++++--- 2 files changed, 116 insertions(+), 30 deletions(-) diff --git a/bench/bench.py b/bench/bench.py index aad0fb4..5adac23 100644 --- a/bench/bench.py +++ b/bench/bench.py @@ -1,34 +1,59 @@ #!/usr/bin/env python +# MIT License # -# __COPYRIGHT__ +# Copyright The SCons Foundation # -# A script for timing snippets of Python code. +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: # -# By default, this script will execute a single Python file specified on -# the command line and time any functions in a list named "FunctionList" -# set by the Python file under test, or (by default) time any functions -# in the file whose names begin with "Func". +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. # -# All functions are assumed to get passed the same arguments, and the -# inputs are specified in a list named "Data," each element of which -# is a list consisting of a tag name, a list of positional arguments, -# and a dictionary of keyword arguments. -# -# Each function is expected to test a single, comparable snippet of -# of Python code. IMPORTANT: We want to test the timing of the code -# itself, not Python function call overhead, so every function should -# put its code under test within the following block: -# -# for i in IterationList: -# -# This will allow (as much as possible) us to time just the code itself, -# not Python function call overhead. +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +A script for timing snippets of Python code. + +By default, this script will execute a single Python file specified on +the command line and time any functions in a list named "FunctionList" +set by the Python file under test, or (by default) time any functions +in the file whose names begin with "Func". + +All functions are assumed to get passed the same arguments, and the +inputs are specified in a list named "Data," each element of which +is a list consisting of a tag name, a list of positional arguments, +and a dictionary of keyword arguments. + +Each function is expected to test a single, comparable snippet of +of Python code. IMPORTANT: We want to test the timing of the code +itself, not Python function call overhead, so every function should +put its code under test within the following block: + + for i in IterationList: + +This will allow (as much as possible) us to time just the code itself, +not Python function call overhead. +""" from __future__ import division, print_function import getopt +import os.path import sys import time import types +from pprint import pprint + Usage = """\ Usage: bench.py OPTIONS file.py @@ -105,6 +130,11 @@ if len(args) != 1: sys.stderr.write(Usage) sys.exit(1) + +(bench_name,_) = os.path.splitext(args[0]) +print(f"Bench: {bench_name} : {args[0]}") +results_filename = f"{bench_name}_results.csv" + with open(args[0], 'r') as f: exec(f.read()) @@ -118,6 +148,7 @@ except NameError: IterationList = [None] * Iterations + def timer(func, *args, **kw): results = [] for i in range(Runs): @@ -127,20 +158,52 @@ def timer(func, *args, **kw): results.append((finish - start) / Iterations) return results -def display(label, results): + +results_dict = {} + + +def display(func, result_label, results): total = 0.0 for r in results: total += r - print(" %8.3f" % ((total * 1e6) / len(results)), ':', label) + + test_result = (total * 1e6) / len(results) + print(" %8.3f" % (test_result), ':', result_label) + if results_dict.get(func.__doc__, False): + results_dict[func.__doc__][result_label] = test_result + else: + results_dict[func.__doc__] = { result_label: test_result} + for func in FunctionList: - if func.__doc__: d = ' (' + func.__doc__ + ')' - else: d = '' + if func.__doc__: + d = ' (' + func.__doc__ + ')' + else: + d = '' print(func.__name__ + d + ':') for label, args, kw in Data: r = timer(func, *args, **kw) - display(label, r) + # print(f"{label} {r}") + display(func, label, r) + +py_ver_string = "%d.%d"%(sys.version_info.major, sys.version_info.minor) + + +# pprint(results_dict) +# breakpoint() +tests = [label for label, args, kw in Data] +columns = ['Python Version', 'Implementation', 'Test'] + tests +with open(results_filename, 'a') as r: + print("Python Version,%s" % ".".join(columns), file=r) + # print("Python Version,%s" % ".".join(columns)) + + for implementation in results_dict.keys(): + for test in tests: + print(f'{py_ver_string},"{implementation}","{test}",%8.3f' % results_dict[implementation][test], file=r) + # print(f'{py_ver_string},"{implementation}","{test}",%8.3f' % results_dict[implementation][test]) + + # Local Variables: # tab-width:4 diff --git a/bench/lvars-gvars.py b/bench/lvars-gvars.py index 1511203..0a81337 100644 --- a/bench/lvars-gvars.py +++ b/bench/lvars-gvars.py @@ -1,9 +1,32 @@ -# __COPYRIGHT__ +# MIT License # -# Functions and data for timing different idioms for fetching a keyword -# value from a pair of dictionaries for localand global values. This was -# used to select how to most efficiently expand single $KEYWORD strings -# in src/engine/SCons/Subst.py. +# Copyright The SCons Foundation +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +""" +Functions and data for timing different idioms for fetching a keyword +value from a pair of dictionaries for localand global values. This was +used to select how to most efficiently expand single $KEYWORD strings +in src/engine/SCons/Subst.py. +""" def Func1(var, gvars, lvars): """lvars try:-except:, gvars try:-except:""" -- cgit v0.12