Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CPU usage per thread

I need to get CPU % for each process thread.

So, I create simple script:

import psutil
from psutil import Process
p = psutil.Process(4499)

treads_list = p.get_threads()

for i in treads_list:
    o = i[0]
    th = psutil.Process(o)
    cpu_perc = th.get_cpu_percent(interval=1)
    print('PID %s use %% CPU = %s' % (o, cpu_perc))

Here is how TOP looks like for this process:

 4942 teamcity  20   0 3288m 831m 3124 R 33.3 10.6  10303:37 java
32700 teamcity  20   0 3288m 831m 3124 S  5.9 10.6  18:49.99 java
 5824 teamcity  20   0 3288m 831m 3124 S  5.9 10.6   1:57.90 java
 4621 teamcity  20   0 3288m 831m 3124 S  3.0 10.6   1834:09 java
 4622 teamcity  20   0 3288m 831m 3124 S  2.6 10.6   1844:15 java

Threads use 2.6-5.9 % CPU, and parent PID - use 33.3.

But - here is script's result:

# ./psutil_threads.py
PID 10231 use % CPU = 60.9
PID 10681 use % CPU = 75.3
PID 11371 use % CPU = 69.9
PID 11860 use % CPU = 85.9
PID 12977 use % CPU = 56.0
PID 14114 use % CPU = 88.8

Looks like each thread 'eat' 56-88 % CPU...

What I'm missing here?

like image 633
setevoy Avatar asked Oct 07 '14 14:10

setevoy


People also ask

Does waiting thread consume CPU?

A thread is inactive when in the blocked or waiting state. When in these states, the thread does not consume any CPU cycles. A thread is in the waiting state when it wants to wait on a signal from another thread before proceeding. Once this signal is received, it becomes runnable.

How do I reduce CPU thread usage?

The best solution to limiting the cpu usage for a process or thread is to make sure that the thread or process uses less cpu. That can best be done by improving the efficiency of the code, or by calling it less often. The aim is to make sure that the process doesn't continually consume all of its available time slice.


3 Answers

This should give you what you need and match top (adapt to your use case):

import psutil

def get_threads_cpu_percent(p, interval=0.1):
   total_percent = p.get_cpu_percent(interval)
   total_time = sum(p.cpu_times())
   return [total_percent * ((t.system_time + t.user_time)/total_time) for t in p.get_threads()]

# Example usage for process with process id 8008:
proc = psutil.Process(8008)
print(get_threads_cpu_percent(proc))
like image 86
Gabe Avatar answered Oct 20 '22 13:10

Gabe


get_cpu_percent(interval=0.1)

Return a float representing the process CPU utilization as a percentage.

When interval is > 0.0 compares process times to system CPU times elapsed before and after the interval (blocking).

When interval is 0.0 or None compares process times to system CPU times elapsed since last call, returning immediately. In this case is recommended for accuracy that this function be called with at least 0.1 seconds between calls.

This sounds a lot like it will give you how much of the CPU time spent non-idle is returned (that is: amount of process CPU time per system CPU time), while top shows the amount of CPU time of the process in relation to real time. This seems realistic given your numbers.

To get the values top would show you, simply multiplying each threads' CPU usage by the CPU usage of the core the thread runs on should work. psutil.cpu_percent should help with that. Note that you need to divide percentages by 100.0 (to get a "percentage" between 0 and 1) before multiplying them.

like image 4
dom0 Avatar answered Oct 20 '22 12:10

dom0


While Gabe's answer is great, note that newer psutil version requires the following updated syntax:

import psutil

def get_threads_cpu_percent(p, interval=0.1):
   total_percent = p.cpu_percent(interval)
   total_time = sum(p.cpu_times())
   return [total_percent * ((t.system_time + t.user_time)/total_time) for t in p.threads()]

# Example usage for process with process id 8008:
proc = psutil.Process(8008)
print(get_threads_cpu_percent(proc))
like image 3
Florent Thiery Avatar answered Oct 20 '22 12:10

Florent Thiery