Pro Yearly is on sale from $80 to $50! »

Faster than C?

Faster than C?

Presentation given at JSConf.eu

23968f0ca75b13463d2db5343e5c2096?s=128

Felix Geisendörfer

October 07, 2012
Tweet

Transcript

  1. Faster than C? Parsing binary data in JavaScript Felix Geisendörfer

    7. Oct, 2012 - JSConf.eu
  2. @felixge transloadit.com nodecopter.com

  3. Faster than C?

  4. Sorry about the “title bait”

  5. High performance JavaScript

  6. JavaScript vs C

  7. Good vs Evil

  8. Good Parts vs Evil

  9. Bad Parts vs Evil

  10. early 2010

  11. No MySQL module for node.js early 2010

  12. All we had was NoSQL Libraries early 2010

  13. None
  14. Pure JS / No C/C++

  15. Before Buffers became usable

  16. The Parser was using JavaScript Strings

  17. Node.js Trivia

  18. “ Buffers” used to be called “Blobs”

  19. For 3 min and 15 sec

  20. RIP Blobs ✞

  21. Sun Dec 13 08:39:20 2009 - Sun Dec 13 08:42:45

    2009
  22. Anyway

  23. mysql can be done without libmysql

  24. None
  25. No good deed goes unpunished

  26. Sir Isaac Newton

  27. Third Law of Motion

  28. “When a first body exerts a force F1 on a

    second body, the second body simultaneously exerts a force F2 = −F1 on the first body. This means that F1 and F2 are equal in magnitude and opposite in direction.”
  29. Third Law of Github

  30. “When a first person pushes a library L1 into a

    remote repository, a second person simultaneously starts working on a second library L2 which will be equally awesome, but in a different way.”
  31. <3 Github!

  32. None
  33. 0 500 1,000 1,500 mysql−0.9.6 mysql−libmysqlclient−1.5.1 benchmark mbit benchmark mysql−0.9.6

    mysql−libmysqlclient−1.5.1
  34. Of course.

  35. libmysql = C

  36. my library = JavaScript

  37. C > JS, right?

  38. But V8!

  39. And Crankshaft!!

  40. Node.js !!!1!

  41. Was I living a lie?

  42. Kind of

  43. V8 / Node = Tools

  44. Performance is not a tool

  45. Performance is hard work & data analysis

  46. 0 500 1,000 1,500 mysql−0.9.6 mysql−libmysqlclient−1.5.1mysql−2.0.0−alpha3 benchmark mbit benchmark mysql−0.9.6

    mysql−libmysqlclient−1.5.1 mysql−2.0.0−alpha3
  47. Third Law of Github

  48. None
  49. 0 1,000 2,000 3,000 4,000 mysql−0.9.6 mysql−libmysqlclient−1.5.1 mysql−2.0.0−alpha3 mariadb−0.1.7 benchmark

    mbit benchmark mysql−0.9.6 mysql−libmysqlclient−1.5.1 mysql−2.0.0−alpha3 mariadb−0.1.7
  50. Time to give up?

  51. NEVER!

  52. New Parser

  53. 0 2,000 4,000 6,000 mysql2 new−parser benchmark mbit benchmark mysql2

    new−parser
  54. Third law of Github?

  55. Endgame

  56. Last bottleneck: Creating JS Objects

  57. Also: MySQL Server saturated

  58. Anyway

  59. How to write fast JS

  60. Does not work

  61. Profiling • Good for spotting small functions with stupid algorithms

    performing many iterations • Bad for complex functions with many primitive operations
  62. Taking performance advice from strangers • Good for ideas &

    inspiration • But useless when applied cargo-cult style
  63. Does Work

  64. BDD

  65. Behavior Driven Development

  66. Benchmark Driven Development

  67. Benchmark Driven Development • Similar to test driven development •

    Use it when performance is an explicit design goal • Benchmark first > benchmark after !
  68. 1 function benchmark() { 2 // intentionally empty 3 }

  69. 1 while (true) { 2 var start = Date.now(); 3

    benchmark(); 4 var duration = Date.now() - start; 5 console.log(duration); 6 }
  70. Benchmark Driven Development • Next step: Implement a tiny part

    of your function • Example: Parse headers of MySQL packets • Look at impact, tweak code, repeat
  71. Example Results • try...catch is ok • big switch statement

    = bad • function calls = very cheap • buffering is ok
  72. Favorite

  73. 1 function parseRow(columns, parser) { 2 var row = {};

    3 for (var i = 0; i < columns.length; i++) { 4 row[columns[i].name] = parser.readColumnValue(); 5 } 6 return row; 7 }
  74. Make it faster!

  75. 1 var code = 'return {\n'; 2 3 columns.forEach(function(column) {

    4 code += '"' + column.name + '":' + 'parser.readColumnValue(),\n'; 5 }); 6 7 code += '};\n'; 8 9 var parseRow = new Function('columns', 'parser', code);
  76. ->

  77. 1 function parseRow(columns, parser) { 2 return { 3 id

    : parser.readColumnValue(), 4 title : parser.readColumnValue(), 5 body : parser.readColumnValue(), 6 created : parser.readColumnValue(), 7 updated : parser.readColumnValue(), 8 }; 9 }
  78. eval = awesome

  79. Data analysis • Produce data points as tab separated values

    • Add as many VM/OS metrics as you can get to every line • Do not mix data and analysis !!
  80. Recommended Tools • node benchmark.js | tee results.tsv • R

    Programming language (with ggplot2) ! • Makefiles, Image Magick, Skitch
  81. Why?

  82. 0 2,000 4,000 6,000 mysql2 new−parser benchmark mbit benchmark mysql2

    new−parser
  83. • • • • • • • • • •

    • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • •• • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • 3,000 4,000 5,000 6,000 mysql2 new−parser benchmark mbit benchmark • • mysql2 new−parser
  84. • • • • • • • • • •

    • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • •• • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • •• • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • • 3,000 4,000 5,000 6,000 mysql2 new−parser benchmark mbit benchmark • • mysql2 new−parser Dafuq? Dafuq?
  85. 3,000 4,000 5,000 6,000 0 100 200 300 number mbit

    benchmark mysql2 new−parser
  86. 10 20 30 0 100 200 300 number Heap Total

    (MB) benchmark mysql2 new−parser
  87. 5 10 15 0 100 200 300 number Heap Used

    (MB) benchmark mysql2 new−parser
  88. tl;dr

  89. 1. Write a benchmark 2. Write/change a little code 3.

    Collect data 4. Find problems 5. Goto 2
  90. Thank you

  91. github.com/felixge/faster-than-c All benchmarks, results and analysis scripts Thank you !

  92. None
  93. None
  94. nodecopter.com Dublin, Oct 20 (Saturday) Brighton, Nov 10 http://tinyurl.com/brcopter