Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> When Erlang does hot code loading, it loads it into the currently running process.

That is also usually true for PHP code using Fastcgi or mod_php or similar. It's not true for PHP code using PHP as a CGI, but nobody has done that since the 90's. It may depends on settings for opcode caching and the like.

> This means that any socket opened by that process stays open, and the connection is uninterrupted.

One of the earliest optimisations for PHP was the ability to make database connections persist across requests. See [1] for documentation of how to do this in current versions of PHP but it has been available pretty much from the start.

> When the process gets to the point of completing the recursive loop within which the old function was called, the new one gets switched in seamlessly and is called from there onwards. I know of no other language that has such mutable late binding, but I can't say they don't exist.

Plenty do.

This is valid Ruby that replaces the method "foo" for each iteration of the currently running loop:

    (1..10).each do |i|
    
      eval(<<END)
      def foo
        puts #{i}
      end
    END
    
      foo
    end
(the textual eval rather than simply inlining the method definition is necessary because "i" is a local variable not accessible from within the newly defined "foo" - if we used e.g. an instance variable instead it'd work, but then foo would effectively be static which would defeat the point of the demonstration)

Ruby's and PHP's ability to do hot reloads is similar, but it needs the running script to cooperate in the loading unless you use a containing process that embeds the interpreter and does hot loading that way.

But the PHP approach there is traditionally instead to throw away the code on each request.

> 1. The process pid is unchanged (it's literally the same process), and 2. The process data state is unchanged (it's literally the same process memory) and 3. The process file handles and sockets are unchanged

To me these are optimisations that are undesirable unless you need them. They're necessary for performance, but they make the system more vulnerable to working on corrupted data. As such I don't think it's a good distinction, but as mentioned depending on how you run PHP it can/will meet 1. and can meet 3. to some extent, and will meet 2. for session data, so it's up to you how much persists across requests.

[1] http://php.net/manual/en/features.persistent-connections.php



To reiterate, I am saying only that it is unfair to Erlang to portray PHP's (or Ruby's) operational characteristics as "like Erlang". It may be true in the loosest possible interpretation, but the details differ radically.

Your argument dismisses as optimizations things that are critical to systems for which Erlang was designed - telecoms. They are not optimizations for Erlang - they are necessary features that permit "write once, run forever" style operation.

Keeping a connection open and available in a database pool is admirable, but not even remotely comparable to keeping a TCP socket open between two participants in a phone call, with RTP voice data flowing, and changing a function - at run time - in that very same process, without disrupting the voice data.

The Erlang-style hot code loading doesn't make an Erlang system more vulnerable to working with corrupted data by not killing the process. That's just incorrect. In any case, well-written Erlang code will self-terminate if it detects anomalies. And it's harder to corrupt data in Erlang because of its immutability, absence of global data, and process isolation.

Compare the rather ugly and unsafe Ruby code with the equivalent Erlang code (provided as a separate module):

    -module(demo).
    -export([run/0, foo/1]).

    run() ->
        lists:foreach(fun(N) -> foo(N) end, lists:seq(1, 10)).

    foo(I) ->
        io:format("~p\n", [I]).
What the Ruby code does is in no stretch of the imagination "mutable late binding". It is evaluating (and hence interpreting) static text, which happens to redefine a Ruby function, every time through the loop. That's equivalent to recompiling a piece of code in a loop.

Where does this load new code?

You can eval code in practically any interpreter, from Perl to Python, and it's an unsafe and slow operation and not remotely the same as hot code loading in the Erlang sense.

The Erlang code is compiled, usually on another system, and the compiled BEAM code is copied to a live server, and loaded into memory into every running process that uses that module, simultaneously, without crashing or restarting any of the processes.

In fact, if there is a cluster of servers, and the replacement code (let's call the module "athana") is copied to the disks of all the servers in the cluster, it can be loaded into all processes running "athana" on all connected nodes of the cluster by entering this one line in the Erlang shell of any one of the production cluster nodes:

    > nl(athana).
That's it.

Please, let's stop this fruitless debate. It is obvious that we are not going to agree, and we are using the same phrases to mean completely different things.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: