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!
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.
@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.
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
@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.