NIF vs Existing System Binary

There is an understanding gap between between Erlang NIF and System Executables (binaries).

  • I understand NIF makes certain programs in erlang/elixir take advantage of the native performance. Also, I’m very well aware of the downsides of writing a NIF.
  • I’m seeing many people using System.cmd/2 for using external binary in most of the cases and I’ve no objection with that.

For example, take WKHTMLTOPDF,

Most of us, use the readymade binary and we’re good with it. Why are we not preferring to use a NIF for it? Is there any specific reason behind it or due to unavailablility of a NIF library?

Is there any advantage to writing a NIF for it? So what’s the reason behind your answers! Please enlighten us!

1 Like

A NIF:

  • Is faster to communicate with, can use native datatypes AFAIK (probably needs some custom work though)
  • Needs to be separately written if the program doesn’t already have one
  • If it crashes, it takes down the BEAM
  • If it stalls, it can adversely affect the BEAM (traditionally NIFs needed to complete in 1ms, nowadays we have dirty schedulers but AFAIK they are not a silver bullet)

A port (external process):

  • Slower to communicate with, as communication needs to go through a pipe or other external method and messages need to be serialized for it
  • If the program crashes, BEAM is not affected
  • If the program stalls, BEAM is not affected
  • No need to implement NIF API and make sure it behaves like a NIF should

In most cases a port is fast enough (like in the case of wkhtmltopdf, I would suspect most of the time is taken in building the PDF, not in communicating), and implementing a NIF is just extra hassle, extra fragility, and may not be worth the effort.

4 Likes

@Nicd That’s sounds great! I do see many other programming languages created native bindings for the example library and use the same in context. I’m curious to understand the choices for these kind of variations.

Rust, Python and PHP has native bindings for WKHTMLTOPDF. I’m aware they are all OOPS based. Just curious, though, I agree with you in regards to the efforts involved in writing a NIF for such libraries.

In case you were actually planning to use wkthmltopdf I would just like to point out the new kid on the block which is orders of magnitude better: GitHub - bitcrowd/chromic_pdf: Convenient HTML to PDF/A rendering library for Elixir based on Chrome & Ghostscript

5 Likes

There are also other important factors (other than what @Nicd have already pointed out):

  • licenses - if you use external program in replaceable way then you can avoid viral licenses like GPL or AGPL in some cases
  • permission system - you can run external program with SETUID flag or other form of raised privileges, while NIF will work with the same privileges as the VM, which is often not what we want
  • resource limits - you can run external program with limited resources like CPU or RAM, you can even do so in limited view on the system via cgroups and namespaces, so it will be basically sandboxed
  • you need to have access to code of the program/library to use it as NIF, it is not always the case when using proprietary executables
5 Likes

@olivermt It adds the headless chrome as a dependency, which kind of makes it heavy. All I’m trying is to see if there are right alternatives using elixir or erlang itself or why should one go for NIF or any other particular solution without having a lot of external dependencies.

@hauleth thanks for the resourceful points. Just curios, are you supporting to go for a NIF or not? wkhtmltopdf is just an example, to brief, it’s written in C++ with qt support and it exposes a c-binding for integration with other softwares.

Depends on the needs and the expected constraints. With wkhtmltopdf I would probably go with the port, because spawning whole WebKit/Blink within Erlang VM is at least poor design choice.

1 Like

That explains the choices, one has to keep in mind!