Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Andrii Chyzh - Node.js Performance (Kharkiv JS ...

Andrii Chyzh - Node.js Performance (Kharkiv JS 2019)

Avatar for Andrii Chyzh

Andrii Chyzh

October 05, 2019
Tweet

More Decks by Andrii Chyzh

Other Decks in Technology

Transcript

  1. Standard Slide • Software Engineer / Team Leader at Wix.com

    • Independent project development consulting • More than 8 years in professional software development • Latest 6 years Node.js my main and beloved technology
  2. AGENDA 1. Update To The Latest Version of Node.js 2.

    Set NODE_ENV = production 3. Avoid The Heavy Synchronous Code 4. Speed Up JSON Serialization 5. Write The Asynchronous Code Correctly 6. Use The Streams Correctly 7. Try To Optimize V8 GC 8. Move CPU Bound Tasks Out Of The Node.js Code 9. Try To Use C++ Extensions 10. Use Tools To Locate Performance Issues
  3. THE LATEST VERSION OF NODE.JS Reducing raw server costs by

    circa 40–50% after upgrading Node.js version from 6 to 8 (experience of Ably Realtime) Profit from update to the next version
  4. Google V8 Benchmark: code with Promise.all THE LATEST VERSION OF

    NODE.JS Execution time, ms (lower is better)
  5. Performance impact ▪ Upcoming LTS version of Node.js can give

    a 15-20% of performance boost in real-world scenarios (in compare with the current LTS version). THE LATEST VERSION OF NODE.JS
  6. Setting NODE_ENV to "production" makes ▪ Middleware and other dependencies

    switch to use efficient code path; ▪ Cache view templates (ie Express); ▪ Cache CSS files generated from CSS extensions (ie Express); ▪ Frameworks generate less verbose error messages. NODE_ENV
  7. Performance impact ▪ Complex Express application with NODE_ENV = production

    can be 2-3 times faster than with default NODE_ENV = development NODE_ENV
  8. API without limits and pagination AVOID THE SYNCHRONOUS CODE Case

    Size, KB JSON.stringify, ms JSON.parse, ms Max throughput, RPS 25 items 26 0.231 0.292 3,400 50 items 56 0.339 0.327 2,950 100 items 115 0.727 1.636 610 250 items 264 1.688 2.135 470 500 items 529 3.345 5.548 180 1000 items 1058 9.498 11.255 88 * MacBook Pro, Intel Core i7 2.7 GHz, Node.js 12.11.1
  9. Not effective usage of databases or storages ▪ Large arrays

    of objects for parsing / iteration / transformation (ie queries without limits and projections); ▪ Not using DB features (ie GROUP BY, aggregations) where it can be effective. AVOID THE SYNCHRONOUS CODE
  10. Technical debt and people’s mistakes ▪ Using sync methods in

    web services (ie fs.readFileSync, fs.writeFileSync, child_process.execSync); ▪ Using recursive sync functions; ▪ Wrap heavy sync functions to async/await. AVOID THE SYNCHRONOUS CODE
  11. Performance impact ▪ Only one place with a blocking event

    loop can decrease throughput to super low values. AVOID THE SYNCHRONOUS CODE
  12. It can be 10x faster than JSON.stringify SPEED UP JSON

    SERIALIZATION Throughput, ops/sec (higher is better)
  13. What we can move to reverse proxy? ▪ Gzip; ▪

    HTTP/2; ▪ SSL; ▪ Serving of static files; ▪ Request/response logging; ▪ Metrics/Monitoring; ▪ Authorization. REVERSE PROXY FOR CPU BOUND TASKS
  14. µWebSockets.js ▪ µWebSockets is optimized implementation of HTTP and WebSockets;

    ▪ The implementation is header-only C++ 17 (7K LOC), cross-platform and compiles down to a tiny binary; ▪ µWebSockets.js is the Google V8 bindings to µWebSockets. C++ EXTENSIONS
  15. C++ EXTENSIONS Performance impact (in compare with core http module)

    ▪ 3.2x better for JSON responses with timestamp ▪ 1.8x better for cache server case (with Redis as storage)
  16. C++ EXTENSIONS Performance impact (in compare with ws package) ▪

    23x better short message throughput ▪ 21x better connection performance ▪ 52x less memory usage
  17. What can we use for loading the application? ▪ WRK;

    ▪ Apache Benchmark (ab); ▪ AutoCannon; ▪ Own handmade loaders; ▪ Nginx Mirroring. TOOLING
  18. TOOLING clinic flame --on-port 'autocannon localhost:$PORT' -- node server.js Clinic.js

    Flame: Uncovers The Bottlenecks And Hot Paths With Flamegraphs
  19. TOOLING Clinic.js: Examples and demos for study ▪ A set

    of simple Doctor examples (slow event loop, slow GC, sync IO etc); ▪ A set of simple Bubbleprof examples; ▪ A MongoDB-based Bubbleprof demo/example; ▪ A Flame demo/example. https://github.com/nearform/node-clinic#examples-and-demos
  20. 1. Use the latest LTS version of Node.js 2. Never

    ever run Express in production without NODE_ENV = production 3. Add limits and pagination to API 4. Review project and use Promise.all where it is possible 5. Use streams for working with large data 6. Try to optimize V8 GC by flags 7. Try to use C++ extensions in critical parts of the application 8. Use load and diagnostic tools for locating performance issues CONCLUSIONS