How are good scheduler priorities and policies related to process identifiers (thread?) On Linux?

I am learning how to make my Linux desktop remain smooth and interactive while I run intensive processor tasks in the background. Here is an example program (written in Java) that I use to simulate processor load:

public class Spinner { public static void main(String[] args) { for (int i = 0; i < 100; i++) { (new Thread(new Runnable() { public void run() { while (true); } })).start(); } } } 

When I run this on the command line, I notice that the interactivity of my desktop applications (like a text editor) drops significantly. I have a dual-core machine, so I'm not surprised at this.

To combat this, my first thought was a good process with renice -p 20 <pid> . However, I found that this does not have much impact. Instead, I have to restore all child processes with something like ls /proc/<pid>/task | xargs renice 20 -p -- ls /proc/<pid>/task | xargs renice 20 -p -- which has a much greater effect.

I am very confused about this since I did not expect threads to have their own process identifiers. Even if they did, I would expect renice to act on the whole process, not just the main thread of the process.

Does anyone have a clear idea of โ€‹โ€‹what's going on here? It seems that each thread is actually a separate process (at least it has a valid PID). I knew that historically Linux worked this way, but I thought NPTL was fixed many years ago.

I am testing RHEL 5.4 (linux kernel 2.6.18).

(Aside. I notice the same effect if I try to use sched_setscheduler(<pid>, SCHED_BATCH, ..) to try to solve this interactivity problem. That is, I need to make this call for all the "child" processes that I I see in /proc/<pid>/task , itโ€™s not enough to execute it once on the main pid program.)

+6
source share
2 answers

Stream identifiers come from the same namespace as the PID. This means that each thread is invididually addressed by its TID - some system calls apply to the whole process (for example, kill ), but others apply to only one thread.

Scheduler system calls tend to be in the last class, because it allows you to give different threads in a process with different scheduler attributes, which is often useful.

+2
source

As I understand it, in Linux, threads and processes are almost the same; threads are simply processes that use the same memory, and do not do fork copy-on-write, and fork (2) and pthread_create (3) are supposedly both simply superimposed on the clone (2) call with different arguments.

The planning material is very confusing because, for example, pthreads (7) starts with a message that the Posix threads have a common pleasant value, but then you need to go to

NPTL still has some inconsistencies with POSIX. 1: Threads do not share an overall pleasant value

to see the whole picture (and I'm sure there are many more useful pages).

I wrote graphical applications that spawn many computational threads from the main user interface thread and always find the key to keep the application very responsive in order to call nice (2) in the computational threads (only); increasing it by 4 or so seems to work well.

Or at least what I remember. I just looked at the code for the first time in many years and saw that I actually did this:

 // Note that this code relies on Linux NPTL non-Posix-compliant // thread-specific nice value (although without a suitable replacement // per-thread priority mechanism it just as well it that way). // TODO: Should check some error codes, // but it probably pretty harmless if it fails. const int current_priority=getpriority(PRIO_PROCESS,0); setpriority(PRIO_PROCESS,0,std::min(19u,current_priority+n)); 

Interestingly. I probably tried it well (2) and found that it really applies to the whole process (all threads), which I did not want (but maybe so). But this is already happening a few years ago; behavior may change since.

One important tool when you play with such things: if you press "H" (NB is not "h") at top (1) , it changes the look of the process, showing all threads and individual threads with good values. For example, if I run [evolvotron][7] -t 4 -n 5 (4 compute threads in nice 5), I see (I am on an old single-core machine other than HT, so this is actually not so much in several threads):

 Tasks: 249 total, 5 running, 244 sleeping, 0 stopped, 0 zombie Cpu(s): 17.5%us, 6.3%sy, 76.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st Mem: 1025264k total, 984316k used, 40948k free, 96136k buffers Swap: 1646620k total, 0k used, 1646620k free, 388596k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 4911 local 25 5 81096 23m 15m R 19.7 2.4 0:04.03 evolvotron 4912 local 25 5 81096 23m 15m R 19.7 2.4 0:04.20 evolvotron 4913 local 25 5 81096 23m 15m R 19.7 2.4 0:04.08 evolvotron 4914 local 25 5 81096 23m 15m R 19.7 2.4 0:04.19 evolvotron 4910 local 20 0 81096 23m 15m S 9.8 2.4 0:05.83 evolvotron ... 
+2
source

Source: https://habr.com/ru/post/893682/


All Articles