Skip to content

Rust-based Erlang NIF examples for showing Erlang VM's scheduler issues

License

Notifications You must be signed in to change notification settings

tatsuya6502/bitwise_rust

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

bitwise_rust: Rust-based Erlang NIF examples showing Erlang VM's scheduler concerns

This is a Rust port of Steve Vinoski's bitwise example.

Recently tested with:

  • Rust 1.5.0
  • Erlang/OTP 18.2.1
  • (TODO) Elixir 1.2

What is Bitwise?

The bitwise module implements several Erlang Native Implemented Functions (NIFs) intended to show several different effects NIFs can have on Erlang scheduler threads. The module supplies several variants of a function exor/2 that takes a binary and a byte value and applies exclusive-or of

that byte to every byte in the binary and returns a new binary of the resulting values. These variants operate as follows:

  • One example, exor_bad/2, shows a misbehaving NIF that, given a large enough input binary, takes up far too much time on a scheduler thread, running for multiple seconds. Normally, a NIF should run on a scheduler thread for only a millisecond or less.

  • Another example uses Erlang code to break the large input binary into 4MB chunks, calling exor_bad/2 separately for each chunk and then reassembling the results.

  • The exor_yield/2 variant uses the enif_schedule_nif function, introduced in Erlang/OTP 17.3, to ensure the NIF yields the scheduler thread after consuming a 1 millisecond timeslice. It uses enif_schedule_nif to reschedule itself to run in the future to continue its exclusive-or operation on the input binary.

  • The final variant, exor_dirty/2, uses dirty schedulers, introduced as an experimental feature in Erlang 17.0. This approach schedules the NIF to run on a dirty scheduler thread rather than a regular scheduler thread. Since dirty scheduler threads are not managed threads, they are not constrained the same way regular scheduler threads are with respect to long-running CPU- or I/O-intensive tasks.

About the Original Bitwise by Steve Vinoski

The original C and Erlang code in bitwise was presented at Chicago Erlang, 22 Sep 2014. The code has evolved since that talk, including a fix for the example of how enif_consume_timeslice() and enif_schedule_nif() are used together. In the Chicago Erlang presentation, the code presented for this area miscalculated timeslice percentages; this has been fixed. The slides have been updated to include this fix as well, which means the slides here, in the file vinoski-opt-native-code.pdf, differ from those originally presented.

That code was also presented at CodeMesh 2014, 5 Nov 2014. The slides for that talk, which are in the file vinoski-schedulers.pdf, include more details than those for the Chicago Erlang talk, specifically about a possible dirty driver API.

Long Scheduling

A useful Erlang feature not shown in the code or the Chicago Erlang slides, but mentioned in the CodeMesh slides, is the ability to detect when native code spends too much time on a regular scheduler thread by calling erlang:system_monitor/2 with the {long_schedule, Time} option. For example, the following code can be interactively run in an Erlang shell to cause the shell to receive messages when any NIFs execute on a regular scheduler thread for 10ms or more:

1> erlang:system_monitor(self(), [{long_schedule, 10}]).
undefined

If any NIF executions meet or exceed the 10ms limit, the shell will receive messages similar to the following:

2> spawn(fun() -> bitwise:exor(LargeBinary, 16#5A) end).
<0.39.0>
3> flush().
Shell got {monitor,<0.39.0>,long_schedule,
                   [{timeout,6018},{in,undefined},{out,undefined}]}

Here, the {timeout, 6018} portion of the message shows that bitwise:exor/2 executed for slightly more than 6 seconds.

See the erlang:system_monitor/2 documentation for more details.

License

This example programs are open sourced under the MIT license. See the LICENCE file for more details.

About

Rust-based Erlang NIF examples for showing Erlang VM's scheduler issues

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published