efficient use of nodejs

30
Efficient use of NodeJS Yuriy Bogdanov Inspiration-driven software engineer

Upload: yura-bogdanov

Post on 06-May-2015

1.516 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Efficient use of NodeJS

Efficient use of NodeJS

Yuriy BogdanovInspiration-driven software engineer

Page 2: Efficient use of NodeJS

My experience

• 10 years of web development

• 2009-2012 own projects

• 3 years of NodeJS on production, starting from earliest versions

• Full-stack-JS projects

Page 3: Efficient use of NodeJS

Eventr, 2010

• Have ~70k RSS/Atom up to date

• Tricky TTL logic

• ~10 feeds per second (in peak)

• A lot of I/O, less CPU

• On PHP was a lot of processes, and a lot of redundancy

• http://habrahabr.ru/post/95526/

Page 4: Efficient use of NodeJS

Eventr, 2010

• NodeJS v0.1.x

• Rewritten feeds updating on Node

• Performance x25 vs PHP

• Despite the newness of technology, it was successful

Page 5: Efficient use of NodeJS

Tactoom, 2011

• Being inspired, I decided to write the next project completely on JS

• NodeJS v0.4.x

• It was a failure, the technology wasn’t justified in this context

• http://habrahabr.ru/post/130345/

Page 6: Efficient use of NodeJS

NodeJS, 2012

• Successful experience with NodeJS

• Realtime solutions for IP-telephony

• Big data exchange on S3

Page 7: Efficient use of NodeJS

Efficient use of NodeJS

• NodeJS is easy-going, but it's unpredictable outside of your laptop

• NodeJS though seems to be multipurpose, but for my opinion, has a rather narrow scope of effective usage

• You better not use NodeJS in cases where Ruby, PHP, etc. will do it easily

Page 8: Efficient use of NodeJS

MythologyNode.js is a platform built on Chrome's JavaScript runtime for easily building fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient, perfect for data-intensive real-time applications that run across distributed devices.

(c) nodejs.org

Page 9: Efficient use of NodeJS

Fast?

• V8 - yes, fast, but this speed is not the main bottleneck today

• non-blocking I/O - makes sense, if you really have a lot of I/O

Page 10: Efficient use of NodeJS

A typical taskUser’s page

• Display a page with following data:

1. Posts

2. Following

3. Followers

Page 11: Efficient use of NodeJS

Arithmetics

• db.getUserFeed()

• db.getUserFollowing()

• db.getUserFollowers()

I/O90%

CPU10%

Time

• I/O - query to DB

• CPU - handling data

Time:

User’s page:

Page 12: Efficient use of NodeJS

ArithmeticsuserPageAction: function(callback) { db.getUserFeed(function(err, feed){ if (err) return callback(err); db.getUserFollowing(function(err, following){ if (err) return callback(err); db.getUserFollowers(function(err, followers){ if (err) return callback(err); callback(null, { feed: feed, following: following, followers: followers }); }); }); });}

50ms

30ms

40ms

~120ms

Page 13: Efficient use of NodeJS

ArithmeticsuserPageAction: function(callback) { async.parallel({ feed: function(callback) { db.getUserFeed(callback); }, following: function(callback) { db.getUserFollowing(callback); }, followers: function(callback) { db.getUserFollowers(callback); } }, callback);}

node-asyncby Caolan McMahon

30ms

50ms

40ms

45 + 5 = 50ms

45 + 5

27 + 3

36 + 4

50ms

Page 14: Efficient use of NodeJS

ArithmeticsuserPageAction: function() { var feed = db.getUserFeed.future(db), following = db.getUserFollowing.future(db), followers = db.getUserFollowers.future(db); return { feed: feed.yield(), following: following.yield(), followers: followers.yield() };}.async()

30ms50ms

40ms

node-syncby Yuriy Bogdanov

45 + 5 = 50ms

Page 15: Efficient use of NodeJS

Arithmetics

120ms

I/O90%

CPU10%

Sequent ia l

I/O79%

CPU21%

Para l le l

50ms

CPU utilization

5 + 3 + 4 = 12ms

Page 16: Efficient use of NodeJS

Arithmetics

CPU100%

ProductionYour laptop

I/O79%

CPU21%

While CPU is free,parallelism is efficient

Page 17: Efficient use of NodeJS

Arithmetics concurrency

benchmark expected real

ab -n 1 -c 1 50ms 52ms

ab -n 100 -c 1 50ms 50ms

ab -n 100 -c 10 50ms

ab -n 100 -c 100 50ms

123msx2

981msx20

120ms x 8

CPU 21% ~ Response time

https://github.com/0ctave/node-bench

Page 18: Efficient use of NodeJS

Arithmetics concurrency

CPU Response time Response time under load

21% 50ms 981ms

10% 120ms

ab -n 100 -c 100

1212ms+23%

http://www.slideshare.net/yurabogdanov/nodejs-8223169

Page 19: Efficient use of NodeJS

Arithmetics PHP

CPU/IOthread

NodeJS

CPUthread

I/Othreads

Time

Page 20: Efficient use of NodeJS

Arithmetics conclusions

• As more I/O part, as more profitable to use NodeJS

• And vice-versa :)

• Parallelism within a single request does nothing (under load)

• That is, synchronous Ruby have done better with given task

• But there are other problems...

Page 21: Efficient use of NodeJS

Language & Platform• JavaScript is super flexible, which is not

always an advantage for the server technology

• There are many non-obvious nuances of the technology itself, which must always be considered

• In the absence of a clear convention it’s difficult to design a great app

Page 22: Efficient use of NodeJS

getUserNetwork: function(callback) { var db = this.getDb(); userId = this.getSessionUserId();

db.getUserFollowing(userId, function(err, following){ if (err) return callback(err);

db.getUserFollowers(userId, function(err, followers){ if (err) return callback(err);

callback(null, { following: following, followers: followers }); }); });}

JavaScript

Page 23: Efficient use of NodeJS

JavaScript

$ node --use_strict app.js

./node_modules/express/node_modules/debug/lib/debug.js:119 + ' +' + humanize(ms) + '\033[0m'

SyntaxError: Octal literals are not allowed in strict mode.

• CoffeeScript

• JSLint

• node --use_strict (starting from 0.9.х)

Page 24: Efficient use of NodeJS

Language & Platform• monkey-patching is convenient, but it

leads to difficulties when debugging

• event emitter difficult to debug and it is often misused

• Difficult to avoid memory leaks, especially with the use of third-party libraries

• There is no decent way to debug, especially on production

Page 25: Efficient use of NodeJS

Language & Platform

• No multi-user aspect

• Memory leaks is not a such problem

• Less async stuff

• Mature frameworks and standards

JavaScript is much easier on front-end:

Page 26: Efficient use of NodeJS

Language & Platform

• One process serves many request at the time

• Therefore, the error in a single request can:

• lead to loss / collision of data

• hanging the hundreds of other requests

• compromise the integrity of the system

• No guaranteed isolation stack for each request / session (as, for example, in erlang)

Bad reliability

Page 27: Efficient use of NodeJS

Language & Platform

CPU1 CPU2 CPU3 CPU4

Bad reliability

node1 node2 node3 node4

-250

connections1,000

http://mr-aleph.livejournal.com/322682.html

Page 28: Efficient use of NodeJS

Shared state

• Very convenient for a sort of tasks

• Loses favor when scaling

• Difficult to make reliable

var counter = 0;app.get('/', function(req, res){ res.send('Counter: ' + counter); counter++;});

Page 29: Efficient use of NodeJS

So what to do with NodeJS?

• Far from users as possible

• Where the load is predictable, where you can "pinch throat"

• I/O intensive, CPU free

• Do «kill -9» reliable

• have a persistence data layer

• do atomic operations

• use transactions when possible

• Not for a vital features

• Things you can not do without it

Page 30: Efficient use of NodeJS

Yuriy Bogdanov

Thanks for your attention

http://about.me/bogdanovhttps://github.com/0ctavehttp://twitter.com/yuriybogdanovhttp://linkedin.com/in/yuriybogdanovhttp://octave.habrahabr.ru/

[email protected]

About.me:Github:Twitter:LinkedIn:Habrahabr:

Email: