Find Out What's Running on Dirty Schedulers

Since your NIF reschedules itself to be executed on a dirty CPU scheduler, it indeed has to split the time between actual “processing” and “large heap GC”.

One way to avoid that would be avoiding creating those large heaps (>1 Mb). In the code you pasted you deliberately create heaps over 1 Mb (and therefore GC happens on the dirty scheduler). In actual production code this is rarely deliberate, but often accidental.

For OTP 26, I implemented memory tracing, and OTP 27 also includes Process Heap Profiler that may help you to understand whether memory allocations in your processes are optimal. Fun fact, you don’t need to wait until OTP 27 release, as hprof is compatible with OTP 26. You can just copy and paste the module in your project, and use it.