intro to node.js from the perspective of a perl hacker
DESCRIPTION
A brief talk about Node.js given to Kitchener/Waterloo Perl Mongers, September 2011.TRANSCRIPT
![Page 1: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/1.jpg)
Node.jsCoding for the server in Javascript
(from the perspective of a Perl hacker)
![Page 2: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/2.jpg)
Why use Node?
![Page 3: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/3.jpg)
1: Performance
![Page 4: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/4.jpg)
Node.js vs Perl
![Page 5: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/5.jpg)
Qpsmtpd vs Haraka
matt@Valour ~/Perl/node$ time /usr/libexec/postfix/smtp-source -l 5000 -m 50000 -s 100 -d -f matt@local -t [email protected] -c localhost:252550000
real 1m28.451suser 0m1.789ssys 0m6.357smatt@Valour ~/Perl/node$ time /usr/libexec/postfix/smtp-source -l 5000 -m 50000 -s 100 -d -f matt@local -t [email protected] -c localhost:252550000
real 0m12.020suser 0m1.730ssys 0m6.351s
![Page 6: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/6.jpg)
2: Non-Blocking IO
![Page 7: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/7.jpg)
What’s your CPU doing?
Core: ~1 instruction per cycle
L1 cache: 3 cycles
L2 cache: 14 cycles
RAM: ~250 cycles
Disk seek: 40 million cycles
Network: 240 million cycles
Source: http://duartes.org/gustavo/blog/post/what-your-computer-does-while-you-wait
![Page 8: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/8.jpg)
Of course Perl has AIO
POE
AnyEvent
EV
Danga::Socket
The problem: CPAN modules aren’t AsyncTypical example: ORMs
![Page 9: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/9.jpg)
3: The Language…
![Page 10: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/10.jpg)
OK so it’s Javascript
It’s really not that bad, if you structure it well
Node.js has clean modules with no global namespace
I’m not missing all the $@%*& bullshit
exports.hook_rcpt = function (next, connection) { connection.relaying = true; next(OK);}
![Page 11: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/11.jpg)
Classes are Functions
function Connection(client, server) { this.client = client; this.server = server; …}
var conn = new Connection(client, server);
![Page 12: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/12.jpg)
Inheritance is weird, but works
var net = require('net');var util = require('util');
function Socket(options) { if (!(this instanceof Socket)) return new Socket(options); net.Socket.call(this, options); // like SUPER this.current_data = ''; this.on('data', this.process_data); this.on('end', this.process_end);}
util.inherits(Socket, net.Socket);
![Page 13: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/13.jpg)
It’s just as messy as Perl
Stomp on inherited class “hash” entries
Parameter passing isn’t checked in any way
Has stuff you shouldn’t use and consider deprecated
![Page 14: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/14.jpg)
It’s nicer than Perl…
No global variables (perlvar) nonsense
Regexps return an array of matches (0 = whole match, 1 = capture 1, 2 = capture 2, etc)
Most methods don’t mutate, which feels surprisingly nice
Less freaky syntax hidden corners
![Page 15: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/15.jpg)
But it also sucks HARD
No lexical scope. Just global (module level) and function level.
for (i=0; i<10; i++) {
var j=i;
setTimeout(function () { console.log(j) }, 1000);
}
prints ten “9”s.
![Page 16: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/16.jpg)
for (i=0; i<10; i++) { setTimeout((function (j) { return function () { console.log(j) } })(i), 1000);}
Outer function captures j (as JShas function variable scope)
Returns inner function whichuses j as a closure variable
We execute the outer functionpassing in i (which becomes j)
![Page 17: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/17.jpg)
But it also sucks HARD
The “this” variable doesn’t stick around:
MyObject.prototype.do_something_later = function () {
setTimeout(function () { this._do_something() }, 1000);}
MyObject.prototype.do_something_later = function () { var self = this;
setTimeout(function () { self._do_something() }, 1000);}
![Page 18: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/18.jpg)
Async can make things hard
What I’ve typically done before: if ($user->requires_moderation()) { # makes a DB call
… # moderate user
}
What you have to do in Async style: user.requires_moderation(function (err, flag) {
if (err) { … }
if (flag) {
// moderate user
}
});
![Page 19: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/19.jpg)
Npm vs CPAN
Node Package Manager
(Obviously) a lot less stuff than CPAN
But still a surprising amount: 3831 packages as of writing
By default everything installs locally – no more screwing up apps by updating some library
For binary tools this still works. Binaries are symlinks to the install directory
Uploading is also much easier. “npm publish”. Done.
![Page 20: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/20.jpg)
Debugging
Basic debugger built in, pretty shit really
Node-inspector – plugs into WebKit’s Javascript debugger
![Page 21: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/21.jpg)
Profiling
Frankly, totally busted
Node-inspector has something but I can’t make it work
V8’s profiler is based on periodic snapshots, not a full profile
![Page 22: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/22.jpg)
Other nice parts
Methods can be (re)defined on the fly – makes per-object methods trivial
Try/catch and switch part of core language
Named methods/functions are just variablesfunction blah () { } === var blah = function () { }
blah // variable containing the function
blah() // call the function
object.blah() === object[“blah”]()
It’s much more pure OO than Perlnot very many global functions
string.length vs length($string)
![Page 23: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/23.jpg)
Node.js API
Timers, current process, Events, binary buffers, Streams, Crypto, Filesystem, Networking (IPv6 compatible), HTTP Server and client, Child processes, OS info
What’s Missing?Cmdline arg parsing
pack/unpack, flock, seek
Decent date/time manipulation
QuotedPrintable
Encode equivalent (iconv on NPM, but that lacks lots)
Test harness
![Page 24: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/24.jpg)
Example of filesystem access
Hard way:
fs.open(path, ‘r’, function (err, fd) { if (err) { ... } var buf = new Buffer(1024); fs.read(fd, buf, 0, 1024, null, function (err, bytesRead, buf) { ... });});
Easy way:
var rs = fs.createReadStream(path);rs.on(‘error’, function (err) { ... });rs.on(‘data’, function (buf) { ... });
Note: no line-by-line reading built in
![Page 25: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/25.jpg)
IPC coming in node 0.6var cp = require('child_process');
// Note: not what we know as fork() in POSIX/Perlvar n = cp.fork(__dirname + '/sub.js');
n.on('message', function(m) { console.log('PARENT got message:', m);});
n.send({ hello: 'world' }); // uses JSON internally
// in sub.js:process.on('message', function(m) { console.log('CHILD got message:', m);});
process.send({ foo: 'bar' });
![Page 26: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/26.jpg)
IPC with hook.io
Available via NPM
Does transparent message passing between multiple listeners
Kind of like gearman for node, but maybe more feature complete
![Page 27: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/27.jpg)
Using multiple CPUs
By default there’s no threading/forking
Needs a module – “cluster” from npm
var net = require(‘net’);var server = net.createServer(function (client) { // handle client connection});
server.listen(2525);
var cluster = require(‘cluster’);var net = require(‘net’);var server = net.createServer(function (client) { // handle client connection});var c = cluster(server);c.listen(2525);
![Page 28: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/28.jpg)
Links:
http://nodejs.org/http://npmjs.org/https://github.com/baudehlo/Haraka
![Page 29: Intro to Node.js From the perspective of a Perl Hacker](https://reader033.vdocuments.us/reader033/viewer/2022061214/549a3fb6ac7959ff2d8b5a8c/html5/thumbnails/29.jpg)
Thank You