<div dir="ltr">I did an experiment a couple of years ago:<div><br></div><div>1. Run an OCaml program behind a port from Erlang</div><div>2. *Pipeline* requests to the port. That is, don't wait for the roundtrip of each message, just shove as many requests you can to the port and have it handle them. The OCaml program just reflects whatever it got back (an integer counter).</div><div>3. Use one CPU core for Erlang, once for OCaml.</div><div><br></div><div>This ran about 1 million req/s on a typical modern laptop. That is, the amortized message overhead is about 1us. It suggests that the NIF usecase is that you have many small calls which are latency bound (my above test is a throughput one due to the amortization). If you have large datastructures there may also be a reason for a NIF in some cases.</div><div><br></div><div>Measurement is key. I think there are many cases where you don't really need a NIF and a port would do fine.<br><br><div class="gmail_quote"><div dir="ltr">On Fri, Aug 18, 2017 at 11:13 AM Joe Armstrong <<a href="mailto:erlang@gmail.com">erlang@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Re NIF's safety etc. Here's my take<br>
<br>
NIFs should be used for one reason only - performance.<br>
<br>
If performance is not a problem you should use an external port<br>
program, or an external c-node.<br>
<br>
Also the NIF should be called many times per second, not just once now<br>
and then - if the NIF is called infrequently then you should use and<br>
external port program.<br>
<br>
The only reason for using a NIF is to eliminate the round-trip times<br>
for talking to an external process, and speeding time to convert the<br>
internal data structures used by the programs since the NIFs have<br>
direct access to the stacks and heaps of the Erlang processes<br>
involved.<br>
<br>
Using a NIF is breaking the guarantee - if you open the package and mess<br>
around with the bits inside then don't blame me if you break something<br>
...<br>
<br>
If you can solve your problem in pure Erlang, then do so and don't use<br>
a NIF.<br>
<br>
There are a large number of reasons not to use NIFs<br>
<br>
  - Your code might break the system in ways you don't understand<br>
  - Your code will be single-platform and non-portable<br>
  - Your code will not be 'future proof'<br>
  - Understanding your code will require knowledge of Erlang +<br>
    <another language> + a build procedure<br>
<br>
I have always believed that large systems should be made from small<br>
communicating components communicating via well-defined protocols -<br>
linking things together in memory makes the individual components<br>
larger and more unmanageable - we should be trying to do exactly the<br>
opposite, making things smaller and isolating them.<br>
<br>
The other problem with NIFs is that they make alternative<br>
implementations pf Erlang far more difficult. An Erlang implementation<br>
has four main components:<br>
<br>
   1) A compiler from Erlang to beam code<br>
   2) A beam instruction emulator<br>
   3) A load of BIFs (or NIF's if you like)<br>
   4) Huge libraries written in Erlang<br>
<br>
Each of these represent massive effort.<br>
<br>
Porting Erlang to (say) the JVM or .NET virtual machine would be<br>
relatively easy were it not for 3). Changing the compiler to a new<br>
instruction set and changing 1) and 2) is not that difficult but any<br>
changes the calling sequences would really mess up all the code for<br>
the BIFs and NIFs.<br>
<br>
Never forget that NIFs are an optimization and nothing else<br>
(since the same effect can be achieved in an external process) -<br>
<br>
"Premature Optimization is the root of all evil"<br>
<br>
[The best form of optimization is patience - in 20 years Erlang has become<br>
 at least million times faster - of this probably a factor 10 comes from<br>
 smarter compilation - and 100,000 from faster clock speeds and better hardware.<br>
 (These are just guess but in 20 years Clock speeds  have gone from Mhz to GHz<br>
  and memories increased from MBytes to GBytes)<br>
<br>
 Pure Erlang code written 30 years ago ofter runs fine and is way faster<br>
 than it was but the BIFs of 30 years ago are long dead and will not<br>
 even compile.<br>
<br>
  Patience is a virue]<br>
<br>
Cheers<br>
<br>
/Joe<br>
<br>
<br>
<br>
On Wed, Aug 16, 2017 at 3:53 PM, code wiget <<a href="mailto:codewiget95@gmail.com" target="_blank">codewiget95@gmail.com</a>> wrote:<br>
> Hello,<br>
><br>
> I have been reading about NIF’s here:<br>
> <a href="http://erlang.org/doc/tutorial/nif.html" rel="noreferrer" target="_blank">http://erlang.org/doc/tutorial/nif.html</a> but it seems like they are<br>
> incredibly unsafe: “it is also the least safe, because a crash in a NIF<br>
> brings the emulator down too”. The problem here is huge, ideally I can’t<br>
> ever have my Erlang VM close.<br>
><br>
> What solution do you Erlangers use when you have to run low level code? My<br>
> goal is to send a sort of “GET” request with a UUID and I will receive back<br>
> that UUID along with some binary values. My C code works with this, but I<br>
> can’t jeopardize the entire server crashing.<br>
><br>
> Thank you for your help!<br>
><br>
> _______________________________________________<br>
> erlang-questions mailing list<br>
> <a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
> <a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
><br>
_______________________________________________<br>
erlang-questions mailing list<br>
<a href="mailto:erlang-questions@erlang.org" target="_blank">erlang-questions@erlang.org</a><br>
<a href="http://erlang.org/mailman/listinfo/erlang-questions" rel="noreferrer" target="_blank">http://erlang.org/mailman/listinfo/erlang-questions</a><br>
</blockquote></div></div></div>