Some changes/additions to debug.nas
Add benchmark_time, rank, and print_rank. Modify benchmark to return/ pass-through the values of the function, appending to a vector if there are multiple executions.
This commit is contained in:
parent
0b49cd942c
commit
642ebfa696
1 changed files with 105 additions and 10 deletions
111
Nasal/debug.nas
111
Nasal/debug.nas
|
@ -32,10 +32,25 @@
|
|||
# debug.isnan() returns 1 if argument is an invalid number (NaN),
|
||||
# 0 if it's a valid number, and nil in all other cases
|
||||
#
|
||||
# debug.benchmark(<label:string>, <func> [, <repeat:int>])
|
||||
# ... runs function <repeat> times (default: 1)
|
||||
# and prints execution time in seconds,
|
||||
# prefixed with <label>.
|
||||
# debug.benchmark(<label:string>, <func> [, <repeat:int> [, <output:vector>]])
|
||||
# ... runs function <repeat> times (default: nil)
|
||||
# and prints total execution time in seconds,
|
||||
# prefixed with <label>, while adding results
|
||||
# to <output>, or returning the only result
|
||||
# if <repeat> is nil.
|
||||
#
|
||||
# debug.benchmark_time(<func> [, <repeat:int> [, <output:vector>]])
|
||||
# ... like debug.benchmark, but returns total
|
||||
# execution time and does not print anything.
|
||||
#
|
||||
# debug.rank(<list:vector> [, <repeat:int>])
|
||||
# ... sorts the list of functions based on execution
|
||||
# time over <repeat> samples (default: 1).
|
||||
#
|
||||
# debug.print_rank(<result:vector>, <names:int>)
|
||||
# ... prints the <result> of debug.rank with <names>
|
||||
# (which can be a vector of [name, func] or
|
||||
# [func, name], or a hash of name:func).
|
||||
#
|
||||
# debug.printerror(<err-vector>) ... prints error vector as set by call()
|
||||
#
|
||||
|
@ -285,17 +300,97 @@ var proptrace = func(root = "/", frames = 2) {
|
|||
|
||||
|
||||
##
|
||||
# Executes function fn "repeat" times and prints execution time in seconds. Examples:
|
||||
# Executes function fn "repeat" times and prints execution time in seconds. If repeat
|
||||
# is an integer and an optional "output" argument is specified, each test's result
|
||||
# is appended to that vector, then the vector is returned. If repeat is nil, then
|
||||
# the funciton is run once and the result returned. Otherwise, the result is discarded.
|
||||
# Examples:
|
||||
#
|
||||
# var test = func { getprop("/sim/aircraft"); }
|
||||
# debug.benchmark("test()/1", test, 1000);
|
||||
# debug.benchmark("test()/2", func setprop("/sim/aircraft", ""), 1000);
|
||||
#
|
||||
var benchmark = func(label, fn, repeat = 1) {
|
||||
var start = systime();
|
||||
# var results = debug.benchmark("test()", test, 1000, []);
|
||||
# print(" Results were:");
|
||||
# print(" ", debug.string(results));
|
||||
#
|
||||
var benchmark = func(label, fn, repeat = nil, output=nil) {
|
||||
var start = var end = nil;
|
||||
if (repeat == nil) {
|
||||
start = systime();
|
||||
output = fn();
|
||||
} elsif (typeof(output) == 'vector') {
|
||||
start = systime();
|
||||
for (var i = 0; i < repeat; i += 1)
|
||||
append(output, fn());
|
||||
} else {
|
||||
start = systime();
|
||||
for (var i = 0; i < repeat; i += 1)
|
||||
fn();
|
||||
print(_bench(sprintf(" %s --> %.6f s ", label, systime() - start)));
|
||||
}
|
||||
end = systime();
|
||||
print(_bench(sprintf(" %s --> %.6f s ", label, end - start)));
|
||||
return output;
|
||||
}
|
||||
|
||||
var benchmark_time = func(fn, repeat = 1, output = nil) {
|
||||
var start = var end = nil;
|
||||
if (repeat == nil) {
|
||||
start = systime();
|
||||
output = fn();
|
||||
} elsif (typeof(output) == 'vector') {
|
||||
start = systime();
|
||||
for (var i = 0; i < repeat; i += 1)
|
||||
append(output, fn());
|
||||
} else {
|
||||
start = systime();
|
||||
for (var i = 0; i < repeat; i += 1)
|
||||
fn();
|
||||
}
|
||||
end = systime();
|
||||
return end - start;
|
||||
}
|
||||
|
||||
##
|
||||
# Executes each function in the list and returns a sorted vector with the fastest
|
||||
# on top (i.e. first). Each position in the result is a vector of [func, time].
|
||||
#
|
||||
var rank = func(list, repeat = nil) {
|
||||
var result = [];
|
||||
foreach (var fn; list) {
|
||||
var time = benchmark_time(fn, repeat);
|
||||
append(result, [fn, time]);
|
||||
}
|
||||
return sort(result, func(a,b) a[1] < b[1] ? -1 : a[1] > b[1] ? 1 : 0);
|
||||
}
|
||||
|
||||
var print_rank = func(label, list, names) {
|
||||
var _vec = (typeof(names) == 'vector');
|
||||
print("Test results for "~label);
|
||||
var first = 1;
|
||||
var longest = list[-1][1];
|
||||
foreach (var item; list) {
|
||||
var (fn, time) = item;
|
||||
var name = nil;
|
||||
if (_vec) {
|
||||
foreach (var l; names) {
|
||||
if (l[1] == fn) {
|
||||
name = l[0]; break;
|
||||
} elsif (l[0] == fn) {
|
||||
name = l[1]; break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (var name; keys(names)) {
|
||||
if (names[name] == fn) break;
|
||||
else name = nil;
|
||||
}
|
||||
}
|
||||
if (name == nil) die("function not found");
|
||||
print(" "~name~(first?" (fastest)":"")~" took "~(time*1000)~" ms ("~(time/longest*100)~"%) time");
|
||||
first = 0;
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue