Android is a privilege-separated operating system, in which each application runs with a distinct system identity: the Linux user ID (uid).
With this patch (sched-automated-per-uid-task-groups.patch) the kernel automatically creates a distinct task group for each uid (when a process calls set_user()) and places all the tasks that belong to a single uid into the same task group. In this way each application can get a fair amount of the CPU bandwidth (guaranteed by the CFS scheduler), independently by the number of task/threads spawned.
The patch is against the CyanogenMod's 6.1.1 kernel (2.6.35.10) and I tested it successfully on my HTC Desire (Bravo).
I've used the following testcase:
- run 4 cpu hogs in background as user app_35 (com.android.email in my case):
$ for i in `seq 4`; do yes >/dev/null & done
- run the Quadrant benchmark in parallel and measure the result with and without the patch applied
Without the patch (output of top):
PID PPID USER STAT VSZ %MEM CPU %CPU COMMAND
6533 123 10070 R 202m 48.6 0 20.0 com.aurorasoftworks.quadrant.ui.st
6506 1 10035 R 1128 0.2 0 20.0 yes
6507 1 10035 R 1128 0.2 0 20.0 yes
6508 1 10035 R 1128 0.2 0 20.0 yes
6509 1 10035 R 1128 0.2 0 20.0 yes
Benchmark result: 676
uid 10035 (cpu hog) : 60.0 % cpu quota
uid 10070 (benchmark): 20.0 % cpu quota
With automated per-uid task group (output of top):
PID PPID USER STAT VSZ %MEM CPU %CPU COMMAND
6784 123 10070 S 209m 51.4 0 50.0 com.aurorasoftworks.quadrant.ui.st
6852 1 10035 R 1128 0.2 0 12.5 yes
6853 1 10035 R 1128 0.2 0 12.5 yes
6854 1 10035 R 1128 0.2 0 12.5 yes
6855 1 10035 R 1128 0.2 0 12.5 yes
Benchmark result: 816
uid 10035 (cpu hog) : 50.0 % cpu quota
uid 10070 (benchmark): 50.0 % cpu quota
Total speedup: ~1.2 (the benchmark is about 20% faster in this case), because in the last case the benchmark gets ~50% of the CPU time and in the other case it gets only ~20%, despite the fact that there are 2 "pair" applications that should be correctly considered as equal from the user's perspective.