Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Memory Sharing among workers in gunicorn using --preload

I have a large model file that I use in my webservice built in Flask and then served through Gunicorn. The folder is strucure is like this:

A.py
Folder_1\
    __init__.py
    B.py

The model is loaded in __init__.py and used in B.py The entry point is A.py that contains @app.routes, etc.

I start A.py with gunicorn and preload the app using --preload option and there are 8 workers.

I am facing 100% CPU utilization on 8 cores; apparently the requests are stuck at app server and not being forwarded to DB. Does the model is also preloaded and made available to all 8 workers, i.e. Is it shared between the worker processes? If not do I have to load the model in A.py so that the model is also preloaded for all workers.

I think the model is being loaded by every worker process and since the model is large, the workers are stuck there.

EDIT 1 : Since I was notified that this might be a duplicate question, I want to clarify I am not asking how python handles shared object. I understand that is possible by using multiprocessing. In my case, I start flask server from gunicorn with 8 workers using --preload option, there are 8 instances of my app running. My question is, since the code was preloaded before workers were forked, gunicorn workers will share the same model object, or they will have a separate copy each.?

like image 553
greenlantern Avatar asked Jul 13 '17 05:07

greenlantern


People also ask

How to improve performance when using Gunicorn?

To improve performance when using Gunicorn we have to keep in mind 3 means of concurrency. Each of the workers is a UNIX process that loads the Python application. There is no shared memory between the workers. The suggested number of workers is (2*CPU)+1. For a dual-core (2 CPU) machine, 5 is the suggested workers value.

How does Gunicorn handle concurrency?

The OS kernel handles load balancing between worker processes. To improve performance when using Gunicorn we have to keep in mind 3 means of concurrency. Each of the workers is a UNIX process that loads the Python application. There is no shared memory between the workers.

Does sync worker support persistent connections with Gunicorn?

When Gunicorn is deployed behind a load balancer, it often makes sense to set this to a higher value. sync worker does not support persistent connections and will ignore this option.

How does Gunicorn handle multiple threads?

Gunicorn also allows for each of the workers to have multiple threads. In this case, the Python application is loaded once per worker, and each of the threads spawned by the same worker shares the same memory space. To use threads with Gunicorn, we use the threads setting.


1 Answers

My question is, since the code was preloaded before workers were forked, gunicorn workers will share the same model object, or they will have a separate copy each.?

It will be a separate copy.

preloading simply takes advantage of the fact that when you call the operating system's fork() call to create a new process, the OS is able to share unmodified sections of memory between the two processes. By preloading as much code as possible more memory is shared between the processes.

This is simply a behind-the-scenes operating system optimization: from the perspective of each individual python process they have unique copies of each object.

like image 170
Levi Avatar answered Nov 14 '22 22:11

Levi