10 ms·
how easy is it, even if you do need complex calculations, to get the best of the Erlang VM and call out to say, Python/Numpy or C when necessary? Can these exte
by vegabook 10y ago
how easy is it, even if you do need complex calculations, to get the best of the Erlang VM and call out to say, Python/Numpy or C when necessary? Can these external processes still be supervised, for example? Are decent sized matrices (for example 100x20000 floats so an 8MB data structure) easily movable around the Erlang VM via message passing?
IE is it viable in your opinion still to use Erlang as a system for distribution and routing of lots of heavy calculations to many users, if said calculations are performed outside of BEAM? I am looking at building a multivariate financial calculation engine, which must be interactive for up to 1000 users, with large firehose of real time data coming in, being massaged, and then distributed, with the calculation graph being customizable for each user interactively.
- sasa555 10y agoIt is possible to start external processes from BEAM and interact with them. I've blogged a bit about it at http://theerlangelist.com/article/outside_elixir http://theerlangelist.com/article/outside_elixir You can also write NIFs (native implemented functions) which run in BEAM process (see http://andrealeopardi.com/posts/using-c-from-elixir-with-nifs/ http://andrealeopardi.com/posts/using-c-from-elixir-with-nif...). The latter option should be the last resort though, because it can violate safety guarantees of BEAM, in particular fault-tolerance and fair scheduling. So using BEAM facing language as a "controller plane" while resorting to other languages in special cases is definitely a viable option.
- sashaafm 10y agoLove your blog and book Sasa. Could elaborate on the fair scheduling disruption by NIFs? Don't recall ever reading about that
- sasa555 10y agoThanks, nice to hear that! Basically a NIF blocks the scheduler, so if you run a tight loop for a long time, there will be no preemption. Therefore, invoking foo(), where a foo is a NIF which runs for say 10 seconds, means a single process will get 10 seconds of uninterrupted scheduler time, which is way more than other processes not calling that NIF. There are ways of addressing that (called dirty schedulers), but the thing is that you need to be aware of the issue in the first place. If due to some bug a NIF implementation ends up in an infinite loop, then the scheduler will be blocked forever, and the only way to fix it is to restart the whole system. That is btw. a property of all cooperative schedulers, so it can happen in Go as well. In contrast, if you're not using NIFs, I can't think of any Erlang/Elixir program that will block the scheduler forever, and assuming I'm right, that problem is completely off the table.
- kyrra 10y agoAs linked elsewhere here, tight loops that never preempt are being fixed in Go 1.8/1.9[0]. Looks like a flag may been added to Go 1.8 called "GOEXPERIMENT=preemptibleloops" that adds a preemptible point at the end of a loop. It's behind a flag for performance/testing reasons, but they are working on it. [0] https://github.com/golang/go/issues/10958 https://github.com/golang/go/issues/10958
- pmarreck 10y agoWon't pre-emptible loops lead to more irreproducible race conditions as a negative consequence, unless the preemption is done deterministically?
- Callmenorm 10y agoI spent 30 minutes looking at NIF, but I was scared away. My understanding is that if the NIF crashes then BEAM crashes. Which leads me to think that if you need NIF then you need safety guarantees on the Native side that C can't provide.
- sasa555 10y agoPrecisely, which is why I always advise to consider ports first :-) However, in some situations the overhead of communicating with a port might be too large, so then you have two options: 1. Move more code to another language which you run as a port. 2. Use a NIF It's hard to generalize, but I'd likely consider option 1 first. If you go for a NIF, you can try to keep its code as simple as possible which should reduce the chances of crashing. You can also consider extracting out the minimum BEAM part which uses the NIF into a separate BEAM node which runs on the same machine. That will reduce the failure surface if the NIF crashes. I've also seen people implementing NIFs in Rust for better safety, so that's another option to consider. So there are a lot of options, but as I said, NIF would usually be my last choice precisely for the reason you mention :-)
- lenkite 10y agoApparently people are working on this using Rust for writing NIFs https://github.com/hansihe/rustler https://github.com/hansihe/rustler
- derefr 10y ago
- andy_ppp 10y agoOr compile Elixir to native code with HiPE by adding: @compile [:native, {:hipe, [:verbose, :o3]}] to the top of the module with the arithmetic. It might not be as performant as C but it can be about 10-15X more performant than pure elixir (in my tests anyway). I've no idea of the relative performance against numpy...
- eoincathal 10y agoThere are libraries that allow C programs and Java programs to interact with Erlang as though they were Erlang processes. From the Erlang Interoperability guide: http://erlang.org/doc/tutorial/overview.html#id61008 http://erlang.org/doc/tutorial/overview.html#id61008 The team at Github took another approach, described here: https://github.com/blog/531-introducing-bert-and-bert-rpc https://github.com/blog/531-introducing-bert-and-bert-rpc It's an old article - so I no idea if it's still in use. The Github sources haven't been updated since 2010. I don't know how effective it is to chuck around 8MB data structures via message-passing. I have no experience of this myself.
- pmarreck 10y ago> I don't know how effective it is to chuck around 8MB data structures via message-passing. It's my understanding that above a certain size and within the same running Erlang VM (machine), a reference is passed instead of a full copy.
- di4na 10y agoonly for binaries. But if your matrix is mainly modified outside of erlang, it may make sense to only use it as an opaque binary inside.
- mr_luc 10y agoYou can write NIFs in Rust (which is made even simpler by supporting libraries like Rustler). scrogson, for instance, is using this to fiddle with lower-overhead json. Re: supervising external processes, an easy hack if you're writing the processes is to add a deadman's switch to both sides, and then launch the processes from a port in BEAM-land. This effectively makes them supervised; kill the beam process and the external process will die, and whether they both get relaunched depends on the restart strategy the supervisor launched the child with.
- deleted 10y ago[deleted]
- arthurcolle 10y agoVery easy - many solutions to do just this. Porcelain is one such library for Elixir that lets you call C executables, interact with CLIs. I have a lib called pricing on my github that uses the lib to price options using a simple C executable.
- julienmarie 10y agoAnother solution is to make your non-erlang process run as a foreign erlang node ( example of a Go library to implement this : https://github.com/goerlang/node https://github.com/goerlang/node ). There are some other messaging libraries for python and ruby that do exist for this.
- rdtsc 10y agoIt's doable. Erlang is used to talk to the hardware and C code. Can build a C functions (NIF), an driver (for IO for example), spawn a process, or implement the logic of Erlang distribution protocol (what is used to talk between VMs) in C. With 20.0 coming up it will be even easier. A nifty feature called "dirty schedulers" will become stable and so building long-running calculation in C will be much easier. Previously had to take care not to block the running scheduler thread. All-in-all Erlang is really good at connecting to and managing things, C and hardware being one of those things.
- di4na 10y agoYou may want to have a look at talks like this one https://www.youtube.com/watch?v=xj3smNjGLaE https://www.youtube.com/watch?v=xj3smNjGLaE It is a common pattern to use erlang has a controller plane.
- vegabook 10y agoThis has been a very informative sub-thread. Many thanks to all contributors for your thoughts and experience. You have helped to move me forward in confidence on using Erlang/Elixir(basically BEAM) for the distribution and routing side of my enterprise-scale soft realtime data-interpretation project. A great testament to the quality of contributors on HN. I will post at a later stage on progress.