이 글은 www.androiddesignpatterns.com에 소개된 글을 저자의 동의를 얻고 번역한 것임을 알려드립니다.

원문 : http://www.androiddesignpatterns.com/2014/01/thread-scheduling-in-android.html

 

이 글은 Android가 어떻게 Thread를 Scheduling를 하는지와 다수의 Thread가 동작하면서 동시에 빠릿빠릿한 UI 동작을 보장하기 위해서는 어떻게 Thread의 priority를 설정해야 하는지 설명한다.

thread scheduler : Operating System에서 다수의 thread가 동시에 동작 할 때, 어떤 thread가 실행되어야 하고, 언제 실행되어야 하고, 또 얼마나 오래 실행되어야 하는지를 결정하는 부분이다. 즉! 한정된 Time slice를 다수의 Thread에 분배하는 일을 한다. Android의 thread schedulernice valuescgroups  2개를 참고하여 scheduling을 한다.

 

Nice values

Linux의 fair scheduling 정책과 같이, Android는 nice values를 이용하여 thread의 우선순위를 결정한다. 높은 nice value(이때 nice는 같이 실행되는 다른 thread에게 ‘nice’ 하다는 의미로, 우선순위는 상대적으로 낮다)를 갖는 Thread는 낮은 nice value를 갖는 thread에 비해 더 적은 실행시간을 할당 받는다.  역설적으로 Thread의 우선순위는 Thread가 수행해야 하는 작업의 양에 반비례한다.  더 많은 일을 해야 하는 Thread 일수록 더 낮은 우선순위를 할당 받아 System이 정상동작 할 수 있도록 한다.

이러한 이유로, user interface thread는 default priority를 할당받고, background thread는 background priority를 부여 받는다.

이론적으로 User interface가 중단되지 않도록 하기 위해서는 background 작업을 줄여야 하기 때문에 Nice value는 중요하다. 하지만 실제로 Nice value만으로는 부족하다. 예를 들어, 12개의 background thread가 동작하고, 하나의 foreground thread가 UI를 담당하고 있다고 가정해보자. background thread 각각은 낮은 우선순위를 갖지만 그 총합은 foreground thread 동작에 영향을 미쳐 사용자 경험에 악영향을 끼칠것이다.

하지만 많은 Android Application이 다수의 background thread를 동시에 사용하고 있기 때문에,  Android OS는 이러한 문제를 반드시 해결해야만 한다. 이제 cgroups으로 넘어가 보자.

 

Cgroups

이러한 문제를 해결하기 위해 Android는 Linux의 cgroups(control groups)을 통해 foreground vs background scheduling 정책을 사용한다.

Background 우선순위를 갖는 Thread는 background cgroup으로 이동한다. background cgroup은 다른 group이 바쁠 때 매우 적은 비율(5%)의 CPU 실행 시간만 부여 받을 수 있도록 제한된다. 이렇게 구분함으로써 foreground thread에 영향을 미치지 않고 background thread가 작업을 수행할 수 있고 foreground thread는 여전히 responsive한 상태로 남아있다.

더 나아가 낮은 background cgroup의 thread에 자동으로 낮은 우선순위를 할당하기 때문에 Android는 foreground에서 동작하지 않는 Application들을 background cgroup으로 자동으로 보낼 수 있다. (Application이 foreground에서 background로 내려갈 때 우선순위 조정)

위와 같이 background application에 자동으로 낮은 우선순위를 부여하기 때문에, 얼마나 많은 application이 background에서 동작하고 있는지와 상관없이 foreground application이 가장 높은 우선순위를 부여받을 수 있다.

 

Setting Priorities with Process#setThreadPriority(int)

대개, Android API는 worker thread에 background 우선순위를 할당한다. (eg. HandlerThread, AsyncTask)   하지만 반드시 그렇지는 않다. Main UI Thread에서 실행된 ThreadsExecutorServices default나 foreground 우선순위를 부여받아 성능에 영향을 미칠 수 있다. 이런 경우에는 Thread가 동작을 수행하기 전 Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND)를 명시적으로 호출하여 우선순위를 조정해야 한다.

 

Good job!