10

I checked the pytest documentation but I could not find anything relevant. I know pytest --durations=0 will print out the runtime for all the tests. Is there a way to get pytest to also print out the peak memory usage consumed by a function? Otherwise, I can probably just use the decoration function below. But I am wondering if there is a better way to do this.

from functools import wraps

    def mem_time(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            
            # Start of function
            r0 = resource.getrusage(resource.RUSAGE_SELF)
            t0 = datetime.datetime.now()
    
            # Call function
            status = func(*args, **kwargs)
            
            # End of function
            r1 = resource.getrusage(resource.RUSAGE_SELF)
            t1 = datetime.datetime.now()
            
            sys.stderr.write('{}: utime {} stime {} wall {}\n'.format(func.__name__,
                                                                      datetime.timedelta(seconds=r1.ru_utime - r0.ru_utime),
                                                                      datetime.timedelta(seconds=r1.ru_stime - r0.ru_stime),
                                                                      t1 - t0))
    
            sys.stderr.write('{}: mem {} MB ({} GB)\n'.format(func.__name__,
                                                              (r1.ru_maxrss - r0.ru_maxrss) / 1000.0,
                                                              (r1.ru_maxrss - r0.ru_maxrss) / 1000000.0))
            
            return status
        
        return wrapper
vvvvv
  • 25,404
  • 19
  • 49
  • 81
user4979733
  • 3,181
  • 4
  • 26
  • 41
  • If interested, I can dig out some code, that shows you the memory occopied by the python process before and after the test. However as Python does not always release memory that quickly it will not necessarily give you the right results, but it can be quite educational in some cases. Interested? – gelonida Nov 20 '19 at 01:23
  • just checked my old code. I don't think it's any better than rusage. The code worked already for python2 though, which almost nobody cares about now. `pip install psutil` to install and then `import os. psutil ; rss = psutil.Process(os.getpid()).memory_info().rss` – gelonida Nov 21 '19 at 00:32

2 Answers2

18

pytest-monitor a new awesome plugins for pytest helps to monitor resources usage, timings, memory and so on. All metrics are stored in an sqlite database for post analysis

check out pytest-monitor from pypi or conda-forge:

Example

$ pytest --db ./monitor.db

$ sqlite3 ./monitor.db

sqlite>.headers on

sqlite> select ITEM, MEM_USAGE from TEST_METRICS;

ITEM|MEM_USAGE
test_api/test_data_get[/data/listdsh]|17.5703125
test_api/test_data_get[/data/listrecipients]|17.97265625
test_api/test_data_get[/data/getuserdetails]|18.125

vvvvv
  • 25,404
  • 19
  • 49
  • 81
jdhalimi
  • 181
  • 1
  • 6
  • 1
    The downside is that [`pytest-monitor`](https://github.com/CFMTech/pytest-monitor) doesn't support [`unittest`](https://docs.python.org/3/library/unittest.html) [yet](https://github.com/CFMTech/pytest-monitor/issues/39). – patryk.beza Aug 03 '21 at 12:02
-1

Memory Profiling:

There is no plugin to get memory profiling from the pytest (As far as I know). Use the following link for memory profiling

https://github.com/fabianp/memory_profiler

Other references: https://stackoverflow.com/a/43772305/9595032

Cumulative times:

https://pypi.org/project/pytest-profiling/

But to get Cumulative times of all calls to use plugin pytest-profiling

pip install pytest-profiling

Usage:

pytest -s -v [file_name] --profile

The output will look somewhat like this

Profiling (from /home/work/project/analytics/testing/TestCases/cloud/prof/combined.prof):
Wed Nov 20 12:09:47 2019    /home/work/project/analytics/testing/TestCases/cloud/prof/combined.prof

         437977 function calls (380211 primitive calls) in 3.866 seconds

   Ordered by: cumulative time
   List reduced from 683 to 20 due to restriction <20>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    3.866    3.866 runner.py:107(pytest_runtest_call)
        1    0.000    0.000    3.866    3.866 python.py:1457(runtest)
        1    0.000    0.000    3.866    3.866 hooks.py:275(__call__)
        1    0.000    0.000    3.866    3.866 manager.py:59(<lambda>)
        1    0.000    0.000    3.866    3.866 manager.py:65(_hookexec)
        1    0.000    0.000    3.866    3.866 callers.py:157(_multicall)
        1    0.000    0.000    3.866    3.866 python.py:188(pytest_pyfunc_call)
        1    0.001    0.001    3.866    3.866 test_abc.py:46(test_abc)
        1    0.000    0.000    3.865    3.865 test_abc.py:9(run_abc_test)
        1    0.001    0.001    3.854    3.854 dataAnalyzer.py:826(sanitize_data)
        1    0.000    0.000    3.773    3.773 Analyzer.py:563(Traffic)
        1    0.000    0.000    3.772    3.772 traffic.py:83(false_alarm_checks)
        3    0.000    0.000    3.767    1.256 api.py:60(get)
        3    0.000    0.000    3.765    1.255 api.py:135(_get_from_overpass)
        3    0.000    0.000    3.765    1.255 api.py:101(post)
        3    0.000    0.000    3.765    1.255 api.py:16(request)
        3    0.000    0.000    3.762    1.254 sessions.py:445(request)
        3    0.000    0.000    3.759    1.253 sessions.py:593(send)
        3    0.000    0.000    3.757    1.252 adapters.py:393(send)
        3    0.000    0.000    3.755    1.252 connectionpool.py:447(urlopen)
kolukuri
  • 317
  • 2
  • 8