2

Is there a way to measure the amount of memory allocated by an arbitrary web request in a Flask/Werkzeug app? By arbitrary, I mean I'd prefer a technique that lets me instrument code at a high enough level that I don't have to change it to test memory usage of different routes. If that's not possible but it's still possible to do this by wrapping individual requests with a little code, so be it.

In a PHP app I wrote a while ago, I accomplished this by calling the memory_get_peak_usage() function both at the start and the end of the request and taking the difference.

Is there an analog in Python/Flask/Werkzeug? Using Python 2.7.9 if it matters.

DaveBurns
  • 2,036
  • 2
  • 27
  • 37

2 Answers2

2

First of all, one should understand the main difference between PHP and Python requests processing. Roughly speaking, each PHP worker accepts only one request, handle it and then die (or reinit interpreter). PHP was designed directly for it, it's request processing language by its nature. So, it's pretty simple to measure per request memory usage. Request's peak memory usage is equal to the worker peak memory usage. It's a language feature.

At the same time, Python usually uses another approach to handle requests. There are two main models - synchronous and asynchronous request processing. However, both of them have the same difficulty when it comes to measure per request memory usage. The reason is that one Python worker handles plenty of requests (concurrently or sequentially) during his life. So, it's hard to get memory usage exactly for a request.

However, one can adapt an underlying framework and application code to accomplish collecting memory usage task. One possible solution is to use some kind of events. For example, one can raise an abstract mem_usage event on: before request, at the beginning of a view function, at the end of a view function, in some important places within the business logic and so on. Then it should exists a subscriber for such events, doing the next thing:

import resource
mem_usage = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss

This subscriber have to accumulate such usage data and on the app_request_teardown/after_request send it to the metrics collection system with information about current request.endpoint or route or whatever.

Also, using a memory profiler is a good idea, but usually not for a production usage.

Further reading about request processing models:

Community
  • 1
  • 1
Ivan Velichko
  • 6,348
  • 6
  • 44
  • 90
  • I'm pretty familiar with the request model of both languages. Let's assume that I'm in a controlled environment where I choose which request is happening and there will be only one at a time. Is there a specific module, either general-purpose or specific to Werkzeug, that is most appropriate for testing mem usage? Thanks. – DaveBurns Mar 21 '16 at 20:18
  • @DaveBurns, how about using [`sys.settrace`](http://stackoverflow.com/a/37049727/1201488)? – Ivan Velichko May 05 '16 at 11:44
0

Another possible solution is to use sys.setrace. Using this tool one can measure memory usage even per each line of code. Usage examples can be found in the memory_profiler project. Of course, it will slowdown the code significantly.

Ivan Velichko
  • 6,348
  • 6
  • 44
  • 90