Reputation: 594
I'm having some issues with bad responsiveness in my Django app which I do not know how to explain. I'm using Nginx, uWSGI Django 1.7 and Python3.4 within a Cent Os dev environment. Also There are a couple of background CPU intense computing threads that run periodically performing some tasks (calculations, Db operations, network I/O) . With a large task to handle, I notice the CPU utilization grows up to 100% for some longer time. During the high CPU utilization , any Django request takes a lot of time to handle, sometimes resulting even in a Timeout due to Nginx.
What I find hard to understand is why the Django thread handling the request gets such a small CPU slice ? It's almost as the background tasks hog the processor while the other threads get only leftovers.
Given a high CPU load, what mechanism / options are available to have Django perform responsively ?
Upvotes: 1
Views: 345
Reputation: 3369
It sounds like you need to adjust the scheduling priority of your background operations. If you're not familiar with this term, here is the basic idea: in order to run many processes, your operating system has to divide up the CPU time into little slices, and assign each running process to a slice. Every time a "time slice" ends, the OS picks a new process to run in the next time slice. This choice is called CPU scheduling, and it occurs many times each second.
Most operating systems allow you to adjust the priority of a process. In essence, it gives the OS a "hint" that it should schedule the process more or less frequently, with respect to other running processes. Linux allows you to adjust the priority of a process by setting it's "nice" value. Nice values range from -20 (the highest priority/most frequently scheduled) to 19 or 20 (the lowest priority). (It's kind of backwards from what you'd expect).
You can set a process's nice value in a couple ways. When you start it, you can run it like this: nice -n [value] [program name]
. If the process is already running, you can run renice -n [value] [pid]
, where the pid
is the process ID. A process can also adjust its own nice value using the nice(3)
system call.
So, with all this in mind, you want to do one of these things:
The cleaner thing to do would be decreasing the priority of your background processes, since there are probably fewer of those than "responsive" processes. If the background processes are in Python, they can make use of the os.nice()
function to adjust their own priority. Otherwise, the program may have a configuration option to specify the nice value. If neither of those works, you'll just have to renice
them, and you'll have to do it each time you reboot as well.
Of course, if you'd like, you could also increase the priority of nginx by adjusting the configuration, uWSGI (I don't know how -- maybe configuration, otherwise renice
), and your Django app (probably with os.renice()
).
Whatever you do, keep the following in mind:
top
or htop
(it's the "NI" column). You just need to set the numbers so that the process you want running more frequently has a little bit lower of a nice value than the other one.Hopefully this all helps. More information is readily available in your man pages: nice(1)
, renice(1)
, nice(3)
, sched(7)
. Or Google for "linux nice" or something similar. Have fun!
Upvotes: 1