Good day colleagues,
For the second week I have been struggling with android and its performance is very confusing for me.
On a clean project, without any effects, in release mode, with all possible optimizations and even a large buffer of 1920 samples, the CPU core goes over 100% and android hangs into eternity. Below is pseudocode that blindly simulates some kind of complex activity.
And I got the following results:
Average CPU load:
Apple M1- 25-27%
Apple A12X - 35-45%
A10 Fusion - 60.4-61%
Intel x64 i5 - 60-70%
Snapdragon 855 - more than 100%, even if I use 512 cycles. Sound is stable only if 256 cycles.
OFast
ffast-math
LTO
release
It looks like some kind of wildness for me :(. The difference 16 times slower on android? Why the apple’s processor can handle the 4096, even 16384 cycles without any problem, but snapdragon 855 only 256 ? Or this is something with Google’s OBOE ?
Thank you!
Pseudo code:
inline void processBlock(AudioBuffer<float> &buffer, int length) noexcept {
float outputBuffer[2][length];
for (int i = 0; i < length; ++i) {
outputBuffer[0][i] = 0.0f;
outputBuffer[1][i] = 0.0f;
}
// oversampling 4x
for (int s = 0; s < 4; ++s) {
// 16 notes/voices
for (int v = 0; v < 16; ++v) {
// 4 oscillators
for (int o = 0; o < 4; ++o) {
// 16 unison for each osc
for (int u = 0; u < 16; ++u) {
// length 44100/48000 samples in one second
for (int i = 0; i < length; ++i) {
auto &pos = phaseAccumulator_[v][o][u];
// get amplitude
auto sound = waveSample_[(int) pos];
// fill buffer
outputBuffer[0][i] += sound; // channel 1
outputBuffer[1][i] += sound; // channel 2
// move phase
pos += 0.02321995464f * 440.0f; // hz
if (pos >= 1024.0f) {
pos -= pos;
}
}
}
}
}
}
auto *bufferRef = buffer.getArrayOfWritePointers();
for (int i = 0; i < length; ++i) {
auto gain = 0.0001f;
bufferRef[0][i] = outputBuffer[0][i] * gain;
bufferRef[1][i] = outputBuffer[1][i] * gain;
}
}
private:
float waveSample_[1024]{}; // you can keep it with zero or fill with sine, square...
float phaseAccumulator_[16][4][16]{};
p.s. I deliberately did not write it with FloatVectorOperations here, because I want to test exactly the same and basic code on different platforms.
Of course, this pseudocode looks terrible and is not optimized, but if I optimize it, the results will be better for apples and intel cpu. On M1 with float vector optimizations and some rearrange I even got 2-3% percent of the load. So my goal is not to optimize the code above, but to understand why it so slow on android.
