NDK thread policy and priority not working

74 views
Skip to first unread message

Alec Miller

unread,
May 18, 2022, 11:57:27 AMMay 18
to android-ndk
We are seeing a slowdown on Android from using any NDK pthreads.  I have a 2/2/4 CPU, and a 4/4 CPU.  In both cases, the performance is 3-4x slower, but should be 3-4x faster even just using the big+medium cpus.   On iOS, we see the expected 3x speedup and don't have affinity but do have policy/priority (SCHED_RR 41).  On iOS, one can even set high priority of > 90. On Android, I have affinity controls set to single or groups of big+med cores.   

The last discussion of this on the forums was from 2015, and many Stack Overflow discussions indicate needed to wrap the thread over to JNI to make priority calls there.

pthread_setschedparam() fails for policy, and succeeds for any policy >= 0.  That means I guess I can only lower priority.    I assume this would normally be 20 to -20, but going < 0 means higher priority. 

pthread_getschedparam() always returns 0 for policy (SCHED_OTHER?) and 0 for priority.  So am I actually setting this?

ptherad_setschedprio() only seems to be available on API 28, and I don't want to deal with dll loading that in a minSDK API 26 application.  This may be broken too, even if I did the effort.

Thread.setThreadPriority are the only examples provided in "Android Performance Patterns".  With the suggestion to always set priority, but none of this applies if priority is broken in the NDK.

Alec Miller

unread,
May 18, 2022, 12:13:24 PMMay 18
to android-ndk
There are even affinity, policy, and priority attribute settings for pthread creation.  But since these parameters seem to fail thread creation, I'm trying to set these after thread creation, since I can ignore failure and still have a thread.

Elliott Hughes

unread,
May 18, 2022, 12:17:34 PMMay 18
to android-ndk
if they fail at thread creation time, they'll almost certainly fail later --- it's the exact same system calls.

fwiw, these functions all "work" and are used by the system, but they might not allow you to do what you want because what an app (versus a system process) can do is restricted by security policies.

Alec Miller

unread,
May 19, 2022, 5:32:22 PMMay 19
to android-ndk
Yes, but like I said, I'd rather have a thread than have it fail at create.   I can ignore the failures after I have a valid thread, but can't ignore a thread that failed to create and try to figure out which of the settings caused it.  I was just suggesting that if these setters can't change the value after create, then attributes at create time could be one solution.  But the danger of not getting a thread back is not something I care to test.

Alec Miller

unread,
May 19, 2022, 5:32:23 PMMay 19
to android-ndk
There is no documentation in the pthread headers or from Google about what is or isn't working, and whatever security policies there are only briefly mentioned in message threads from random Android devs.

So I if call the following on a minSDK 26 device.  This is what happens.

```
int priority = 2;
int policy = 0;  // SCHED_OTHER?  it's 1 on Apple, only 0 works on Android NDK pthread 
struct sched_param priorityVal = { priority }; 
int rt = pthread_setschedparam( pthread_self(), policy, &priorityVal );
assert( rt == 0 );  <- success, didn't change policy due to security, but I should be able to lower priority

priorityVal.sched_priority = -1;
rt = pthead_getschedparam( pthread_self(), &policy, &priorityVal );
assert( rt == 0 );  <- success, I got the policy/priority back
assert( policy == 0 );  <- okay, didn't change policy since I can't
assert( priorityVal.sched_priority == 2 ); <- fails, returns 0

```

On Wednesday, May 18, 2022 at 9:17:34 AM UTC-7 e...@google.com wrote:

Alec Miller

unread,
May 26, 2022, 1:53:45 AMMay 26
to android-ndk
Found that Vulkan validation layer trampolines all calls through a single mutex.   So each function call is suddenly conflicting with any other threads trying to generate commands on other threads.

Alec Miller

unread,
Jun 22, 2022, 5:12:36 PMJun 22
to android-ndk
Recommendation from the Filament team, and their job manager was to use the following.  This has a setter and getter, but can only adjust the current thread priority.  It looks like it's setting some global priority on the process, but it's not.

setpriority( PRIO_PROCESS, 0, priority );

priority values are 0, -4, -8 where negative is higher priority.  Pretty sure the full range is -20 to 20.

Reply all
Reply to author
Forward
0 new messages