Live data from Hacker News

The Erlang Shell

medium.com

21–30 of 62 posts

Re: The Erlang Shell

#21
post #20

I'm another recent Erlang convert (though I'm still trying to get used to the paradigm and ecosystem). There are a few concepts that haven't quite clicked for me. I come from a Rails background. While Erlang's hot code reloading and the ability to attach to running nodes is cool, I am not quite able to connect the dots on how this is useful. In Rails, a process is short-lived by design (the lifecycle of a request). A…

When you are running in production and something is not right, you can attach to the console and see what is going on. This is of course not something that you should do often, but can be a real life saver. Simulating something that is designed to work with thousands or even millions of users at the same time is pretty much impossible. Hot code loading and attaching to console gives you the option to see what is goin…

I get that. For persistent connections, it's a life saver. But for a synchronous web service, every connection comes and goes quickly. What do you gain from attaching to the console in that situation that you wouldn't get from the rails console?

Re: The Erlang Shell

#22
post #20

I'm another recent Erlang convert (though I'm still trying to get used to the paradigm and ecosystem). There are a few concepts that haven't quite clicked for me. I come from a Rails background. While Erlang's hot code reloading and the ability to attach to running nodes is cool, I am not quite able to connect the dots on how this is useful. In Rails, a process is short-lived by design (the lifecycle of a request). A…

When you are running in production and something is not right, you can attach to the console and see what is going on. This is of course not something that you should do often, but can be a real life saver. Simulating something that is designed to work with thousands or even millions of users at the same time is pretty much impossible. Hot code loading and attaching to console gives you the option to see what is goin…

Why should you not do it often?

Re: The Erlang Shell

#23

I'm another recent Erlang convert (though I'm still trying to get used to the paradigm and ecosystem). There are a few concepts that haven't quite clicked for me. I come from a Rails background. While Erlang's hot code reloading and the ability to attach to running nodes is cool, I am not quite able to connect the dots on how this is useful. In Rails, a process is short-lived by design (the lifecycle of a request). A…

curious, which type of projects do you plan to develop in Erlang? especially after rails.

That's the question I can't answer. I have some problems I want to solve. If I build them in Erlang the way I would on Rails, then there's not much gain. I'm trying to figure out how Erlang will allow me to solve those problems differently. One problem is how to handle authentication across our private and public APIs. With Rails, I've got a db with credentials and tons of memcached running to minimize latency (since every endpoint needs to check auth). How would a long running application in Erlang handle that differently? How is that better than what we currently have?

Re: The Erlang Shell

#24
> And all this without service interruption. And you get all this for free, just because you picked Erlang as the implementation language.

GDB or even VS's debugger can do a lot of magic even if you use C. Until absolutely necessary, leave debugging information reasonably high and optimization reasonably low or off and you'll get an amazing, dynamic environment to inspect a live C system.

Re: The Erlang Shell

#25
post #20

Earlier quoted context omitted.

When you are running in production and something is not right, you can attach to the console and see what is going on. This is of course not something that you should do often, but can be a real life saver. Simulating something that is designed to work with thousands or even millions of users at the same time is pretty much impossible. Hot code loading and attaching to console gives you the option to see what is goin…

I get that. For persistent connections, it's a life saver. But for a synchronous web service, every connection comes and goes quickly. What do you gain from attaching to the console in that situation that you wouldn't get from the rails console?

If you only have a socket dispatcher and a quick request processor that servers a page and dies, then that code path is quite minimal.

Now you should probably have a supervisor. Your connections could be handled by a connection or socket pool. You could have a database driver. There could be a background processing queue. Now things get interesting, not all those things get torn down and recreated on each request.

Even for short lived requests you could attached to a live system and trace one of the short lived requests or set a debug point to see what it does in "slow motion" to so speak.

One can use Erlang for quite a bit without touching the distribution (as in distributed nodes across many systems forming a single cluster). Then the shell can help you log in to any other node, transparently.

The ability to reload code at runtime is not something many systems can boast. Because that is one case you might touch once you have found the problem, but that is again one thing you can do.

You can diagnose loading and system resource utilization as well. If you have a fully-featured system (say downloaded from Erlang solutions) open the shell and type observer:start(). to start the observers. It will launch a GUI window (make sure to have X forwarding if running via SSH). There you can see runtime stats, the application tree, process list, ETS tables. For each application in the tree you can click on the process and see its state.

Re: The Erlang Shell

#26
post #11

> When systems have faults due to concurrency and distribution, debuggers will not work. Those are very tricky indeed, mix in threads with pointers and a system becomes haunted. "This one customer noticed a crash, on this hardware, after running for 10 weeks, but ... we couldn't reproduce it". "Oh I suspect there is a memory overwrite or use after free that corrupted the data". People start doubting their sanity -- "…

Nitpick: mixing threads with pointers isn't really the problem; it's mixing threads with shared mutable state.

A concurrency idiom I've gotten a lot of mileage out of is to use threads, without shared state, but with pointers. Instead of shared state, you use a message passing style where you pass pointers over queues. Threads only mutate data that they are explicitly handed via a queue. After putting an object on a queue, they NULL out their local reference.

It's basically like Go's goroutine idiom, but with C/C++/Python, real OS threads, and a thread safe queue (which is all a channel is). There is also some relation to the SEDA architecture.

The logical structure of such a program is not really that different than an Erlang program, I imagine. It just works a little better with existing C/C++ codebases, and is potentially faster in some cases.

It has a completely different character than spaghetti written using threads and shared state, and can be made extremely reliable. Especially because the explicit channels provide a hook for testing black box behavior.

Re: The Erlang Shell

#27
post #26
post #11

> When systems have faults due to concurrency and distribution, debuggers will not work. Those are very tricky indeed, mix in threads with pointers and a system becomes haunted. "This one customer noticed a crash, on this hardware, after running for 10 weeks, but ... we couldn't reproduce it". "Oh I suspect there is a memory overwrite or use after free that corrupted the data". People start doubting their sanity -- "…

Nitpick: mixing threads with pointers isn't really the problem; it's mixing threads with shared mutable state. A concurrency idiom I've gotten a lot of mileage out of is to use threads, without shared state, but with pointers. Instead of shared state, you use a message passing style where you pass pointers over queues. Threads only mutate data that they are explicitly handed via a queue. After putting an object on a…

That is true. One can build an almost shared nothing architecture in any of the languages supporting thread safe queues and threads.

It is a continuum. One could write it with shared mutable state too, using locks. The problem is it is easy to mess up.

C, a large program could load modules, and some of them are thread safe some are not. One could bring in a new module that calls some initialization routine (say curl_global_init()) and then another part of the system ends up calling it as well. But it is not thread safe and should only be called once. It is not intentional sharing, but it just happens as it is running in the same memory space.

Someone likened that to running your code in Windows 3.1 when you Command & Conquer game would crash and take down the word processor with it. They didn't intend on doing so but it happened by accident as a bug. Sometimes running your application as a Windows 3.1 system is acceptable, sometimes it isn't. It depends on the problem.

Re: The Erlang Shell

#28

Earlier quoted context omitted.

Is it actually possible to do hot code reloading while preserving the state of the running system in Common Lisp? I'm genuinely curious, I kind of had this impression that it was a feature fairly unique to Erlang.

> Is it actually possible to do hot code reloading while preserving the state of the running system in Common Lisp? Yes. > I'm genuinely curious, I kind of had this impression that it was a feature fairly unique to Erlang. It's not. iIRC there's even a version of the JVM with code reloading. What's interesting about Common Lisp is that not only can code be dynamically compiled into the running image but class definit…

I use Common Lisp and Scheme at work, and have written and maintained several systems heavily relied on class redefinition and run-time code loading. They're great. OTOH, I feel Common Lisp's concurrent process handling is rather weak, and I envy Erlang for that (Not that CL can't do the trick, but usually what implementations offer is fairly low-level and I had to roll my own higher-level IPC.)

For example, how well CL's class redefintion and instance reinitialization work with preemptive threads? It isn't obvious how each implementation address this issue by skimming docs, so I'm curious if anybody with direct experience. When I implemented CLOS/MOP style OO in my Scheme, I ended up using a global lock during class redefinition, for it need to modify lots of places. It's MT-safe now, but I'm still wary to run class redefinition on a system written in my Scheme, which is busy handling requests.

Re: The Erlang Shell

#29
post #25

Earlier quoted context omitted.

I get that. For persistent connections, it's a life saver. But for a synchronous web service, every connection comes and goes quickly. What do you gain from attaching to the console in that situation that you wouldn't get from the rails console?

If you only have a socket dispatcher and a quick request processor that servers a page and dies, then that code path is quite minimal. Now you should probably have a supervisor. Your connections could be handled by a connection or socket pool. You could have a database driver. There could be a background processing queue. Now things get interesting, not all those things get torn down and recreated on each request. Ev…

Thanks! That makes sense. I see it now. For the benefit of other Rails devs looking in: think about debugging issues with unicorn or passenger on a live system without interrupting service. Then think about being able to fix the code without interrupting service. That's powerful. That's not something I do every day, but I can understand why that's powerful.

Re: The Erlang Shell

#30

Earlier quoted context omitted.

> there's even a version of the JVM with code reloading. Yes, because of Java's extensible classloading mechanism, all you have to do is drop an war/ear to the 'deploy' folder of your application server. New files are deployed, rewritten files are redeployed and deleted files are undeployed.

Is there a mechanism to migrate existing data to the new code?

If you have external state stored in say a database, I think you have to control your deployments to migrate the schema before the model objects can be deployed.
Post reply on HN