Package: simple-profile
simple-profileSimple decorators to profile the memory usage and execution time.Installationpipinstallsimple-profileDecoratorsDecoratorDescription@simple_profile()Profiles the peak memory usage and the average execution time of a function.@memory_profile()Profiles only the peak memory usage of a function.@time_profile()Profiles only the average execution time of a function.Usage1. Profile a functionThe@simple_profile()decorator allows to log the peak memory usage and the average execution time of each function call.By default, memory usage and execution time are logged in the most suitable units, but it is possible to change the units.fromsimple_profileimportsimple_profile@simple_profile()defmy_function():return[2*iforiinrange(10)]my_function()Output:my_function | 432 B | 445.2 ns2. Profile only the memory usage of a functionThe@memory_profile()decorator allows to log the peak memory usage of each function call.This is done using thetracemallocmodule provided by Python.fromsimple_profileimportmemory_profile@memory_profile()defmy_function():return[2*iforiinrange(10)]my_function()Output:my_function | 432 B3. Profile only the execution time of a functionThe@time_profile()decorator allows to log the average execution time of each function call.This is done using thetimeitmodule provided by Python.By default, each function call is repeated1,000,000times to get a reliable measurement, but it is possible to change this value.fromsimple_profileimporttime_profile@time_profile()defmy_function():return[2*iforiinrange(10)]my_function()Output:my_function | 439.3 ns4. Change the number of iterationsIt is possible to change the number of times a function call is repeated when profiling the execution time.To do this, you can set theiterationsargument of thesimple_profile()andtime_profile()decorators.fromsimple_profileimportsimple_profile@simple_profile(iterations=100)defpi(n):result=0d=1foriinrange(1,n):a=2*(i%2)-1result+=4*a/dd+=2returnresultpi(100)Output:pi | 168 B | 6.461 µs5. Change the time and memory unitsIt is also possible to change the time and memory units used in the logs.To do this, you can set theunitargument of thememory_profile()andtime_profile()decorators.For thesimple_profile()decorator, you can set thetime_unitandmemory_unitarguments.fromsimple_profileimportsimple_profile,MemoryUnit,TimeUnit@simple_profile(memory_unit=MemoryUnit.KILOBYTES,time_unit=TimeUnit.MILLISECONDS)defexponential(x,n):result=1.0foriinrange(n,0,-1):result=1+x*result/ireturnresultexponential(8,100)Output:exponential | 0.168 kB | 0.005429 ms6. Change the time and memory precisionMoreover, it is possible to change the precision of memory and time values.To do this, you can define the number of significant digits you want in theprecisionargument of any decorator provided by this package.For thesimple_profile()decorator, you can set thetime_precisionandmemory_precisionarguments for more granular control.fromsimple_profileimportsimple_profile@simple_profile(precision=10)defaverage(lst):returnsum(lst)/len(lst)average([25,12,18,88,64,55,22])Output:average | 120 B | 176.6314 ns7. Log the arguments and the resultFurthermore, it is possible to log the arguments and the result of each function call.Indeed, this can be useful to better profile a function and analyze its behavior.fromsimple_profileimportsimple_profile@simple_profile(print_args=True,print_result=True)defgreeting_message(name,coins):return"Hello{}! You have{}coins.".format(name,coins)greeting_message("John",coins=5)Output:greeting_message | John, coins=5 | Hello John! You have 5 coins. | 521 B | 350.1 ns8. Set a custom name for a functionAdditionally, it is possible to define a custom descriptive name for each function.To do this, you can set thenameargument of any decorator provided by this package.fromsimple_profileimportsimple_profile@simple_profile(name="Naive method")deffactorial(n):result=1foriinrange(1,n+1):result*=ireturnresultfactorial(10)Output:Naive method | 160 B | 411.3 ns9. Compare multiple functionsfromsimple_profileimportsimple_profile@simple_profile(name="List comprehension")defmy_function(n):return[pow(2,i)foriinrange(n)]@simple_profile(name="For loop")defmy_function_2(n):lst=[]foriinrange(n):lst.append(pow(2,i))returnlstmy_function(10)my_function_2(10)Output:List comprehension | 464 B | 666.8 ns
For loop | 312 B | 650.7 ns10. Profile a recursive functionThe decorators work seamlessly with recursive functions.Only one profiling message is logged per function call even if the function is recursive.fromsimple_profileimportsimple_profile@simple_profile(print_args=True,print_result=True,iterations=100)deffibonacci(n):ifn<=1:returnnelse:returnfibonacci(n-1)+fibonacci(n-2)fibonacci(10)Output:fibonacci | 10 | 55 | 1.648 kB | 21.04 µs11. Enable garbage collection during measurementsBy default, garbage collection is temporarily turned off to make measurements more comparable, but it is possible to enable it if you prefer.To do this, you can set theenable_gcargument of thesimple_profile()andtime_profile()decorators toTrue.fromsimple_profileimportsimple_profile@simple_profile(name="Without GC")defmy_function():return[oct(i)foriinrange(10)]@simple_profile(name="With GC",enable_gc=True)defmy_function_2():return[oct(i)foriinrange(10)]my_function()my_function_2()Output:Without GC | 954 B | 666.5 ns
With GC | 954 B | 669.2 ns