Java threads in linux

Thread Priority in Linux and Java

Jul 11, 2020 · 16 min read

First a caveat, this article describes Java thread priority as it works on Linux, the description below may or may not apply to other OS.

What is a thread in Linux?

Before getting into what thread priorities mean, its good to first recap what is a thread in Linux. A thread in Linux is just another process, there is no concept of thread in Linux kernel. Here is a simple java program illustrating this. The program renames main thread to MainThread and then starts a new thread with name ForkedThread and then waits forever:

When you run the program, it will wait forever and using top we can see both threads (few columns are removed in output below to make it fit in one line):

Note that the two threads have different PID . This has an interesting implication that from Linux Scheduler scheduling perspective, both threads are same and are independently scheduled. This along with the PR and NI columns are what most of this article is about, so take a note of the values in those columns.

But wait, aren’t threads supposed to share memory, file descriptors etc with other threads in the same process? How does that work in this model? Linux achieves this via passing appropriate flags to the clone system call that is used to create a child process. Here is flow of code from Java to Linux layer (github hyperlinks to OpenJDK/glibc code is provided for the curious). When we call Thread.start in Java, it ends up calling a native method start0 (Thread.java):

start0 is declared in Thread.c :

JVM_StartThread is implemented in jvm.cpp where it makes this call to create thread:

The class JavaThread is declared in thread.hpp and implemented in thread.cpp, where the JavaThread constructor makes this call:

which is defined for each supported OS type. For linux code is in os_linux.cpp, where it ends up calling pthread_create :

The call ends up in glibc , where its implemented in pthread_create.c, where it makes this call:

The create_thread is defined in linux/createthread.c where it makes linux clone system call to create a child process. Here is what man clone says about sharing:

Indeed the glibc createthread.c passes multiple flags to share these resources. Here is excerpt from comment from the code:

To summarize, a Linux thread is nothing but a process which shares various resources with another process to enable programming language level thread semantics.

So when we create a thread in Java program running on Linux, the newly created thread becomes just another process that Linux scheduler allocates CPU to. As setting Java thread priority is trying to influence how much cpu time this new process gets, its important to understand how Linux scheduling works.

Process Scheduling in Linux

Linux has multiple schedulers that can be used to schedule processes. There is priority based scheduler and timeshare based scheduler. Linux allows multiple schedulers to co-exist simultaneously and schedule processes.

The way it works is that each process has a static priority and an associated scheduling policy. Static priority of a process can range from 0 to 99. The default static priority is 0 and is used for normal processes. Static priority in the range 1 to 99 is used by realtime processes. All scheduling is preemptive based on static priority of the process. A higher priority process runs before lower priority process and can preempt an existing running lower priority process. If two processes have same static priority, then the order is determined by the scheduling policy at that priority level.

A scheduling policy is implemented by a scheduler. Process having priority of 1 to 99 need to use a realtime scheduling policy. There are two types of realtime scheduling policies, RoundRobin/RR and FIFO . Process having priority of 0 are scheduled by scheduling policy SCHED_NORMAL (also called by its Posix name SCHED_OTHER ). So realtime processes always get scheduled before normal processes.

The scheduler implementing SCHED_NORMAL scheduling policy is Completely Fair Scheduler (or CFS) . It is a timeshare scheduler in the sense that all process it schedules get a time slice from a time quantum in round robin fashion. This is the scheduler that is used by default to schedule normal Linux processes. This article thus looks into java thread priority as implemented by CFS scheduler. Here is excerpt from man 7 sched explaining this:

Читайте также:  Драйвера для материнской платы asrock h55m le windows 10

The Completely Fair Scheduler (CFS)

At a high level, CFS works by first defining a target latency , which is minimum amount of time required for each runnable process to get one turn on the processor. So if target latency is 30 ms and we have 6 runnable processes, each one will get 5 ms to execute. Generalizing it, if there are N runnable tasks, each task will get 1/N slice of target latency . There is a limit on how small a slice can become, as there is cost of context switching. So there is a minimum granularity specified, it is the floor of the time slice. If N becomes too big so that «1/N of target latency» , the machine is overloaded.

Here are values on my Linux box:

The values are in nanosecs, so target latency is 24 msec and min granularity is 3 msec on my desktop box. The box has 12 cores, so it can have 96 concurrent running processes.

CFS also supports a nice value for a process. The value ranges from -20 to 19 with 0 being the default. A nice value works in reverse direction of priority, higher value is low priority (means the process is nice to other ones running on the machine). The way nice value is taken into account by CFS is that the process’s 1/N slice of target latency get weighted by their nice values (so its no longer simple division). So a higher nice value means smaller slice of the target latency, whereas a negative nice value leads to the process getting higher slice of the target latency. The main thing to note is that unlike real time schedulers, with CFS each process will get a chance to run at least once in each target latency period. The amount of time slice it gets depends on the nice value of the process and number of running processes. Here is relevant portion from man 7 sched about this:

With all the background out of way, now we can look into how thread priorities are implemented in Java.

Thread Priority in Java

Java Thread class has a setPriority method that can be used to set priority of a thread. The method takes the priority to set as a parameter. The value can be anything between Thread.MAX_PRIORITY and Thread.MIN_PRIORITY (defined as 10 and 1 respectively). Default is Thread.NORM_PRIORITY with a value of 5.

Here is a simple java program that creates two threads named HighPriority and LowPriority , sets their priority to be 3 above and 3 below Thread.NORM_PRIORITY and then wait for these threads to terminate. The forked threads however going to sleep. This keeps the program running and allows us to check the scheduler related information for them from the command line.

Here is output of running the program and using top to check status:

Looking at the listing of all threads in process 2046 we can see the two threads we have created, HighPriority and LowPriority are there along with other JVM threads like GC threads. Did you notice anything different in PR and NI values for these threads?

Well, me neither. Looking at JDK source code where thread priority is set in os_linux.cpp:

Seems like we need to set UseThreadPriorities and ThreadPriorityPolicy JVM settings. Here is what documentation of the method says:

Here is another try with setting the VM flags as suggested by documentation (and code):

Now if we take a look at the nice column, HighPriority thread has a value of -3 whereas LowPriority thread has a value of 3, so it seems to be working now. However, there are two things to notice:

  1. This way of launching a program has a side effect that all JVM threads have got a nice bump in the priority too (a negative nice value). This shows internally JVM itself is setting priorities for threads that it deems important, but they don’t take effect as we don’t normally use these flags on java command line.
  2. We needed to use sudo to launch the program. JVM will refuse to start if we launch this command as non superuser.

In Linux an owner of a process can always lower its priority and doesn’t require root privilege, but JVM enforces it. There is a workaround where specifying ThreadPriorityPolicy something other than 0 or 1 will allow JVM to launch the process and also allow lowering the priority (positive nice value) without requiring sudo . But increasing priority will need JVM to be launched with root privilege. Here is documentation about these flags from JDK code globals.hpp:

Next question that arises is what thread priority to pick up for an application. Here is Java priority to Linux nice value mapping in os_linux.cpp:

Читайте также:  System windows forms sendkeys sendwait

So the minimum value one can go to is a nice value of 4 (corresponds to Thread.MIN_PRIORITY ). NOTE: JVM allows mapping to be changed using JVM flags, but lets use this mapping for our discussion. So, how much difference a nice value of 4 can make?

nice to weight mapping is hard-coded in Linux kernel/sched/core.c (with default value of 1024):

Based on this a thread with nice value of 4 will get only 42.3% weight of a normal thread. So if we only have two threads, one with nice value of 4 and one normal thread and a target latency of 20 msec, normal thread will get 14.3 seconds and thread with nice value of 4 will get remaining 5.7 seconds.

So this leaves us with a bigger question, even if I can set thread priority, will it help with my java application? There are few practical issues:

  1. CFS gurantees that all runnable threads will get a time slice in the target latency . So if my application creates too many low priority threads (say N threads) it can starve normal priority threads (say M threads), if N >> M. To have desired impact application need to control number of threads its spawning.
  2. As at Linux level there is no concept of threads, the issue is present at OS level itself. So even if a user can somehow control number of threads that its launching it may not help. A high priority thread in an application (like GC threads in JVM example above) may get starved if there are too many processes running on the system.

Normal desire in this type of scenario is to guarantee a minimum (or constrain to a maximum) cpu usage that a process (or process group) can receive. In addition for some use cases, its ok to absorb additional cpu cycles when the load is low and cpu is idle.

First ask here is to be able to create a thread/process group on which nice value can be applied. This allows a process to create a thread pool for a job running at a certain priority. Linux has an autogroup feature for this. All processes that are forked by a process are put in the parent’s autogroup . All members of an autogroup are put into same scheduler’s task group . The CFS scheduler then treats a task group as one entity on which nice value can be applied.

The second feature that can limit cpu usage by a process or autogroup , is Linux control groups (or cgroups ). The cpu scheduling part of cgroups again uses CFS scheduler to do its job.

Considering cgroups and docker (or any other container technology) is how most of the applications are deployed currently in Linux, its hard to see where setting Java Thread priority is useful. However, understanding how all pieces of this puzzle fits together is helpful.

Источник

4 commands to check thread count per process (threads vs processes) in Linux

Table of Contents

In Linux, some processes are divided into pieces called threads. In one liner, threads are essentially just processes with a shared address space on Linux. In this article we will get some brief overview on threads and processes, also some examples to show threads per process, check thread count per process, check number of threads allowed, count threads and some more related topics.

Threads vs Processes

  • A thread is very similar to a process, it has an identifier (TID, or thread ID), and the kernel schedules and runs threads just like processes.
  • However, unlike separate processes, which usually do not share system resources such as memory and I/O connections with other processes, all threads inside a single process share their system resources and some memory.
  • A process with one thread is single-threaded , and a process with more than one thread is multithreaded .
  • All processes start out single-threaded . This starting thread is usually called the main thread. The main thread may then start new threads in order for the process to become multithreaded, similar to the way a process can call fork() to start a new process.
  • The primary advantage of a multithreaded process is that when the process has a lot to do, threads can run simultaneously on multiple processors, potentially speeding up computation.
  • Although you can also achieve simultaneous computation with multiple processes, threads start faster than processes, and it is often easier and/or more efficient for threads to intercommunicate using their shared memory than it is for processes to communicate over a channel such as a network connection or a pipe.

Show threads per process

1. Using PID task

You can count threads with the list of available sub directories inside /proc/

/task/ . The count of total available sub-directories inside this part is directly proportional to the thread count per process for the provided PID.

Читайте также:  Windows into safe mode

For example to check java thread count, I have a Java process for which you can see I have multiple sub-directories so it means this is a multi threaded process. using ls command under this path you can show threads per process for java

But then again I have another process for which as you can see I have single sub-directory hence we know this is a single thread process

2. Using ps command

You can also use » ps » command to show threads per process. With » ps » we can list LWP (Light Weight process) which depicts Thread ID of the respective process and NWLP (Number of Threads).

To show threads per process using ps command you can use below argument

3. Using pstree command

You can also use pstree to show threads per process. Here as you see java thread count and check number of threads for java process

4. Using top command

In top , by default we will not be able to see thread count per process. But when running top , it is possible to change which fields to display and add this column to print thread count per process can be added manually.

  • Press f
  • This will show a list of fields that top can display. The fields that are displayed in bold are the ones that top will display.
  • Use the down arrow to navigate to «nTH» (Number of Threads).
  • Press to select «nTH«
  • Press ‘s‘ to sort on number of threads.
  • Press ‘q‘ to display the data of threads count.

Next you should see a new column at the end of top command with number of thread (nTH) column to show threads per process

Check thread count per process

Next you can use the above explained commands to also check thread count per process by customising them a little bit.

1. Using PID status

To check thread count per process you can use below command. For example here java thread count is 59 threads in my Linux environment

While amsHelper process has single thread

2. Using ps command

We used ps command to show threads per process and count threads, we can also use » ps » command to get LWP and NLWP details, which when combined with » wc » we can count threads per process.

To check thread count per process for a particular PID for example to check java thread count:

Check number of threads allowed in Linux system?

Linux doesn’t have a separate threads per process limit, j ust a limit on the total number of processes on the system . This value controls the maximum number of threads that can be created using fork() . During initialization the kernel sets this value such that even if the maximum number of threads is created

To check number of threads which Linux system can allow

The minimum number of threads that can be written to threads-max is 20 .
The maximum value that can be written to threads-max is given by the constant FUTEX_TID_MASK (0x3fffffff) .
If a value outside of this range is written to threads-max an error EINVAL occurs.

The default value depends on memory size. You can use threads-max to check number of threads allowed in Linux. You can increase thread count per process limit like this:

There is also a limit on the number of processes (an hence threads) that a single user may create, see ulimit for details regarding these limits:

Here, the system is able to create 35,000 threads/processes in total and a single user can create 10000 number of processes.

The logic is very simple here every CPU can execute 1 process at a time, if there are 8 cores that means 8 to 10 processes at a time can be executed easily without any stress but if number of running or runnable threads per CPU increases drastically then there will be performance issue.

What is the maximum processes count allowed in Linux?

Verify the value for kernel.pid_max

Here I can execute 35,000 processes simultaneously in my system that can run in separate memory spaces.

To change the value of kernel.pid_max to 65534:

Lastly I hope the steps from the article to show threads per process, check thread count per process, check number of threads allowed on Linux was helpful. So, let me know your suggestions and feedback using the comment section.

Didn’t find what you were looking for? Perform a quick search across GoLinuxCloud

If my articles on GoLinuxCloud has helped you, kindly consider buying me a coffee as a token of appreciation.

For any other feedbacks or questions you can either use the comments section or contact me form.

Thank You for your support!!

Источник

Оцените статью