What is the Python equivalent of Matlab tic and toc?

What is the Python equivalent of Matlab tic and toc ?

+76
python matlab timing
May 01 '11 at 16:46
source share
11 answers

Besides the timeit that timeit mentioned, an easy way to do this is simple (after importing time ):

 t = time.time() # do stuff elapsed = time.time() - t 

I have a helper class that I like to use:

 class Timer(object): def __init__(self, name=None): self.name = name def __enter__(self): self.tstart = time.time() def __exit__(self, type, value, traceback): if self.name: print('[%s]' % self.name,) print('Elapsed: %s' % (time.time() - self.tstart)) 

It can be used as a context manager:

 with Timer('foo_stuff'): # do some foo # do some stuff 

Sometimes I find this technique more convenient than timeit - it all depends on what you want to measure.

+128
May 01 '11 at 16:55
source share
β€” -

I had the same question when I switched to python from Matlab. Using this thread, I was able to build an exact analogue of the Matlab tic() and toc() functions. Just paste the following code at the top of the script.

 import time def TicTocGenerator(): # Generator that returns time differences ti = 0 # initial time tf = time.time() # final time while True: ti = tf tf = time.time() yield tf-ti # returns the time difference TicToc = TicTocGenerator() # create an instance of the TicTocGen generator # This will be the main function through which we define both tic() and toc() def toc(tempBool=True): # Prints the time difference yielded by generator instance TicToc tempTimeInterval = next(TicToc) if tempBool: print( "Elapsed time: %f seconds.\n" %tempTimeInterval ) def tic(): # Records a time in TicToc, marks the beginning of a time interval toc(False) 

What is it! Now we are ready to fully use tic() and toc() in the same way as in Matlab. for example

 tic() time.sleep(5) toc() # returns "Elapsed time: 5.00 seconds." 

In fact, it is more universal than Matlab's built-in functions. Here you can create another instance of TicTocGenerator to track multiple operations or simply in different ways. For example, although the time is a script, we can now separate each part of the script separately, as well as the entire script. (I will give a concrete example)

 TicToc2 = TicTocGenerator() # create another instance of the TicTocGen generator def toc2(tempBool=True): # Prints the time difference yielded by generator instance TicToc2 tempTimeInterval = next(TicToc2) if tempBool: print( "Elapsed time 2: %f seconds.\n" %tempTimeInterval ) def tic2(): # Records a time in TicToc2, marks the beginning of a time interval toc2(False) 

You should now be able to separate two separate things: In the following example, we split the total number of script and script parts separately.

 tic() time.sleep(5) tic2() time.sleep(3) toc2() # returns "Elapsed time 2: 5.00 seconds." toc() # returns "Elapsed time: 8.00 seconds." 

In fact, you don't even need to use tic() every time. If you have a series of commands that you want to use, you can write

 tic() time.sleep(1) toc() # returns "Elapsed time: 1.00 seconds." time.sleep(2) toc() # returns "Elapsed time: 2.00 seconds." time.sleep(3) toc() # returns "Elapsed time: 3.00 seconds." # and so on... 

I hope this will be helpful.

+22
Nov 02 '14 at 2:44
source share

The absolute best analogue of tic and toc would be to simply define them in python.

 def tic(): #Homemade version of matlab tic and toc functions import time global startTime_for_tictoc startTime_for_tictoc = time.time() def toc(): import time if 'startTime_for_tictoc' in globals(): print "Elapsed time is " + str(time.time() - startTime_for_tictoc) + " seconds." else: print "Toc: start time not set" 

Then you can use them like:

 tic() # do stuff toc() 
+15
Sep 19 '13 at 7:12
source share

Usually IPython %time , %timeit , %prun and %lprun (if line_profiler set) satisfactorily satisfy my profile needs. However, the use case for tic-toc functionality came about when I tried to profile computations that were interactively controlled, that is, by moving the mouse in the graphical user interface. I felt like tic and toc spam in the sources, while testing online would be the fastest way to identify bottlenecks. I went with the Eli Bendersky Timer class, but was not completely satisfied, since I needed to change the indentation of my code, which can be inconvenient in some editors and confuses version control. Moreover, it may be necessary to measure the time between points in different functions, which will not work with the with statement. Having tried a lot of Python tricks, here is a simple solution that I found best:

 from time import time _tstart_stack = [] def tic(): _tstart_stack.append(time()) def toc(fmt="Elapsed: %ss"): print fmt % (time() - _tstart_stack.pop()) 

Since this works by pressing the start time of the stack, it will work correctly for several tic and toc s levels. It also allows you to change the format string of the toc statement to display additional information that I liked in the Eli Timer class.

For some reason, I was involved with the overhead of a pure Python implementation, so I also tested the C extension module:

 #include <Python.h> #include <mach/mach_time.h> #define MAXDEPTH 100 uint64_t start[MAXDEPTH]; int lvl=0; static PyObject* tic(PyObject *self, PyObject *args) { start[lvl++] = mach_absolute_time(); Py_RETURN_NONE; } static PyObject* toc(PyObject *self, PyObject *args) { return PyFloat_FromDouble( (double)(mach_absolute_time() - start[--lvl]) / 1000000000L); } static PyObject* res(PyObject *self, PyObject *args) { return tic(NULL, NULL), toc(NULL, NULL); } static PyMethodDef methods[] = { {"tic", tic, METH_NOARGS, "Start timer"}, {"toc", toc, METH_NOARGS, "Stop timer"}, {"res", res, METH_NOARGS, "Test timer resolution"}, {NULL, NULL, 0, NULL} }; PyMODINIT_FUNC inittictoc(void) { Py_InitModule("tictoc", methods); } 

This is for MacOSX, and I skipped the code to check if lvl out of bounds. While tictoc.res() gives a resolution of about 50 nanoseconds on my system, I found that measuring jitter of any Python instruction is easily in the microsecond range (and much more when used with IPython). At the moment, the overhead of the Python implementation is becoming negligible, so it can be used with the same certainty as the C implementation.

I found that the usefulness of tic-toc -Approach is practically limited to blocks of code that take more than 10 microseconds to complete. Below are averaging strategies such as timeit to get an accurate measurement.

+11
Nov 15 '13 at 17:07
source share

I just created the [tictoc.py] module to achieve nested tic currents, which is what Matlab does.

 from time import time tics = [] def tic(): tics.append(time()) def toc(): if len(tics)==0: return None else: return time()-tics.pop() 

And it works as follows:

 from tictoc import tic, toc # This keeps track of the whole process tic() # Timing a small portion of code (maybe a loop) tic() # -- Nested code here -- # End toc() # This returns the elapse time (in seconds) since the last invocation of tic() toc() # This does the same for the first tic() 

Hope this helps.

+5
May 18 '17 at 18:52
source share

Just in case, someone is interested. Based on all the other answers, I wrote a tictoc class that has the best of them.

Link to github here.

You can also use pip to get it.

 pip install ttictoc 

How to use this:

Import it

 from ttictoc import TicToc 

Using the expression "c"

Without creating any object, you can calculate the time of your code as follows.

 with TicToc('name'): some code... # Prints the elapsed time 

Or by creating an object, you can do the same.

 t = TicToc('name') with t: some code... # Prints the elapsed time 

Call Tic Toc explicitly

You can also explicitly call Tic Toc, as shown below.

 t = TicToc('name') t.tic() some code... t.toc() print(t.elapsed) With indentation 

If you want to synchronize several levels of your code, you can also do this by setting the indentation to True.

 t = TicToc(,indentation=True) t.tic() some code1... t.tic() some code2... t.tic() some code3... t.toc() print('time for code 3 ',t.elapsed) t.toc() print('time for code 2 with code 3 ',t.elapsed) t.toc() print('time for code 1 with code 2 and 3 ',t.elapsed) 

the arguments

The class has 3 arguments: name, method and indent.

  • name: this is the name of the object. It's not obligatory.
  • method: indicates which method should be used to get the time.
  • indent: Allows you to use the same object several times, with different indents in time.

The argument to the method can be either int, str, or your choice of method. If it is a string, valid values ​​are time, perf_counter, and process_time. If it is an integer, valid values ​​are 0, 1, and 2.

  • time or 0: time. time
  • perf_counter or 1: time.perf_counter
  • process_time or 2: time.process_time

If Python version> = 3.7: - time_ns or 3: time.time_ns - perf_counter_ns or 4: time.perf_counter_ns - process_time_ns or 5: time.process_time_ns

In case you prefer to use another method that you just use (e.g. time.clock:

 TicToc(method=time.clock) 

The class is as follows:

 import sys import time class TicToc(object): """ Counts the elapsed time. """ def __init__(self,name='',method='time',indentation=False): """ Args: name (str): Just informative, not needed method (int|str|ftn|clss): Still trying to understand the default options. 'time' uses the 'real wold' clock, while the other two use the cpu clock. If you want to use your own method, do it through this argument Valid int values: 0: time.time | 1: time.perf_counter | 2: time.proces_time if python version >= 3.7: 3: time.time_ns | 4: time.perf_counter_ns | 5: time.proces_time_ns Valid str values: 'time': time.time | 'perf_counter': time.perf_counter 'process_time': time.proces_time if python version >= 3.7: 'time_ns': time.time_ns | 'perf_counter_ns': time.perf_counter_ns 'proces_time_ns': time.proces_time_ns Others: Whatever you want to use as time.time indentation (bool): Allows to do tic toc with indentation with a single object. If True, you can put several tics using the same object, and each toc will correspond to the respective tic. If False, it will only register one single tic, and return the respective elapsed time of the future tocs. """ self.name = name self.indentation = indentation if self.indentation: self.tstart = [] self.__measure = 's' # seconds self.__vsys = sys.version_info if self.__vsys[0]>2 and self.__vsys[1]>=7: # If python version is greater or equal than 3.7 if type(method) is int: if method==0: method = 'time' elif method==1: method = 'perf_counter' elif method==2: method = 'process_time' elif method==3: method = 'time_ns' elif method==3: method = 'perf_counter_ns' elif method==4: method = 'process_time_ns' else: import warnings msg = "Value '{0}' is not a valid option. Using 'time' instead.".format(method) warnings.warn(msg,Warning) method = 'time' if type(method) is str: if method=='time': self.get_time = time.time elif method=='perf_counter': self.get_time = time.perf_counter elif method=='process_time': self.get_time = time.process_time elif method=='time_ns': self.get_time = time.time_ns, self.__measure = 'ns' # nanoseconds elif method=='perf_counter_ns': self.get_time = time.perf_counter_ns, self.__measure = 'ns' # nanoseconds elif method=='process_time_ns': self.get_time = time.process_time_ns, self.__measure = 'ns' # nanoseconds else: import warnings msg = "Value '{0}' is not a valid option. Using 'time' instead.".format(method) warnings.warn(msg,Warning) self.get_time = time.time else: self.get_time = method else: # If python vesion is lower than 3.7 if type(method) is int: if method==0: method = 'time' elif method==1: method = 'perf_counter' elif method==2: method = 'process_time' else: import warnings msg = "Value '{0}' is not a valid option. Using 'time' instead.".format(method) warnings.warn(msg,Warning) method = 'time' if type(method) is str: if method=='time': self.get_time = time.time elif method=='perf_counter': self.get_time = time.perf_counter elif method=='process_time': self.get_time = time.process_time else: import warnings msg = "Value '{0}' is not a valid option. Using 'time' instead.".format(method) warnings.warn(msg,Warning) self.get_time = time.time else: self.get_time = method def __enter__(self): if self.indentation: self.tstart.append(self.get_time()) else: self.tstart = self.get_time() def __exit__(self,type,value,traceback): self.tend = self.get_time() if self.indentation: self.elapsed = self.tend - self.tstart.pop() else: self.elapsed = self.tend - self.tstart if self.name!='': name = '[{}] '.format(self.name) else: name = self.name print('{0}Elapsed time: {1} ({2})'.format(name,self.elapsed,self.__measure)) def tic(self): if self.indentation: self.tstart.append(self.get_time()) else: self.tstart = self.get_time() def toc(self): self.tend = self.get_time() if self.indentation: if len(self.tstart)>0: self.elapsed = self.tend - self.tstart.pop() else: self.elapsed = None else: self.elapsed = self.tend - self.tstart 
+4
Jul 26 '18 at 21:41
source share

Check out the timeit module. This is not entirely equivalent, but if the code you want to use is inside a function that you can easily use.

+3
May 01 '11 at 16:48
source share

I changed @Eli Bendersky a bit to use ctor __init__() and dtor __del__() to make timing so that it can be used more conveniently, without departing from the source code:

 class Timer(object): def __init__(self, name=None): self.name = name self.tstart = time.time() def __del__(self): if self.name: print '%s elapsed: %.2fs' % (self.name, time.time() - self.tstart) else: print 'Elapsed: %.2fs' % (time.time() - self.tstart) 

To use a simple timer ("blahblah") at the beginning of some local area. Elapsed time will be printed at the end of the scope:

 for i in xrange(5): timer = Timer("eigh()") x = numpy.random.random((4000,4000)); x = (x+xT)/2 numpy.linalg.eigh(x) print i+1 timer = None 

He prints:

 1 eigh() elapsed: 10.13s 2 eigh() elapsed: 9.74s 3 eigh() elapsed: 10.70s 4 eigh() elapsed: 10.25s 5 eigh() elapsed: 11.28s 
+1
May 27 '15 at
source share

This can also be done with a wrapper. A very common way to keep time.

The shell in this code example wraps any function and prints the amount of time it takes to execute the function:

 def timethis(f): import time def wrapped(*args, **kwargs): start = time.time() r = f(*args, **kwargs) print "Executing {0} took {1} seconds".format(f.func_name, time.time()-start) return r return wrapped @timethis def thistakestime(): for x in range(10000000): pass thistakestime() 
+1
Jul 27 '16 at 13:18
source share

Based on the answers of Stefan and Antonimo, I ended up

 def Tictoc(): start_stack = [] start_named = {} def tic(name=None): if name is None: start_stack.append(time()) else: start_named[name] = time() def toc(name=None): if name is None: start = start_stack.pop() else: start = start_named.pop(name) elapsed = time() - start return elapsed return tic, toc 

in the utils.py module and I use it with

 from utils import Tictoc tic, toc = Tictoc() 

This way

  • you can just use tic() , toc() and nest them in matlab
  • you can name them: tic(1) , toc(1) or tic('very-important-block') , toc('very-important-block') and timers with different names will not interfere
  • Importing data in this way prevents interference between the modules used.

(here toc does not print the elapsed time, but returns it.)

0
Oct 22 '17 at 13:30
source share

Update Eli's answer in Python 3:

 class Timer(object): def __init__(self, name=None, filename=None): self.name = name self.filename = filename def __enter__(self): self.tstart = time.time() def __exit__(self, type, value, traceback): message = 'Elapsed: %.2f seconds' % (time.time() - self.tstart) if self.name: message = '[%s] ' % self.name + message print(message) if self.filename: with open(self.filename,'a') as file: print(str(datetime.datetime.now())+": ",message,file=file) 

Like Eli, it can be used as a context manager:

 import time with Timer('Count'): for i in range(0,10_000_000): pass 

Exit:

 [Count] Elapsed: 0.27 seconds 

I also updated it to print out the time units that were reported (in seconds) and trim the number of digits according to the Can clause, as well as with the option of adding to the log file. You must import datetime in order to use the registration function:

 import time import datetime with Timer('Count', 'log.txt'): for i in range(0,10_000_000): pass 
0
Jun 20 '18 at 22:05
source share



All Articles