Is there an easy way to compare python script?

I usually use the shell command time . My goal is to check if the data is small, medium, large or very large, how much time and memory will be.

Any tools for linux or just python for this?

+64
python benchmarking unix shell
Oct 20 '09 at 7:40
source share
8 answers

Take a look at timeit , the python profiler, and pycallgraph .

timeit

 def test(): """Stupid test function""" lst = [] for i in range(100): lst.append(i) if __name__ == '__main__': import timeit print(timeit.timeit("test()", setup="from __main__ import test")) 

Essentially, you can pass python code as a string parameter, and it will execute the specified number of times and print the runtime. Important bits from the docs:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)

Create an instance of Timer with this statement, set the code and timer, and run its timeit method using the number of executions.

... and:

Timer.timeit(number=1000000)

Execution of time numbers of the main operator. This performs the setup once, and then returns the time required to complete the main several times, measured in seconds as a float. An argument is the number of times through the loop, by default it is one million. The main operator, installation instruction, and timer function that will be used are passed to the constructor.

Note

By default, timeit temporarily disables the garbage collection during synchronization. The advantage of this approach is that it makes independent timings more comparable. This drawback is that HA can be an important component of a measurable function. If so, the GC can be turned on again as the first in the configuration line. For example:

timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()

Profiling

Profiling will give you a more detailed idea of ​​what is happening. Here's an “instant example” from official docs :

 import cProfile import re cProfile.run('re.compile("foo|bar")') 

What will give you:

  197 function calls (192 primitive calls) in 0.002 seconds Ordered by: standard name ncalls tottime percall cumtime percall filename:lineno(function) 1 0.000 0.000 0.001 0.001 <string>:1(<module>) 1 0.000 0.000 0.001 0.001 re.py:212(compile) 1 0.000 0.000 0.001 0.001 re.py:268(_compile) 1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset) 1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset) 4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction) 3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile) 

Both of these modules should give you an idea of ​​where to look for bottlenecks.

Also, to access profile output, check out this post.

pycallgraph

This module uses graphviz to create callgraphs, such as:

callgraph example

You can easily see which paths used the most time by color. You can create them using the pycallgraph API or using a packed script:

 pycallgraph graphviz -- ./mypythonscript.py 

Overhead is quite significant. Therefore, for already long processes, creating a schedule may take some time.

+91
Oct 20 '09 at 7:45
source share

I use a simple decorator to make func time

 def st_time(func): """ st decorator to calculate the total time of a func """ def st_func(*args, **keyArgs): t1 = time.time() r = func(*args, **keyArgs) t2 = time.time() print "Function=%s, Time=%s" % (func.__name__, t2 - t1) return r return st_func 
+24
Jun 22 2018-12-12T00
source share

The timeit module was slow and weird, so I wrote this:

 def timereps(reps, func): from time import time start = time() for i in range(0, reps): func() end = time() return (end - start) / reps 

Example:

 import os listdir_time = timereps(10000, lambda: os.listdir('/')) print "python can do %d os.listdir('/') per second" % (1 / listdir_time) 

For me it says:

 python can do 40925 os.listdir('/') per second 

This is a primitive kind of benchmarking, but it is good enough.

+12
Aug 08 2018-12-12T00:
source share

I usually do a quick time ./script.py to find out how long it will take. This does not show you memory, although at least not by default. You can use /usr/bin/time -v ./script.py to get a lot of information, including memory usage.

+10
Apr 04 2018-11-21T00:
source share

Take a look at nose and this one of your plugins.

After installation, the nose is a script in your path, and you can call in the directory that contains some python scripts:

 $: nosetests 

It will look in all python files in the current directory and will perform any function that it recognizes as a test: for example, it recognizes any function with the word test_ in its name as a test.

So you can just create a python script called test_yourfunction.py and write something like this in it:

 $: cat > test_yourfunction.py def test_smallinput(): yourfunction(smallinput) def test_mediuminput(): yourfunction(mediuminput) def test_largeinput(): yourfunction(largeinput) 

Then you need to run

 $: nosetest --with-profile --profile-stats-file yourstatsprofile.prof testyourfunction.py 

and to read the profile file use this python line:

 python -c "import hotshot.stats ; stats = hotshot.stats.load('yourstatsprofile.prof') ; stats.sort_stats('time', 'calls') ; stats.print_stats(200)" 
+3
Oct. 20 '09 at 8:38
source share

A memory profiler for all your memory needs.

https://pypi.python.org/pypi/memory_profiler

Run pip setup:

 pip install memory_profiler 

Import Library:

 import memory_profiler 

Add a decorator to the item you want to view:

 @profile def my_func(): a = [1] * (10 ** 6) b = [2] * (2 * 10 ** 7) del b return a if __name__ == '__main__': my_func() 

Run code:

 python -m memory_profiler example.py 

Get the result:

  Line # Mem usage Increment Line Contents ============================================== 3 @profile 4 5.97 MB 0.00 MB def my_func(): 5 13.61 MB 7.64 MB a = [1] * (10 ** 6) 6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7) 7 13.61 MB -152.59 MB del b 8 13.61 MB 0.00 MB return a 

Examples from the documents linked above.

+3
Jun 22 '17 at 7:27
source share

Be careful timeit very slow, it will take 12 seconds on my average processor to just initialize (or maybe run a function). You can check this accepted answer

 def test(): lst = [] for i in range(100): lst.append(i) if __name__ == '__main__': import timeit print(timeit.timeit("test()", setup="from __main__ import test")) # 12 second 

for simplicity, I will use time instead, it will return 0.0 on my computer

 import time def test(): lst = [] for i in range(100): lst.append(i) t1 = time.time() test() result = time.time() - t1 print(result) # 0.000000xxxx 
0
Mar 10 '19 at 19:35
source share

The easiest way to quickly test any function is to use this syntax: %timeit my_code

For example:

 %timeit a = 1 13.4 ns ± 0.781 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each) 
0
Mar 28 '19 at 9:49
source share



All Articles