Skip to content

Commit

Permalink
FEAT: New features for timing functions (Issue #322) (#340)
Browse files Browse the repository at this point in the history
* FEAT: Add various options to timing.py

* TEST: Add tests to timing.py
  • Loading branch information
QBatista authored and mmcky committed Sep 28, 2017
1 parent ecbf2b2 commit f1e33f3
Show file tree
Hide file tree
Showing 3 changed files with 259 additions and 36 deletions.
2 changes: 1 addition & 1 deletion quantecon/util/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
from .array import searchsorted
from .notebooks import fetch_nb_dependencies
from .random import check_random_state
from .timing import tic, tac, toc
from .timing import tic, tac, toc, loop_timer
86 changes: 70 additions & 16 deletions quantecon/util/tests/test_timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,86 @@
Authors: Pablo Winant
Tests for timing.py
"""

import time
from numpy.testing import assert_allclose
from nose.tools import eq_
from quantecon.util import tic, tac, toc, loop_timer


class TestTicTacToc():
def setUp(self):
self.h = 0.1
self.digits = 10

def test_timer(self):
tic()

time.sleep(self.h)
tm1 = float(tac())

time.sleep(self.h)
tm2 = float(tac())

def test_tic_tac_toc():
time.sleep(self.h)
tm3 = float(toc())

from ..timing import tic, tac, toc
import time
rtol = 0.1
for actual, desired in zip([tm1, tm2, tm3], [self.h, self.h, self.h*3]):
assert_allclose(actual, desired, rtol=rtol)

h = 0.1
def test_digits(self):
tic()

time.sleep(self.h)
tm1 = tac(self.digits)

tic()
time.sleep(self.h)
tm2 = tac(self.digits)

time.sleep(h)
el1 = tac()
time.sleep(self.h)
tm3 = toc(self.digits)

eq_(len(str(tm1).split(".")[1]), 10)
eq_(len(str(tm2).split(".")[1]), 10)
eq_(len(str(tm3).split(".")[1]), 10)

def test_output(self):
tic()

time.sleep(self.h)
tm1 = tac(self.digits, True, False)

time.sleep(h)
el2 = tac()
time.sleep(self.h)
tm2 = tac(self.digits, True, False)

time.sleep(h)
el3 = toc()
time.sleep(self.h)
tm3 = toc(self.digits, True, False)

eq_(tm1, None)
eq_(tm2, None)
eq_(tm3, None)

def test_loop(self):
def test_function_one_arg(n):
return time.sleep(n)

rtol = 0.1
for actual, desired in zip([el1, el2, el3], [h, h, h*3]):
assert_allclose(actual, desired, rtol=rtol)
def test_function_two_arg(n, a):
return time.sleep(n)

test_one_arg = loop_timer(5, test_function_one_arg, self.h, 10)
test_two_arg = loop_timer(5, test_function_two_arg, [self.h, 1], 10)
for tm in test_one_arg:
assert(abs(float(tm)-self.h)<0.01)
for tm in test_two_arg:
assert(abs(float(tm)-self.h)<0.01)

if __name__ == "__main__":

if __name__ == '__main__':
import sys
import nose

test_tic_tac_toc()
argv = sys.argv[:]
argv.append('--verbose')
argv.append('--nocapture')
nose.main(argv=argv, defaultTest=__file__)
207 changes: 188 additions & 19 deletions quantecon/util/timing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class __Timer__:
'''Computes elapsed time, between tic, tac, and toc.
"""Computes elapsed time, between tic, tac, and toc.
Methods
-------
Expand All @@ -18,7 +18,10 @@ class __Timer__:
tac :
Returns and prints time elapsed since last
tic(), tac() or toc() whichever occured last.
'''
loop_timer :
Returns and prints the total and average time elapsed for n runs
of a given function.
"""

start = None
last = None
Expand All @@ -32,10 +35,29 @@ def tic(self):
self.start = t
self.last = t

def tac(self):
"""Returns and prints time elapsed since last
tic(), tac() or toc() whichever occured last."""

def tac(self, digits=2, print_output=True, output=True):
"""
Returns and prints time elapsed since last tic(), tac() or toc()
whichever occured last.
Parameters
----------
digits : scalar(int), optional(default=2)
Number of digits for time elapsed.
print_output : bool, optional(default=True)
If True, then prints time.
output : bool, optional(default=True)
If True, then returns time.
Returns
-------
tac : str
Time elapsed since last tic(), tac() or toc().
"""

import time

if self.start is None:
Expand All @@ -44,12 +66,45 @@ def tac(self):
t = time.time()
elapsed = t-self.last
self.last = t

print("TAC: Elapsed: {} seconds.".format(elapsed))
return elapsed

def toc(self):
"""Returns and prints time elapsed since last tic()."""

if print_output:
m, s = divmod(elapsed, 60)
h, m = divmod(m, 60)
print("TAC: Elapsed: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(elapsed, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

tac = rounded_time.split('.')[0] + "." + time_digits

return tac

def toc(self, digits=2, print_output=True, output=True):
"""
Returns and prints time elapsed since last tic().
Parameters
----------
digits : scalar(int), optional(default=2)
Number of digits for time elapsed.
print_output : bool, optional(default=True)
If True, then prints time.
output : bool, optional(default=True)
If True, then returns time.
Returns
-------
toc : str
Time elapsed since last tic().
"""

import time

Expand All @@ -60,9 +115,116 @@ def toc(self):
self.last = t
elapsed = t-self.start

print("TOC: Elapsed: {} seconds.".format(elapsed))
return elapsed

if print_output:
m, s = divmod(elapsed, 60)
h, m = divmod(m, 60)
print("TOC: Elapsed: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(elapsed, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

toc = rounded_time.split('.')[0] + "." + time_digits

return toc


def loop_timer(self, n, function, args=None, digits=2, print_output=True,
output=True, best_of=3):
"""
Returns and prints the total and average time elapsed for n runs
of function.
Parameters
----------
n : scalar(int)
Number of runs.
function : function
Function to be timed.
args : list, optional(default=None)
Arguments of the function.
digits : scalar(int), optional(default=2)
Number of digits for time elapsed.
print_output : bool, optional(default=True)
If True, then prints average time.
output : bool, optional(default=True)
If True, then returns average time.
best_of : scalar(int), optional(default=3)
Average time over best_of runs.
Returns
-------
average_time : str
Average time elapsed for n runs of function.
average_of_best : str
Average of best_of times for n runs of function.
"""
tic()
all_times = []
for run in range(n):
if hasattr(args, '__iter__'):
function(*args)
elif args == None:
function()
else:
function(args)
all_times.append(float(tac(digits, False, True)))

elapsed = toc(digits, False, True)

m, s = divmod(float(elapsed), 60)
h, m = divmod(m, 60)

print("Total run time: %d:%02d:%0d.%0*d" %
(h, m, s, digits, (s%1)*(10**digits)))

average_time = sum(all_times) / len(all_times)

best_times = all_times[:best_of]
average_of_best = sum(best_times) / len(best_times)

if print_output:
m, s = divmod(average_time, 60)
h, m = divmod(m, 60)
print("Average time for %d runs: %d:%02d:%0d.%0*d" %
(n, h, m, s, digits, (s%1)*(10**digits)))
m, s = divmod(average_of_best, 60)
h, m = divmod(m, 60)
print("Average of %d best times: %d:%02d:%0d.%0*d" %
(best_of, h, m, s, digits, (s%1)*(10**digits)))

if output:
rounded_time = str(round(average_time, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

average_time = rounded_time.split('.')[0] + "." + time_digits

rounded_time = str(round(average_of_best, digits))
time_digits = rounded_time.split('.')[1]

while len(time_digits) < digits:
time_digits += "0"

average_of_best = rounded_time.split('.')[0] + "." + time_digits

return average_time, average_of_best


__timer__ = __Timer__()


Expand All @@ -71,11 +233,18 @@ def tic():
return __timer__.tic()


def tac():
def tac(digits=2, print_output=True, output=True):
"""Prints and returns elapsed time since last tic, tac or toc."""
return __timer__.tac()
return __timer__.tac(digits, print_output, output)


def toc():
def toc(digits=2, print_output=True, output=True):
"""Returns and prints time elapsed since last tic()."""
return __timer__.toc()
return __timer__.toc(digits, print_output, output)


def loop_timer(n, function, args=None, digits=2, print_output=True,
output=True, best_of=3):
"""Prints the total and average time elapsed for n runs of function."""
return __timer__.loop_timer(n, function, args, digits, print_output, output,
best_of)

0 comments on commit f1e33f3

Please sign in to comment.