Live data from Hacker News

Experimenting with Node.js

jeffkreeftmeijer.com

61–70 of 88 posts

Re: Experimenting with Node.js

#61
post #43

Earlier quoted context omitted.

"With coroutines you have to worry about IO all over the place and have to make your functions coroutine safe and Ryan Dahl," No, no, a thousand times no. Node.js partisans really need to start actually using Erlang or Haskell for a little while before spouting this canned line off. You do not have to jump through enormous hoops to deal with IO in Haskell or Erlang, it just works . Callbacks are behind the state of t…

It's really a question of how much state you're storing, and how you're dealing with that. Many languages and many runtimes allocate stacks in megabytes, and store every local variable in it. With a callback-based system, stacks are short, and you explicitly carry that state. You KNOW what state you're storing, and you can see it easily. There's some benefit to that. And the pattern for aggregating functions is diffe…

You need to try Erlang. (Or Haskell, but Erlang is more approachable.) You and every other Node.js partisan keep making criticisms that simply make it clear that you have no clue what you are criticizing and that doesn't make it terribly likely that you're going to sway me to your point of view.

"With a callback-based system, stacks are short, and you explicitly carry that state. You KNOW what state you're storing, and you can see it easily."

Actually, no. You have implicit state carried around in the function closures and you will discover that it is very easy to have a leak in there that will be very hard to diagnose. I say this because I am speaking from experience.

(Remember, Node.js isn't a blinding new architecture. The architecture has been around for over a decade and I don't even know when the idea started. The only new aspect is that this time, it's Javascript. I've got a lot of experience with that architecture, and what that experience tells me is never again!)

On the other hand, it is very easy to examine an entire running Erlang system, see every process and the exact contents of its stack at that point in time, and the exact amount of memory currently allocated to it, and since Erlang doesn't have any sharing between processes, that state is everything about that process. It isn't always the best about giving back memory if you have long running processes, but I was able to diagnose which processes were consuming my RAM, determine why they were consuming my RAM, and test out a fix for the excessive RAM consumption (since it came in the form of sending a particular message sooner rather than later), all without shutting down my server.

You do not have that level of introspection and visibility in Node.js. I don't even have to ask.

"Many languages and many runtimes allocate stacks in megabytes, and store every local variable in it."

I'm not talking about "many languages". I don't care about "many languages". I'm talking about good languages. Erlang can very easily allocate a couple hundred bytes to a process, or less. I'm not actually sure what the minimum allocation is, but it is certainly going to be competitive with a minimal Node.js handler.

"Receive a starting event, emit a done event -- you aggregate processes into sets of events, not into function calls. So yeah, it's not going to follow some of the same patterns that non-event-driven code follows, and event-driven code is going to look rather different than callback-passing code."

None of that appears to have any relationship to coding in Erlang, from what I can see. Better technologies don't have to have events. They just code right through things. A loop for a simple proxy might look like:

    proxy(SenderSocket, DestSocket) ->
        case socket_read(Sender) of
            done -> done; %% return to the original caller
            {ok, Data} ->
                socket_write(DestSocket, Data),
                %% go back for more
                proxy(SenderSocket, DestSocket);
            {error, Error} ->
                handle_error(Error)
        end
    end.
I don't need to "aggregate events"; I just tell the system what I want it to do, and it does it, and I don't sit here and specify how to wire functions together. In Erlang, the above will not block any other process. If you don't want it to block your current process, that's easy:

    spawn(fun () -> proxy(SomeSender, SomeDest))
Bam. Separate process and the current process can move on with life. No hooking up events. No code blathering on about how to interleave the events in that process with the events in this process. It's just happening. (There is standard library code to make things even more reliable, but going into the built-in supervisor stuff would take too much time. Also, it's hitting below the belt, no other language has anything quite like OTP.)

Erlang doesn't actually use coroutines, Haskell does only upon request, coroutines for concurrency are just cooperative multitasking and I mock them as well, albeit for different reason.

You need to try Erlang. If only to know how to argue against it without arguing against some fictional language that doesn't exist.

Re: Experimenting with Node.js

#62

I made this RPG node demo a while back: http://sleeperbot.com I'm not using any server monitoring so it can crash at any moment. Would love to get more than 15 users on here moving around and see what happens. code: http://github.com/weixiyen/avatar

I would highly recommend sanitizing chat input. As a quick demo, type 'alert("a")' or something.

Very cool concept though.

Re: Experimenting with Node.js

#63
post #62

I made this RPG node demo a while back: http://sleeperbot.com I'm not using any server monitoring so it can crash at any moment. Would love to get more than 15 users on here moving around and see what happens. code: http://github.com/weixiyen/avatar

I would highly recommend sanitizing chat input. As a quick demo, type ' alert("a") ' or something. Very cool concept though.

thanks, i put that in.

the blinky body toggle was pretty cool to see though :)

Re: Experimenting with Node.js

#64
post #28

While I think it's great that more and more developers are being exposed to building network applications using async I/O (which I guess is "evented" now) via Node.js, I think it's worthwhile to point out that the state of the art has moved well beyond these kind of callback frameworks. The reason is simple: it sucks programming in callback patterns on serious, large projects. You end up with lots of routines that ar…

Coroutines bring their own headaches and baggage. To say that callbacks are behind "state of the art" is a little misplaced,; its just a different way of doing things. With coroutines you have to worry about IO all over the place and have to make your functions coroutine safe and Ryan Dahl, the node.js creator, will argue with you all day long about coroutines vs callbacks. I do agree, though, that developers should…

Really? I recently wrote a framework to do networking with Lua. The network code itself is event based, but each TCP connection is handled by a Lua coroutine which makes it easy to write straightforward code such as:

  function main(socket)
   io.stdout:write("connection from " .. tostring(socket))
   while(true)
     local cmd = string.upper(socket:read())
     if cmd == "SHOW" then
       socket:write("show me some stuff\n")
     elseif cmd == "PING" then
       for i = 1 , 15 do
         socket:write(".")
         socket:sleep(1)
       end
       socket:write("\n")
     elseif cmd == "QUIT" then
       socket:write("Good bye\n");
       return
     elseif cmd == nil then
       return
     end
   end
  end
Makes writing simple servers nice and easy.

Re: Experimenting with Node.js

#65
Great stuff.

Just for sake of completeness, you can basically copy-paste that code into Ruby as well via em-websocket: http://github.com/igrigorik/em-websocket

Also, to avoid some of the callback muck that a few have brought up: http://github.com/igrigorik/em-synchrony

(same idea, closures + coroutines to abstract the callbacks).

Re: Experimenting with Node.js

#69

Web sockets are great, but almost all of the demos I see use a separate port (i.e. not port 80), making the app useless in practice. Come on guys - it's _Web_ sockets, not intranet sockets.

The problem here is that to bind the websocket to the port 80 they would need to code their whole sites in node.js (with no reverse proxying from nginx and the likes) or at least make a reverse proxy in node.js and use it as front-end.

Re: Experimenting with Node.js

#70
post #61

Earlier quoted context omitted.

It's really a question of how much state you're storing, and how you're dealing with that. Many languages and many runtimes allocate stacks in megabytes, and store every local variable in it. With a callback-based system, stacks are short, and you explicitly carry that state. You KNOW what state you're storing, and you can see it easily. There's some benefit to that. And the pattern for aggregating functions is diffe…

You need to try Erlang. (Or Haskell, but Erlang is more approachable.) You and every other Node.js partisan keep making criticisms that simply make it clear that you have no clue what you are criticizing and that doesn't make it terribly likely that you're going to sway me to your point of view. "With a callback-based system, stacks are short, and you explicitly carry that state. You KNOW what state you're storing, a…

Good points, thank you!

The problem is that they do not even understand that it is ridiculous to compare someone's hobby-project (actually a bunch of hacks - just read the source) and well-designed (all papers are available) battle-tested and widely used in telecoms (not in browsers) solution. ^_^

So, you're right - "It is Javascript". Same as for Clojure "It is JVM!"

Post reply on HN