top | item 35560791

(no title)

peregrine | 2 years ago

I go into this in the article :) the rustler team has a made a DirtyNif that can work around that, or you can manually yield if you'd like.

discuss

order

clessg|2 years ago

Indeed, your (excellent) article addresses this, here's the gist for those following along:

> Change `#[rustler::nif]` to `#[rustler::nif(schedule = "DirtyCpu")]`

> This tells the Rustler and BEAM to automagically schedule this in a way that won't block the entire world while it works. Again amazing, this is called a DirtyNif and is way more difficult to work with when you are manually using this via C.

Essentially, regular NIFs have to be extremely fast (< 1ms) because the VM can't preempt them - they run on the same scheduler threads the BEAM itself uses. Dirty NIFs solve this by running jobs in a completely separate thread pool ("dirty schedulers"). Rustler's docs explain it succinctly (https://docs.rs/rustler/latest/rustler/attr.nif.html):

> For functions that may take some time to return - let’s say more than 1 millisecond - it is recommended to use the `schedule` flag. This tells the BEAM to allocate that NIF call to a special scheduler. These special schedulers are called “dirty” schedulers.

> We can have two types of “lengthy work” functions: those that are CPU intensive and those that are IO intensive. They should be flagged with “DirtyCpu” and “DirtyIo”, respectively.

(Somewhat OT, but since I'm here: excellent article @ peregrine! I really enjoyed the read. Elixir and Rust are such a perfect fit. Plus, some of the specifics will be helpful for certain image-related things I'm actively working on, which is always nice. :) )