To boldly go where Node man has gone before
blog.jgc.org
blog.jgc.org
You'll drive yourself into the looney bin if you hop from one thing to the next based on these comparisons that inevitably popup every month or so.
If you enjoy programming in JS with Node use it - if you enjoy programming with Go use it. Your enjoyment will far outweigh performance differences that will be minor in 99% of real world cases.
Go is really promising but it won't win over the majority of casual developers until there's a community around it. I might as well write a webserver in C if I'm only concerned with performance
Really? In my experience, all but the most mature modules are hardly beta-quality and in constant flux. Find a good module for your job? Too bad it only runs on 0.4. Find another to get around that; oops, too bad your version of gcc needs to be patched and re-built. The language and its entire package ecosystem is so immature, I'm blown away people trust it in production at all.
"So fix it and submit a Pull Request," you say? That doesn't help me when I'm trying to deliver on a deadline. I love contributing, but I often have more pressing things on my plate.
Node.JS has a great community that is writing many great modules, no doubt. But the community is very young and almost by definition many of the modules are immature.
This can be very enjoyable from an engineering perspective (you get to write and hack on things that you would not otherwise), but can also slow down the process of building things since you do end up having to reinvent the wheel at times.
With your response in mind - I don't see Node being mature enough (yet) to solely support an end-to-end large scale Web property. But, for serving up API content from Memcache/MySQL - it is blazing fast with minimal footprint. On our stack - we run Node right on our existing Apache Web servers (behind haproxy).
For a taste of what's out there, see: http://go.pkgdoc.org/index.
I couldn't find any way to specify a specific tag or revision, so it's basically always getting the bleeding edge developer build of the library code. That might be nice in some situations, but for getting work done I almost always want the most recent stable release.
Am I missing something?
It's a convenient hack but nothing more.
[noir "1.2.0"]
ensures I'm always grabbing the same version. In Go, appears the only way to guarantee this is to check in the full source of the library alongside your own in your repo. {deps, [
{quoted, "1.0.3",
{git, "git://git.corp.smarkets.com/quoted.erl.git", {tag, "1.0.3"}}},
{proper, ".*",
{git, "git://git.corp.smarkets.com/proper.git", {branch, "master"}}}
]}.I've seen this plugin before but its not particularly useful without dependency checking. It's a start though. I'll have to look at leiningen to see if it exposes hooks for that sort of thing.
$ sudo apt-get install golang
$ go get github.com/pauek/garzon/grz
That's it, and it takes a few seconds.If Go adds some method to specify a tagged version that could be pretty nice though.
I hope it goes without saying that there's no way this kind of hack (neat as it is) is a substitute for a proper package management system like npm (which is a very good package manager).
npm install git://github.com/substack/node-optimist.git npm install express
Not only do npm handle versioning for you, you also don't have to remember the host or username. Obviously Go is a younger community, and could make a package manager some day, but I'm puzzled by how you're comparing this positively with npm.And I'm not saying this feature of Go is better than npm, I also use npm and I like it very much. What I like is the fact that Go comes already with this feature and I don't need anything extra.
But when installing packages, I have to say, npm is fantastic.
Furthermore npm can install git URLs directly too, including tags and branches if you need a particular one. Just specify the url as the "version" in your dependencies section of package.json. Totally trivial.
Edit: haha I love how people downvote this like i'm being sarcastic. Down with Perl, that horrible language with a community and modules 100x larger than Node!
So you want an environment that is easy to program in a functional style with closures and first class functions. Has a large ecosystem, including hundreds (thousands?) of packages to do asynchronous IO. Is easily extensible and can fall back on code written in C. Finally, has a large and active community ( Madison NAPC is sold out )?
And Perl isn't even on your radar?
https://github.com/semmypurewal/node-talk-examples/
and translated them to Perl.
https://github.com/sciurus/anyevent-plack-examples
If you're interested in functional programming, I've learned a lot from the parts I've read of Higher-Order Perl.
I'm a fan of C and Python myself, but I always chuckle at all the Perl hate.
Another draw of Go that you didn't mention is the language and toolchain design itself. I know Javascript better than Go, but would rather write servers in Go than JS.
If you think Node has a huge community and wealth of awesome modules wait til you to discover the older and more mature languages/platforms, like Python, C, Java, etc.
"What I like about Justin Bieber is the massive history of his career, spanning decades, and the broad range of his musical style across several genres." :)
Programming language is just a tool - one from many tools you can choose to make your projects and node.js have done some basic things better than Python (e.g. packaging). I have learned to love JavaScript and it is really good language now. Still there are projects I wouldn't choose node.js as my tool.
That's an enormous advantage for startups as (a) the JavaScript hiring pool is much larger than most other languages (particularly in comparison to nascent ones, like Go), and (b) the ability to write client- and server-side code in the same language means small teams can be far more integrated and collaborative than otherwise (and if the startup has a single coder, the point is even stronger).
Assuming these benchmarks are accurate and translate into similar results for more complex applications, I'd gladly pay the 10-20% performance penalty to get the above benefits. Node is fast enough for most startups.
There is a big difference between a jQuery hack and a good JavaScript developer.
But for Node - I've really come to the conclusion that it is a great tool for back end API work, such as serving very short requests, Ajax calls, etc. Couple the ability to develop in Javascript while serving JSON makes Node a really nice place to develop in.
Plus, performance is off the charts for my API serving applications. On a dev instance I can serve close to 5500 reqs/sec for one of our APIs where PHP was at about 1000 req/sec. And the difference in memory usage is fantastic.
BTW, our production Node deployment is Node, with the memcache, mysql, mysql-pool, cluster, and express modules. I've been thrilled so far.
The language of the web is javascript. Until web browsers allow Go as the embeddable language, node will remain useful. I seriously doubt people would pick Go over node because of a micro-benchmark.
Do people really get that much code re-use between client and server that using Javascript on the server provides a large benefit?
For complex ones yes. The actual code shared may not be that much, but consider the advantages in sharing validation code between the client and server -- you never accidentally forget one requirement on the server side, leaving you vulnerable to an attack.
Is there a mature implementation of this yet?
One that is not tied to an entire immature framework (meteor) or programming pattern (nowjs)?
Code-reuse was the big promise of node. Yet in reality I've never seen it executed beyond brittle experiments.
Where is the form_for_model() function that emits code for both the client and the server?
In other languages, even if you write completely logicless views in a templating language that can compile in the browser like Mustache, you'll end up duplicating your presenter code if you don't use a language that browsers can understand.
Nonsense. It's far from trivial to have the same code get binding and validation right on both sides. That's why it needs to be wrapped in a thin abstraction, which apparently nobody in the node-community has been capable of writing.
Instead we see dozens of rails-clones (oh, exciting..), and a handful of very half-baked full-stack universes that are nowhere near production ready.
Update your model? Don't forget to update your validation in both the client and server. Otherwise, you'll validate something on the client but not the server (bad UX), invalidate something on the client but not the server (bad UX), or corrupt your data slowly when validation entirely fails (bad UX).
Since it's a pain in the ass to remember to update two places when you make a change, you're seeing people make ridiculous leaps of programming ingenuity by choosing a server-side language that allows them to not have to update two places at once, and Javascript absolutely sucks for server programming. Every time I have to do any client-side Javascript I, quite literally, hate my life. People that love Javascript and want to apply it to everything have arguments about the stupidest things, like using semicolons, which is telling about how awful of a programming environment it can be.
Easier: Just don't validate on the client, and make a round trip. If you're doing mobile or on a high-latency link, there's an argument for doing client-side validation but then you just need the discipline to update both sides at once, which hopefully integration tests should help with.
Just not my experience that this is the case. Though I might be old-fashioned.
I've recently been working with a team that is developing a content management system for which the display side of things (responsible for routing requests to models and views, fetching model content, rendering, etc.) is about 500 lines of non-comment CoffeeScript code.
Nearly 100% of the server-side code is re-used on the client, and perhaps 80% of the (non-library) client-side code is shared with the server.
In this case the exceptions are:
- Things like HTTP-level request handling and reading from local files rather than over HTTP are used on the server-side only.
- Things like DOM-manipulation and interacting with browser events are used on the client-side only.
I wonder if a significant factor may be how much functionality you're actually replicating on both the client and server. In our case, browser-permitting, the entire display engine runs equally well on the client or on the server. If we had a lot of JQuery kind of stuff happening in the client-side JavaScript the ratios might be a little different, but "also-run-the-app-on-the-client" is a good example of a use case that leads to a lot of reuse of the server side code.
A crud app would properly share relatively little code between the server and the client. A multiplayer game would share much, much more.
as for sharing: data sources, domain models, utilities and templates can be shared. its the io handling (HTTP and dom) that can not be shared.
Rolling your own framework based on the same ideas is not hard.
I don't think there are many people who choose js because they like it. It's usually because they feel forced. Javascript is a terrible language, I always prefer one of the compilers.
Dart can't come fast enough.
Is there a separate branch/fork of GWT with Go support? That would be absolutely awesome in fact but it doesn't seem to be true.
This makes me wonder.. and this is totally off the cuff, non-researched pondering.. could there be merit to a JavaScript dialect that would compile to Go?
One thing the author didn't mention is that Go will use multiple cores in this example, whereas Node is single-threaded. Right?
Basically if you say this:
fn()
The Go runtime will execute the function in its entirety and wait for a return value.If you say this:
go fn()
The Go runtime will execute that function in a new goroutine (the return value is discarded) and then immediately proceed to the next line in the current goroutine.So if you have some callDB() function that performs some long-running i/o, in node, you might do something like this to perform that operation without blocking the surrounding code:
...
callDB(someparam, otherparam, function (result) {
// do something with result here
})
...
while in Go, you would do something more like this: ...
go func() {
result := callDB(someparam, otherparam)
// do something with result here
}()
...
which winds up being more like this func superGreat() {
result := callDB(someparam, otherparam)
// do something with result here
}
go superGreat()
With the benefit being that if you want superGreat to run concurrently, you use the go keyword, and if you want it to be run in a synchronous style, you just call it normally.The problem with Ruby/Python/etc is that it is awkward to take something that is blocking and make it nonblocking. The problem with node.js is that node.js says "blocking is bad; therefore, never block". Go takes a different approach, in that it makes it obvious to know how to write something so that it does or does not block, so that the developer is free to use whatever I/O paradigm fits the problem at hand.
The net/http package allows you to register a handler, which is a function that takes and http request and writes a response. There is a main request loop that, when receiving a request, will create a new goroutine for each request and execute its handler in its own context. So within your handlers, you mostly just write blocking code, because you're already in your own isolated goroutine, and the only thing you'd be blocking is the processing of the current request. If you want to do something in the background, you run it in a new goroutine. goroutines are very cheap, so you can be quite cavalier about their usage.
If you want to use a callback-passing style, you can do that in Go (because it has function literals and closures and first-class functions and all that), but that's not idiomatic by a longshot.
The absolutist position that node.js takes by saying that "all i/o must be nonblocking" is no better than our previous options of "all i/o is blocking". Sometimes the simplest and most readable solution is simply to block. There is a yin to the yang of blocking.
In any case:
Node lets you reuse the same code on both the client and server. This can be very valuable if you're writing a JS-heavy webapp. In my experience, the most useful bits of code are the in-code data representation (models in an MVC world). Being able to have identical functionality client- and server-side can save a lot of time.
Node also has Socket.IO, which is very useful if you want to use websockets. (Go has a library for it, but it hasn't been updated in a long time.) The vast majority of the Node ecosystem revolves mostly around building interaction- and communication-heavy webapps. I don't know Go or its community at all, but I don't believe they have the same kind of single-minded focus that Node has. If you're trying to do the things Node does well, you will likely benefit from the community support.
There are, of course, many downsides to Node as well, but much as I dislike Javascript, I still think it's one of the best choices for writing highly interactive webapps right now.
I wouldn't use node if it wasn't for this because I don't particularly like javascript.
All my other games have used Python on the back end and you can really feel how clunky and painful javascript is when you have to switch between the two five times a day.
I'd love to see a second set of benchmarks of the same code on multiple cores.
Well, for starters, Go is much more awkward for working with JSON than JS is (which is to be expected since JSON is literally a subset of JavaScript). More importantly, Go lacks the ridiculously vibrant ecosystem for Web development that Node has — no NPM, no Connect, no Jade, no Stylus, etc.
What I've done sometimes is just clone the repo within a directory that appears in the GOPATH, maybe checkout a specific revision, and that solves the problem.
type UploadProgress struct {
Progress int `json:"progress"`
}
//...
// variable progress is of type Progress
if json_data, err := json.Marshal(progress); err == nil {
w.Header().Set("Content-Type", "application/json")
w.Write(json_data)
}
json.Unmarshal works the same way. IMHO, not exactly more awkward than using JSON.parse and JSON.stringify.In retrospect, I think I may have overstated it a little bit, and I doubt this problem would crop up too often for most apps.
Deleted comment
http://stackoverflow.com/questions/9452897/how-to-decode-jso...
the label on the field lets you denote when that will happen, so... it's not quite as difficult as it may seem; you don't have to write a single method for that case.
The type system is a feature, not an obstacle. Yes, you have to specify a type, but as a result, the compiler can perform a lot of checks that, in dynamically typed languages, would either be something you'd handle manually, something that would cause undefined behavior, or something that you would write a unit test to test for. Yes, you could just wing it, unmarshal some data, have an unsafe reference to some field and hope that it performs the way you want it to, but the reality is that things like that are easy in JavaScript because they're wrong. All data inherently has some kind of type, and different languages deal with that in different ways.
but yes, that particular type of thing does come up a lot, and the topic of handling bad json is one that has woefully too litter literature surrounding it (I've had it stump me before on my own projects). Things like "they're using the wrong format for the timestamp" or "that is sometimes string, sometimes null" are stumbling blocks when coming from dynamically typed languages (I'm coming from Python/JavaScript), but in my experience writing Go, the way the language works makes writing bad code much more difficult, and my Go programs have been much more stable, easy to refactor, and easy to maintain forward progress on over a long period of time. After using it for some time, I've come to the conclusion that these types of tradeoffs have been worthwhile. The significant reduction in runtime errors that I've seen in my Go applications compared to my Python applications have more than outweighed the amount of time I would normally spend debugging and testing my Python code, which is tedious and boring.
It's for an older version of Go, and has only been tested on Plan 9, but it shows a static content + blog server, with JSON config files and templated HTML for the blog pages.
I am surprised that Node performed so well.. I would like to see that same Go benchmark with 4 CPUs vs. Node and also vs. Node with a clustered web server and the code to see how much more code that involves for clustering with Node.
Also I would like to see some Go code and benchmark that reads a file and/or database in the request and works efficiently.
Actually the code for a Node cluster that would use all of the available CPUs for http in CoffeeScript would look like this:
cluster = require 'cluster'
http = require 'http'
numCPUs = require('os').cpus().length
if cluster.isMaster
cluster.fork() for i in [1..numCPUs]
else
app = http.createServer()
app.on 'request', (req, res) ->
res.end "hello world\n"
app.listen 8000
Maybe someone could take V8, change it so it compiles (immediately) to static code and uses CoffeeScript, and add a way to optionally specify types (in an unambiguous and readable way) and pointers only when you have to.However Go's memory usage increases by about 5X.
So what happens when you reach 1000 simultaneous requests? Which will perform better then?
I think this is called "selection bias."
Not to knock Go -- it's a beautiful language, and absolutely faster than Javascript for most purposes (and will no doubt increase in stability and speed as time goes on). But this post had some pretty flawed analysis of the benchmark presented.
of course, for a front end guy, Node is still the most exciting thing on the block simply because it is server-side javascript. The fact that it's not much worse than the latest greatest compiled language is pretty exciting to me.
https://github.com/laverdet/node-fibers
In the long term:
Neither of those two things are new ideas. Python has had generators forever. If it solved the underlying problems, Go would never have been written.
So which part of the test demonstrated that it was hard to build, slow, and/or not scalable?
If you're not impressed that JavaScript reached 80% parity with a statically typed, compiled language – well, sorry dude.
Anyway, nobody is begging you to be impressed. 99.999% of successful projects are built with technology that is completely unimpressive.