Skip to content

Commit 63d8998

Browse files
author
y-p
committed
Merge pull request #3734 from y-p/PR_test_perf_pickle_compare
BLD: test_perf.py, add --base-pickle --target-pickle options to test_perf
2 parents 4d4c2e0 + 0e0f838 commit 63d8998

File tree

1 file changed

+113
-29
lines changed

1 file changed

+113
-29
lines changed

vb_suite/test_perf.py

Lines changed: 113 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,18 @@
3737
import random
3838
import numpy as np
3939

40+
import pandas as pd
4041
from pandas import DataFrame, Series
4142

43+
try:
44+
import git # gitpython
45+
except Exception:
46+
print("Error: Please install the `gitpython` package\n")
47+
sys.exit(1)
48+
4249
from suite import REPO_PATH
4350

51+
VB_DIR = os.path.dirname(os.path.abspath(__file__))
4452
DEFAULT_MIN_DURATION = 0.01
4553
HEAD_COL="head[ms]"
4654
BASE_COL="base[ms]"
@@ -57,6 +65,14 @@
5765
parser.add_argument('-t', '--target-commit',
5866
help='The commit to compare against the baseline (default: HEAD).',
5967
type=str)
68+
parser.add_argument('--base-pickle',
69+
help='name of pickle file with timings data generated by a former `-H -d FILE` run. '\
70+
'filename must be of the form <hash>-*.* or specify --base-commit seperately',
71+
type=str)
72+
parser.add_argument('--target-pickle',
73+
help='name of pickle file with timings data generated by a former `-H -d FILE` run '\
74+
'filename must be of the form <hash>-*.* or specify --target-commit seperately',
75+
type=str)
6076
parser.add_argument('-m', '--min-duration',
6177
help='Minimum duration (in ms) of baseline test for inclusion in report (default: %.3f).' % DEFAULT_MIN_DURATION,
6278
type=float,
@@ -104,8 +120,7 @@
104120
parser.add_argument('-a', '--affinity',
105121
metavar="a",
106122
dest='affinity',
107-
default=1,
108-
type=int,
123+
default=None,
109124
help='set processor affinity of processm by default bind to cpu/core #1 only'
110125
'requires the "affinity" python module , will raise Warning otherwise' )
111126

@@ -206,21 +221,34 @@ def profile_comparative(benchmarks):
206221

207222
head_res = get_results_df(db, h_head)
208223
baseline_res = get_results_df(db, h_baseline)
209-
totals = prep_totals(baseline_res, head_res)
210-
211-
h_msg = repo.messages.get(h_head, "")
212-
b_msg = repo.messages.get(h_baseline, "")
213224

214-
print_report(totals,h_head=h_head,h_msg=h_msg,
215-
h_baseline=h_baseline,b_msg=b_msg)
225+
report_comparative(head_res,baseline_res)
216226

217-
if args.outdf:
218-
prprint("The results DataFrame was written to '%s'\n" % args.outdf)
219-
totals.save(args.outdf)
220227
finally:
221228
# print("Disposing of TMP_DIR: %s" % TMP_DIR)
222229
shutil.rmtree(TMP_DIR)
223230

231+
def prep_pickle_for_total(df, agg_name='median'):
232+
"""
233+
accepts a datafram resulting from invocation with -H -d o.pickle
234+
If multiple data columns are present (-N was used), the
235+
`agg_name` attr of the datafram will be used to reduce
236+
them to a single value per vbench, df.median is used by defa
237+
ult.
238+
239+
Returns a datadrame of the form expected by prep_totals
240+
"""
241+
def prep(df):
242+
agg = getattr(df,agg_name)
243+
df = DataFrame(agg(1))
244+
cols = list(df.columns)
245+
cols[0]='timing'
246+
df.columns=cols
247+
df['name'] = list(df.index)
248+
return df
249+
250+
return prep(df)
251+
224252
def prep_totals(head_res, baseline_res):
225253
"""
226254
Each argument should be a dataframe with 'timing' and 'name' columns
@@ -241,6 +269,27 @@ def prep_totals(head_res, baseline_res):
241269
).sort("ratio").set_index('name') # sort in ascending order
242270
return totals
243271

272+
def report_comparative(head_res,baseline_res):
273+
try:
274+
r=git.Repo(VB_DIR)
275+
except:
276+
import pdb
277+
pdb.set_trace()
278+
279+
totals = prep_totals(head_res,baseline_res)
280+
281+
h_head = args.target_commit
282+
h_baseline = args.base_commit
283+
h_msg = r.commit(h_head).message.strip()
284+
b_msg = r.commit(h_baseline).message.strip()
285+
286+
print_report(totals,h_head=h_head,h_msg=h_msg,
287+
h_baseline=h_baseline,b_msg=b_msg)
288+
289+
if args.outdf:
290+
prprint("The results DataFrame was written to '%s'\n" % args.outdf)
291+
totals.save(args.outdf)
292+
244293
def profile_head_single(benchmark):
245294
import gc
246295
results = []
@@ -398,18 +447,23 @@ def main():
398447
random.seed(args.seed)
399448
np.random.seed(args.seed)
400449

401-
try:
402-
import affinity
403-
affinity.set_process_affinity_mask(0,args.affinity)
404-
assert affinity.get_process_affinity_mask(0) == args.affinity
405-
print("CPU affinity set to %d" % args.affinity)
406-
except ImportError:
407-
import warnings
408-
print("\n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"+
409-
"The 'affinity' module is not available, results may be unreliable\n" +
410-
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"
411-
)
412-
time.sleep(2)
450+
if args.base_pickle and args.target_pickle:
451+
baseline_res = prep_pickle_for_total(pd.load(args.base_pickle))
452+
target_res = prep_pickle_for_total(pd.load(args.target_pickle))
453+
454+
report_comparative(target_res, baseline_res)
455+
sys.exit(0)
456+
457+
if args.affinity is not None:
458+
try:
459+
import affinity
460+
461+
affinity.set_process_affinity_mask(0,args.affinity)
462+
assert affinity.get_process_affinity_mask(0) == args.affinity
463+
print("CPU affinity set to %d" % args.affinity)
464+
except ImportError:
465+
print("-a/--afinity specified, but the 'affinity' module is not available, aborting.\n")
466+
sys.exit(1)
413467

414468
print("\n")
415469
prprint("LOG_FILE = %s" % args.log_file)
@@ -489,10 +543,40 @@ def inner(repo_path):
489543

490544
if __name__ == '__main__':
491545
args = parser.parse_args()
492-
if not args.head and (not args.base_commit and not args.target_commit):
546+
if (not args.head
547+
and not (args.base_commit and args.target_commit)
548+
and not (args.base_pickle and args.target_pickle)):
493549
parser.print_help()
494-
else:
495-
import warnings
496-
warnings.filterwarnings('ignore',category=FutureWarning)
497-
warnings.filterwarnings('ignore',category=DeprecationWarning)
498-
main()
550+
sys.exit(1)
551+
elif ((args.base_pickle or args.target_pickle) and not
552+
(args.base_pickle and args.target_pickle)):
553+
print("Must specify Both --base-pickle and --target-pickle.")
554+
sys.exit(1)
555+
556+
if ((args.base_pickle or args.target_pickle) and not
557+
(args.base_commit and args.target_commit)):
558+
if not args.base_commit:
559+
print("base_commit not specified, Assuming base_pickle is named <commit>-foo.*")
560+
args.base_commit = args.base_pickle.split('-')[0]
561+
if not args.target_commit:
562+
print("target_commit not specified, Assuming target_pickle is named <commit>-foo.*")
563+
print(args.target_pickle.split('-')[0])
564+
args.target_commit = args.target_pickle.split('-')[0]
565+
566+
import warnings
567+
warnings.filterwarnings('ignore',category=FutureWarning)
568+
warnings.filterwarnings('ignore',category=DeprecationWarning)
569+
570+
if args.base_commit and args.target_commit:
571+
print("Verifying specified commits exist in repo...")
572+
r=git.Repo(VB_DIR)
573+
for c in [ args.base_commit, args.target_commit ]:
574+
try:
575+
msg = r.commit(c).message.strip()
576+
except git.BadObject:
577+
print("The commit '%s' was not found, aborting" % c)
578+
sys.exit(1)
579+
else:
580+
print("%s: %s" % (c,msg))
581+
582+
main()

0 commit comments

Comments
 (0)