Analysis of process and thread scheduling in Android: nice

Analysis of process and thread scheduling in Android: nice

In computer operating systems, processes are the basic units for resource allocation and scheduling, and each process can also contain multiple threads. So in the Android system (Linux Kernel), how do processes grab resources and how do threads switch based on priority? This article will try to analyze this issue and study the application of nice in Linux and Android systems.

[[148283]]

Some concepts

  • A process is the entity in which a program runs in a computer system and is also a container for threads.

  • A thread is the actual execution unit in a process. A thread is the smallest unit of program execution flow. There can be multiple threads in a process.

Nice and process scheduling

In Linux, the nice value (hereinafter referred to as the nice value) is used to set the priority of a process, and the system task scheduler arranges the scheduling reasonably according to the nice value.

  • The value range of nice is -20 to 19.

  • Normally, the default value of nice is 0. It depends on the specific operating system.

  • The larger the nice value is, the lower the priority of the process is and the fewer opportunities it has to get the CPU to call. The smaller the nice value is, the higher the priority of the process is and the more opportunities it has to get the CPU to call.

  • A process with a nice value of -20 has the highest priority, and a process with a nice value of 19 has the lowest priority.

  • The nice value of the child process forked by the parent process is the same as that of the parent process. If the parent process is renice, the nice value of the child process will not change accordingly.

Etymology

There is almost no information about the origin of the command nice, so I tried to infer it myself. The meanings given in dictionaries such as Ciba and Hujiang are all good; beautiful; lovely; kind, friendly. However, Youdao Dictionary gives a slightly different meaning than other dictionaries, which is kind. I personally think that the one given by Youdao is more reasonable. To be kind, you need to be humble, so you need to sacrifice yourself a little to help others. So the higher the nice value, the kinder you are, but the lower your priority will be.

renice

For a new process, we can set the nice value for a process according to the following code.

nice -n 10 adb logcat

For the created process, we can use renice to modify the nice value

su do renice -n 0 -p 24161

This command requires root privileges, and the value corresponding to -p is the process id.

Note that the -n value of the renice command in Linux distributions should be the target priority of the process. On Mac, -n represents the increase in the current privilege. For example, on Mac, to change the nice value of a process from 19 to 10, you can do this: sudo renice -n -9 -p 24161. This is important to note to avoid falling into a trap.

Nice in Android

Since Android is based on the Linux Kernel, there is also a nice value in Android. However, we generally cannot control it for the following reasons:

  • The Android system is not as convenient as other Linux distributions to use nice commands.

  • Renice requires root privileges, which cannot be achieved by general applications.

Thread Scheduling

Although we cannot control the priority of the process, we can control the priority of the threads in the process. There are two kinds of thread priorities in Android, one is the Android API version and the other is the Java native version.

Android API

The thread priority levels in Android are currently defined as follows. Once you understand the relationship between process priority and nice value, the relationship between thread priority and value will be easier to understand.

  • THREAD_PRIORITY_DEFAULT, the default thread priority, value is 0.

  • THREAD_PRIORITY_LOWEST, the lowest thread level, the value is 19.

  • THREAD_PRIORITY_BACKGROUND It is recommended to set this priority for background threads to 10.

  • THREAD_PRIORITY_FOREGROUND The UI thread that the user is interacting with. This priority cannot be set in the code. The system will adjust it to this priority according to the situation. The value is -2.

  • THREAD_PRIORITY_DISPLAY is also a priority level related to UI interaction, but it takes precedence over THREAD_PRIORITY_FOREGROUND. It cannot be set in the code and is adjusted by the system according to the situation. The value is -4.

  • THREAD_PRIORITY_URGENT_DISPLAY The highest priority of the display thread, which is used to handle drawing screens and retrieving input events. This priority cannot be set in the code. The value is -8.

  • THREAD_PRIORITY_AUDIO The standard level of the sound thread. The priority cannot be set in the code. The value is -16.

  • THREAD_PRIORITY_URGENT_AUDIO The highest priority of the audio thread, higher than THREAD_PRIORITY_AUDIO. This priority cannot be set in code. The value is -19.

  • THREAD_PRIORITY_MORE_FAVORABLE has a slight preference on THREAD_PRIORITY_DEFAULT and a value of -1.

  • THREAD_PRIORITY_LESS_FAVORABLE is slightly behind THREAD_PRIORITY_DEFAULT and has a value of 1.

It is also very simple to set the priority of a thread using the Android API. You only need to call the android.os.Process.setThreadPriority method when the thread is executing. This method of modifying the priority of a thread while it is running has an effect similar to renice.

new Thread () {
@Override
public void run() {
super.run();
android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
}
}.start();

Java Native API

Java provides three levels of settings for Thread.

  • MAX_PRIORITY, equivalent to android.os.Process.THREAD_PRIORITY_URGENT_DISPLAY, with a value of 10.

  • MIN_PRIORITY, equivalent to android.os.Process.THREAD_PRIORITY_LOWEST, has a value of 0.

  • NORM_PRIORITY, equivalent to android.os.Process.THREAD_PRIORITY_DEFAULT, with a value of 5.

Using setPriority we can set the priority for a thread, and using getPriority we can get the priority of a thread.

In the Android system, it is not recommended to use the Java native API, because the API provided by Android is divided into more levels and is more suitable for setting detailed priorities in the Android system.

Notice

The thread priority of Android API is relatively independent from the priority of Java native API. For example, after using android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND), the value obtained by using Java native API, Thread.getPriority() will not change. As shown in the following code:

new Thread() {
@Override
public void run() {
super.run();
Log.i(LOGTAG, "Java Thread Priority Before=" + Thread.currentThread().getPriority());
Process.setThreadPriority(Process.THREAD_PRIORITY_LOWEST);
Log.i(LOGTAG, "Java Thread Priority=" + Thread.currentThread().getPriority());
}
}.start();

The running log of the above code is

I/MainActivity ( 3679 ) : Java Thread Priority Before = 5 I/MainActivity ( 3679 ) : Java Thread Priority = 5

Due to the above defect, we need to pay attention when analyzing ANR trace. In the ANR log information below, the value of proi in prio=5 corresponds to the thread priority of the Java native API, and nice in nice=-6 represents the thread priority of the Android API version.

"main" prio=5 tid=1 NATIVE
| group="main" sCount=1 dsCount=0 obj=0x41690f18 self=0x4167e650
| sysTid=1765 nice=-6 sched=0/0 cgrp=apps handle=1074196888
| state=S schedstat=( 0 0 0 ) utm=5764 stm=3654 core=2
#00 pc 00022624 /system/lib/libc.so (__futex_syscall3+8)
#01 pc 0000f054 /system/lib/libc.so (__pthread_cond_timedwait_relative+48)
#02 pc 0000f0b4 /system/lib/libc.so (__pthread_cond_timedwait+64)

Avoiding ANRs

In my previous article about ANR in Android, I mentioned using WorkerThread to handle time-consuming IO operations and lowering the priority of WorkerThread. For time-consuming IO operations, such as reading databases and files, we can set the priority of the workerThread to THREAD_PRIORITY_BACKGROUND to reduce the ability to compete with the main thread.

<<:  What is the background data of the most popular application in WeChat?

>>:  10 Questions Programmers Should Ask Themselves

Recommend

Galanz sues Tmall for alleged abuse of market dominance

On November 5, 2019, Galanz released an announcem...

FAO: Climate Change Strategy 2022-2031

The Climate Change Strategy, approved by the FAO ...

Detailed explanation of Tik Tok information flow delivery strategy!

Nowadays, more and more companies and projects ar...

Tesla's batteries depend on its Gigafactory's history

Tesla has just released its second quarter 2016 f...

Can a vegetarian be a muscular man?

Recently, I have been paying attention to the iss...

Christmas and New Year's Day marketing plan (attached with download)

Christmas and New Year's Day are important fe...

Vsync signal mechanism and UI refresh process

[[439732]] Preface The screen refresh frame rate ...

Domestication of millet: "Millet" tells the story of a grain of millet

Millet is the most important food crop in ancient...