1. Introduction
Modern CPUs are made up of more than one core. So, in order to leverage the power of multi-core processors, applications generally run on multi-threaded processes. Sometimes, we may need information on how many threads a particular process uses. In this article, we will walk you through all the tools and commands we can utilize to check and monitor the thread count data.
We assume that the concepts of thread and process are known. Hence, if you’re not familiar with or want to learn more about the difference between threads and processes, make sure to read our article, Linux Process vs. Thread.
2. Checking the Thread Count
In this section, we’ll see how we can get the immediate thread count information of a process. Altogether, we have several options for that. Let’s dive right in.
2.1. Using the ps Command
The command ps displays information about current active processes on the computer. Combining the options -e and -f is a standard approach we can use to get the information on every process in a formatted way. Similarly, we can attach the -L option to make ps report the additional thread information:
$ ps -eLf
UID PID PPID LWP C NLWP STIME TTY TIME CMD
root 1 0 1 0 1 12:00 ? 00:00:01 /sbin/init splash
root 2 0 2 0 1 12:00 ? 00:00:00 [kthreadd]
root 3 2 3 0 1 12:00 ? 00:00:00 [rcu_gp]
root 4 2 4 0 1 12:00 ? 00:00:00 [rcu_par_gp]
root 6 2 6 0 1 12:00 ? 00:00:00 [kworker/0:0H-events_highpri]
root 9 2 9 0 1 12:00 ? 00:00:00 [mm_percpu_wq]
root 10 2 10 0 1 12:00 ? 00:00:00 [rcu_tasks_rude_]
root 11 2 11 0 1 12:00 ? 00:00:00 [rcu_tasks_trace]
root 12 2 12 0 1 12:00 ? 00:00:00 [ksoftirqd/0]
root 13 2 13 0 1 12:00 ? 00:00:00 [rcu_sched]
root 14 2 14 0 1 12:00 ? 00:00:00 [migration/0]
root 15 2 15 0 1 12:00 ? 00:00:00 [idle_inject/0]
root 16 2 16 0 1 12:00 ? 00:00:00 [cpuhp/0]
root 17 2 17 0 1 12:00 ? 00:00:00 [cpuhp/1]
.
.
.
baeldung 1970 1350 1970 0 5 12:01 ? 00:00:01 /usr/libexec/gnome-terminal-server
baeldung 1970 1350 1971 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
baeldung 1970 1350 1972 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
baeldung 1970 1350 1973 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
baeldung 1970 1350 1977 0 5 12:01 ? 00:00:00 /usr/libexec/gnome-terminal-server
baeldung 1978 1970 1978 0 1 12:01 pts/0 00:00:00 bash
baeldung 1996 1350 1996 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
baeldung 1996 1350 1997 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
baeldung 1996 1350 1998 0 3 12:02 ? 00:00:00 /usr/libexec/gvfsd-metadata
baeldung 1999 1607 1999 0 4 12:02 ? 00:00:00 update-notifier
baeldung 1999 1607 2002 0 4 12:02 ? 00:00:00 update-notifier
baeldung 1999 1607 2003 0 4 12:02 ? 00:00:00 update-notifier
baeldung 1999 1607 2004 0 4 12:02 ? 00:00:00 update-notifier
root 2139 2 2139 0 1 12:07 ? 00:00:00 [kworker/u4:1-events_unbound]
root 2149 2 2149 0 1 12:15 ? 00:00:00 [kworker/1:1-cgroup_destroy]
root 2240 2 2240 0 1 12:32 ? 00:00:00 [kworker/0:1-events]
root 2241 2 2241 0 1 12:32 ? 00:00:00 [kworker/0:3-inet_frag_wq]
root 2247 2 2247 0 1 12:36 ? 00:00:00 [kworker/u4:0-events_unbound]
root 2298 2 2298 0 1 12:43 ? 00:00:00 [kworker/u4:2]
root 2335 2 2335 0 1 12:44 ? 00:00:00 [kworker/1:0-cgroup_destroy]
root 2336 2 2336 0 1 12:44 ? 00:00:00 [kworker/0:0-events]
baeldung 2346 1978 2346 0 1 12:45 pts/0 00:00:00 ps -eLf
In the output, the NLWP (Number of Light Weight Processes) column indicates the number of threads attached to that particular process. For example, when we take a look at a process that has an NLWP value of more than one, we can see that the corresponding number of rows after it has the same PID value.
However, if we don’t want to receive all this messy information for every process and we’re only searching for the number of threads of a specific process, we can make use of ps with the -o option:
$ ps -o nlwp 1970
NLWP
5
Here, nlwp indicates the column we used to get the thread count information above, and 1970 is the PID of a process. As we can see, this process runs five threads simultaneously. We can get the same result by using thcount instead of nlwp if we’d like:
$ ps -o thcount 1970
THCNT
5
2.2. Inspecting the /proc Directory
In a similar fashion, we can examine the /proc directory for thread count data. /proc is a virtual file system that contains various information about processes. Let’s take a look at what information we can get:
$ ls /proc/1970/task/
1970 1971 1972 1973 1977
As we see clearly above, the process with PID 1970 contains five threads. In fact, this result matches what we got with the command ps previously. Furthermore, we can verify that these directory names are exactly the same as the appropriate results under the LWP column.
Another way to look for thread count information is by examining the status file under the convenient folder:
$ cat /proc/1970/status | grep Threads
Threads: 5
3. Monitoring the Thread Count
So far, we’ve looked at getting the immediate result by using several methods. Let’s now see the case when we want to monitor the status in real-time.
3.1. Combining Previous Commands With watch
When we use the tool watch combined with the commands we mentioned in the previous section, we can monitor the thread status of any process in real-time. We can also specify the update intervals in seconds with the -n option. Let’s see an example:
$ watch -n 1 ps -o thcount 1970
Every 1,0s: ps -o thcount 1970 baeldung: Tue Mar 29 16:35:30 2022
THCNT
5
Please note that the above result refreshes every second. watch runs the command ps -o thcount 1970 every second and shows the output back to the console.
3.2. Making Use of the top Tool
top is a built-in program that reports system information like CPU usage and memory status. We can use this tool to get thread-count-per-process information, but it’s disabled by default. Therefore, we’ll have to manually tweak the tool. First, we need to get into the utility:
$ top
Then, after pressing the key f, we’ll see a list of metrics that top can display. Let’s select the nTH field accordingly with d and head back to the main interface by pressing q:
top - 15:53:11 up 3:52, 1 user, load average: 0,14, 0,13, 0,09
Tasks: 198 total, 1 running, 197 sleeping, 0 stopped, 0 zombie
%Cpu(s): 1,7 us, 0,7 sy, 0,0 ni, 97,3 id, 0,0 wa, 0,0 hi, 0,3 si, 0,0 st
MiB Mem : 971,2 total, 90,5 free, 543,3 used, 337,4 buff/cache
MiB Swap: 923,3 total, 718,7 free, 204,6 used. 273,4 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND nTH
1622 baeldung 20 0 4218272 304356 76152 S 2,3 30,6 2:22.32 gnome-shell 12
1416 baeldung 20 0 286816 58088 24356 S 1,7 5,8 0:39.93 Xorg 2
1970 baeldung 20 0 818528 43312 30420 S 1,0 4,4 0:16.31 gnome-terminal- 5
1547 baeldung 20 0 158108 2068 1984 S 0,3 0,2 0:13.21 VBoxClient 4
1 root 20 0 167660 7924 5496 S 0,0 0,8 0:01.38 systemd 1
2 root 20 0 0 0 0 S 0,0 0,0 0:00.00 kthreadd 1
3 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_gp 1
4 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 rcu_par_gp 1
6 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 kworker/0:0H-events_highpri 1
9 root 0 -20 0 0 0 I 0,0 0,0 0:00.00 mm_percpu_wq 1
10 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rcu_tasks_rude_ 1
11 root 20 0 0 0 0 S 0,0 0,0 0:00.00 rcu_tasks_trace 1
12 root 20 0 0 0 0 S 0,0 0,0 0:00.21 ksoftirqd/0 1
13 root 20 0 0 0 0 I 0,0 0,0 0:00.53 rcu_sched 1
14 root rt 0 0 0 0 S 0,0 0,0 0:00.03 migration/0 1
15 root -51 0 0 0 0 S 0,0 0,0 0:00.00 idle_inject/0 1
16 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/0 1
17 root 20 0 0 0 0 S 0,0 0,0 0:00.00 cpuhp/1 1
It’s important to note that the process with PID 1970 has five threads, as we saw with previous methods.
We can also use the more modern version htop. The idea is the same. However, keep in mind that top generally comes built-in whereas we may need to install htop manually.
4. Conclusion
To sum up, we’ve now learned how to get and track the thread count information of a process using several tools and methods. Feel free to read the man pages of the tools and try to implement what we’ve learned.