Efficient use of NodeJS


Published on

Published in: Technology
  • Be the first to comment

No Downloads
Total views
On SlideShare
From Embeds
Number of Embeds
Embeds 0
No embeds

No notes for slide

Efficient use of NodeJS

  1. 1. Efficient use ofNodeJSYuriy BogdanovInspiration-driven software engineer
  2. 2. 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
  3. 3. 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/
  4. 4. Eventr, 2010• NodeJS v0.1.x• Rewritten feeds updating on Node• Performance x25 vs PHP• Despite the newness of technology, it was successful
  5. 5. 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/
  6. 6. NodeJS, 2012• Successful experience with NodeJS• Realtime solutions for IP-telephony• Big data exchange on S3
  7. 7. Efficient use of NodeJS• NodeJS is easy-going, but its 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
  8. 8. MythologyNode.js is a platform built on Chromes JavaScript runtime for easilybuilding fast, scalable network applications. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight andefficient, perfect for data-intensive real-time applications that runacross distributed devices. (c) nodejs.org
  9. 9. 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
  10. 10. A typical task User’s page• Display a page with following data: 1. Posts 2. Following 3. Followers
  11. 11. ArithmeticsUser’s page: Ti me• db.getUserFeed() CPU 10%• db.getUserFollowing()• db.getUserFollowers() I/OTime: 90%• I/O - query to DB• CPU - handling data
  12. 12. Arithmetics userPageAction: function(callback) {50ms db.getUserFeed(function(err, feed){ if (err) return callback(err);30ms db.getUserFollowing(function(err, following){ if (err) return callback(err);40ms db.getUserFollowers(function(err, followers){ if (err) return callback(err); callback(null, { feed: feed, following: following, followers: followers }); }); }); }); ~120ms }
  13. 13. Arithmetics userPageAction: function(callback) {50ms async.parallel({ feed: function(callback) { 50ms45 + 5 db.getUserFeed(callback); },30ms following: function(callback) {27 + 3 db.getUserFollowing(callback); },40ms followers: function(callback) {36 + 4 db.getUserFollowers(callback); } }, callback); } 45 + 5 = 50ms node-async by Caolan McMahon
  14. 14. Arithmetics userPageAction: function() { var feed = db.getUserFeed.future(db), following = db.getUserFollowing.future(db), followers = db.getUserFollowers.future(db); return {50ms feed: feed.yield(),30ms following: following.yield(),40ms followers: followers.yield() }; }.async() 45 + 5 = 50ms node-sync by Yuriy Bogdanov
  15. 15. Arithmetics120ms 50msS e qu en ti al Parallel 5+3+4= 12ms CPU 10% CPU 21% I/OI/O 79%90% CPU utilization
  16. 16. ArithmeticsYour laptop Production CPU 21% CPU 100%I/O79% While CPU is free, parallelism is efficient
  17. 17. Arithmetics concurrency CPU 21% ~ Response time benchmark expected real ab -n 1 -c 1 50ms 52ms ab -n 100 -c 1 50ms 50ms ab -n 100 -c 10 50ms 123ms x2 ab -n 100 -c 100 50ms 981ms x20https://github.com/0ctave/node-bench 120ms x 8
  18. 18. Arithmetics concurrencyCPU Response time Response time under load21% 50ms 981ms10% 120ms 1212ms +23% ab -n 100 -c 100 http://www.slideshare.net/yurabogdanov/nodejs-8223169
  19. 19. ArithmeticsPHP NodeJS TimeCPU/IO CPU I/Othread thread threads
  20. 20. 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...
  21. 21. 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
  22. 22. JavaScriptgetUserNetwork: 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 }); }); });}
  23. 23. JavaScript• CoffeeScript• JSLint• node --use_strict (starting from 0.9.х)$ node --use_strict app.js./node_modules/express/node_modules/debug/lib/debug.js:119 + + + humanize(ms) + 033[0mSyntaxError: Octal literals are not allowed in strict mode.
  24. 24. 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
  25. 25. Language & PlatformJavaScript is much easier on front-end:• No multi-user aspect• Memory leaks is not a such problem• Less async stuff• Mature frameworks and standards
  26. 26. Language & Platform Bad reliability• 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)
  27. 27. Language & Platform Bad reliability CPU1 CPU2 CPU3 CPU4 node1 node2 node3 node4 -250 1,000 connections http://mr-aleph.livejournal.com/322682.html
  28. 28. Shared statevar counter = 0;app.get(/, function(req, res){ res.send(Counter: + counter); counter++;});• Very convenient for a sort of tasks• Loses favor when scaling• Difficult to make reliable
  29. 29. So what to do with NodeJS?• Far from users as possible• Where thethroat" predictable, where you can "pinch load is• 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
  30. 30. Yuriy BogdanovAbout.me: http://about.me/bogdanov Github: https://github.com/0ctave Twitter: http://twitter.com/yuriybogdanov LinkedIn: http://linkedin.com/in/yuriybogdanovHabrahabr: http://octave.habrahabr.ru/ Email: octave@tactoom.com Thanks for your attention