290 karma · joined January 20, 2010
Since then I've written and maintain a javascript codec with two optimized versions. One is for [node.js][] and uses node's Buffer methods to do the fast byte to number conversions. The other is for the [browser][] using typed arrays.
I use these libraries in production at various places (the cloud9 IDE backend used them to great effect)
While the native JSON.parse and JSON.stringify is slightly faster than mine with string heavy payloads (and the msgpack is only marginally smaller in that case anyway), when the data is array and number heavy, my codec is much faster than JSON and the data on the wire is a lot smaller.
Also don't underestimate the value of having a binary data type. In my libraries, I extended the format slightly to also encode undefined (as well as null). I also have a string type and a buffer type. In node.js the buffer type is a instance of a node Buffer. In the browser, the buffer is an ArrayBuffer instance (typed array type). So the practical effect is if you put a JS string in, it's encoded as UTF-8 on the wire and comes out the other end as a JS string. If you put a binary buffer in, it comes out the other end as a buffer.
I've contacted the authors of some of the other codecs and when they extend the format, we agree to extend in compatible ways.
My biggest production use of msgpack was as the transport format of my [smith][] rpc system. In smith, an rpc call is done as an array. The first value is the function to call, and the rest are the args. If you're calling an anonymous function, then the identifier is a number. In this usage, the payload tends to be array and number heavy and thus very fast and efficient.
(Edited to add in missing links)
[node.js]: https://github.com/creationix/msgpack-js [browser]: https://github.com/creationix/msgpack-js-browser [smith]: https://github.com/c9/smith
The main thing that helps us work together is clearly defining the interfaces between different modules or pieces of the system and keeping things encapsulated.
For example, I work on the VFS interface that other parts of the system use to access workspaces. If I follow semver, then I can push bugfixes without breaking other's code. If I have to change my interface, then I bump the minor version.
Granted, normal npm modules already provide a lot of this. They have semantic versions and the module name is the name to the API interface. We use vanilla npm modules as well. Architect is a layer on top of this.
The real strength of architect over just plain npm dependencies is the config file. You build your architect application as a JSON (or JS) config file that tells the system what plugins to load and what parameters to provide to each. Since the plugins are decoupled and never touch eachother except through defined architect services, it's easy to see if a dependency is missing. You can replace a dependency with some other module that implements the same interface. This makes manual and automated testing much easier. If I want to test my new feature in isolation, I configure a minimal version of the app and add in my plugin. Then I can add more and more plugins as I test to make sure it integrates with everything. I can switch between config profiles with a single flag.
Also having opposing timezones makes it impossible to make real progress on tightly coupled systems. San Francisco is drinking morning coffee when Amsterdam is going home, I'm in between in Red Lick, Texas.
Architect is just a tool that helps in some cases. The important rule is to decouple modules using some tool (vanilla npm, architect, or something else) and then take interfaces seriously. This makes testing sane, distributed development efficient, and large programs possible.
Using pure events works too (as does dnode and smith), but for large projects they tend to get hairy. Architect separates concerns into defined interfaces provided by configurable plugin instances. It keeps things clean and configurable.
Node depending on how you build it can take between 300 and 1000 ms of time and 10Mb of ram to just start up on the TouchPad. Luvit starts instantly and uses much less ram.
Larger programs are needed to see how the memory usage and performance scales with real work. That could be completely different.
http://howtonode.org/control-flow http://howtonode.org/control-flow-part-ii http://howtonode.org/control-flow-part-iii http://howtonode.org/do-it-fast http://howtonode.org/step-of-conductor
It's a lot better than writing C, (which is what Ryan was doing before starting node) since JS has closures, anonymous functions and other functional niceties that make event based programming much easier.
The fact that you can now code your server-side code in the same language and paradigm as your client-side code is a huge bonus, but was not the reason node was created. V8 is an amazing VM and it's a language that lots of talented developers know. Why not let them loose on the server and see what comes out of this talent.
Given the constraint of using JavaScript on the server, node is the best solution. If you don't want that constraint, then maybe erlang or something with no-shared state is a better solution.
Node is an attempt at using this successful model on the server too where is can solve massive scalability issues using the exact paradigm front-end devs already know.
Also while there are many technical ways to make code look blocking, but really be running other events under the hood, it's this exact implicit running of "other stuff" that makes writing threaded code so hard. You have to assume that things can change between every function call because you don't know if somewhere down the chain it's doing pseudo-blocking.
JavaScript's model is simple, you provide callbacks and you know exactly at what boundaries things can happen asynchronously.
In summary, node is one way of doing it. We think it's a better model and it's proven itself in the browser. If you think another model is better, than by all means go for it!
Let the leapfrogging begin ;)