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

Faster than C?

Faster than C?

Presentation given at JSConf.eu

Felix Geisendörfer

October 07, 2012
Tweet

More Decks by Felix Geisendörfer

Other Decks in Programming

Transcript

  1. Faster than C?
    Parsing binary data in JavaScript
    Felix Geisendörfer 7. Oct, 2012 - JSConf.eu

    View Slide

  2. @felixge
    transloadit.com nodecopter.com

    View Slide

  3. Faster than C?

    View Slide

  4. Sorry about the
    “title bait”

    View Slide

  5. High
    performance
    JavaScript

    View Slide

  6. JavaScript vs C

    View Slide

  7. Good vs Evil

    View Slide

  8. Good Parts vs Evil

    View Slide

  9. Bad Parts vs Evil

    View Slide

  10. early 2010

    View Slide

  11. No MySQL module
    for node.js
    early 2010

    View Slide

  12. All we had was
    NoSQL Libraries
    early 2010

    View Slide

  13. View Slide

  14. Pure JS / No C/C++

    View Slide

  15. Before Buffers
    became usable

    View Slide

  16. The Parser was using
    JavaScript Strings

    View Slide

  17. Node.js Trivia

    View Slide

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

    View Slide

  19. For 3 min and 15 sec

    View Slide

  20. RIP Blobs

    View Slide

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

    View Slide

  22. Anyway

    View Slide

  23. mysql can be done
    without libmysql

    View Slide

  24. View Slide

  25. No good deed goes
    unpunished

    View Slide

  26. Sir Isaac Newton

    View Slide

  27. Third Law of Motion

    View Slide

  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.”

    View Slide

  29. Third Law of Github

    View Slide

  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.”

    View Slide

  31. <3 Github!

    View Slide

  32. View Slide

  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

    View Slide

  34. Of course.

    View Slide

  35. libmysql = C

    View Slide

  36. my library = JavaScript

    View Slide

  37. C > JS, right?

    View Slide

  38. But V8!

    View Slide

  39. And Crankshaft!!

    View Slide

  40. Node.js !!!1!

    View Slide

  41. Was I
    living a lie?

    View Slide

  42. Kind of

    View Slide

  43. V8 / Node
    = Tools

    View Slide

  44. Performance
    is not a tool

    View Slide

  45. Performance is
    hard work &
    data analysis

    View Slide

  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

    View Slide

  47. Third Law of Github

    View Slide

  48. View Slide

  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

    View Slide

  50. Time to give up?

    View Slide

  51. NEVER!

    View Slide

  52. New Parser

    View Slide

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

    View Slide

  54. Third law of Github?

    View Slide

  55. Endgame

    View Slide

  56. Last bottleneck:
    Creating JS Objects

    View Slide

  57. Also: MySQL Server saturated

    View Slide

  58. Anyway

    View Slide

  59. How to write fast JS

    View Slide

  60. Does not work

    View Slide

  61. Profiling
    • Good for spotting small functions with stupid
    algorithms performing many iterations
    • Bad for complex functions with many
    primitive operations

    View Slide

  62. Taking performance advice
    from strangers
    • Good for ideas & inspiration
    • But useless when applied cargo-cult style

    View Slide

  63. Does Work

    View Slide

  64. BDD

    View Slide

  65. Behavior Driven
    Development

    View Slide

  66. Benchmark Driven
    Development

    View Slide

  67. Benchmark Driven Development
    • Similar to test driven development
    • Use it when performance is an explicit design goal
    • Benchmark first > benchmark after !

    View Slide

  68. 1 function benchmark() {
    2 // intentionally empty
    3 }

    View Slide

  69. 1 while (true) {
    2 var start = Date.now();
    3 benchmark();
    4 var duration = Date.now() - start;
    5 console.log(duration);
    6 }

    View Slide

  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

    View Slide

  71. Example Results
    • try...catch is ok
    • big switch statement = bad
    • function calls = very cheap
    • buffering is ok

    View Slide

  72. Favorite

    View Slide

  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 }

    View Slide

  74. Make it faster!

    View Slide

  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);

    View Slide

  76. ->

    View Slide

  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 }

    View Slide

  78. eval = awesome

    View Slide

  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 !!

    View Slide

  80. Recommended Tools
    • node benchmark.js | tee results.tsv
    • R Programming language (with ggplot2) !
    • Makefiles, Image Magick, Skitch

    View Slide

  81. Why?

    View Slide

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

    View Slide


  83. ● ●

    ● ●

    ● ●
    ● ●

    ● ● ●
    ● ● ●
    ● ●
    ● ● ●


    ● ●
    ● ● ●●
    ● ● ●
    ● ● ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●


    ● ● ●
    ● ●
    ● ● ● ●

    ● ●
    ● ● ●
    ● ● ●
    ● ●

    ● ●
    ● ● ●
    ● ●



    ● ●


    ● ●
    ● ●

    ● ● ●
    ● ●





    ● ●
    ● ●
    ● ●
    ● ● ●

    ● ● ●

    ● ●

    ● ● ● ●

    ● ●

    ● ●

    ● ● ●

    ● ●
    ● ● ●


    ● ●
    ● ●
    ● ●
    ● ● ●●
    ● ●

    ● ●
    ● ●
    ● ● ●
    ●● ● ●
    ● ●

    ● ●

    ● ●

    ● ●
    ●● ● ●

    ● ● ●
    ● ●




    ● ● ● ●






    ● ●
    ● ●
    ● ● ●

    ● ● ●
    ● ●
    ● ●



    ● ●


    ● ● ●
    ● ●






    ● ●
    ● ●

    ● ●
    ● ●



    ● ● ● ●



    ● ●

    ● ●

    ● ●

    ● ●

    ● ● ●



    ● ●



    ● ●




    ● ●



    ●●



    ● ●

    ● ●

    ● ● ●
    ● ● ●
    ● ●



    ● ● ●
    ● ●●


    ● ●

    ● ●

    ● ●

    ● ●





    ● ●●



    ● ●
    ● ●

    ● ●




    ● ●
    ● ●

    ● ●



    ● ●


    ● ● ●





    ● ●
    ● ● ●






    ● ●

    ● ●



    ● ● ● ●

    ● ●

    ● ●
    ● ● ● ●
    ● ●

    ● ●

    ● ●

    ● ●


    ● ●




    ● ● ●





    ● ●
    ● ●

    ● ●

    ● ●



    ● ●




    ● ● ●
    ● ● ●

    ● ●
    ● ●
    ● ● ●


    ● ●

    ● ●

    ● ●
    ● ●









    ● ●






    ● ● ●




    ● ● ● ●

    ● ●


    ● ●

    ● ●●
    ● ● ●
    ● ●
    ● ●

    ● ●

    ● ●


    ● ● ● ●

    ● ●
    ● ●


    ● ●
    ● ●
    ● ●
    ● ●

    ● ● ●









    ● ●



    ● ●
    3,000
    4,000
    5,000
    6,000
    mysql2 new−parser
    benchmark
    mbit
    benchmark


    mysql2
    new−parser

    View Slide


  84. ● ●

    ● ●

    ● ●
    ● ●

    ● ● ●
    ● ● ●
    ● ●
    ● ● ●


    ● ●
    ● ● ●●
    ● ● ●
    ● ● ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●
    ● ●


    ● ● ●
    ● ●
    ● ● ● ●

    ● ●
    ● ● ●
    ● ● ●
    ● ●

    ● ●
    ● ● ●
    ● ●



    ● ●


    ● ●
    ● ●

    ● ● ●
    ● ●





    ● ●
    ● ●
    ● ●
    ● ● ●

    ● ● ●

    ● ●

    ● ● ● ●

    ● ●

    ● ●

    ● ● ●

    ● ●
    ● ● ●


    ● ●
    ● ●
    ● ●
    ● ● ●●
    ● ●

    ● ●
    ● ●
    ● ● ●
    ●● ● ●
    ● ●

    ● ●

    ● ●

    ● ●
    ●● ● ●

    ● ● ●
    ● ●




    ● ● ● ●






    ● ●
    ● ●
    ● ● ●

    ● ● ●
    ● ●
    ● ●



    ● ●


    ● ● ●
    ● ●






    ● ●
    ● ●

    ● ●
    ● ●



    ● ● ● ●



    ● ●

    ● ●

    ● ●

    ● ●

    ● ● ●



    ● ●



    ● ●




    ● ●



    ●●



    ● ●

    ● ●

    ● ● ●
    ● ● ●
    ● ●



    ● ● ●
    ● ●●


    ● ●

    ● ●

    ● ●

    ● ●





    ● ●●



    ● ●
    ● ●

    ● ●




    ● ●
    ● ●

    ● ●



    ● ●


    ● ● ●





    ● ●
    ● ● ●






    ● ●

    ● ●



    ● ● ● ●

    ● ●

    ● ●
    ● ● ● ●
    ● ●

    ● ●

    ● ●

    ● ●


    ● ●




    ● ● ●





    ● ●
    ● ●

    ● ●

    ● ●



    ● ●




    ● ● ●
    ● ● ●

    ● ●
    ● ●
    ● ● ●


    ● ●

    ● ●

    ● ●
    ● ●









    ● ●






    ● ● ●




    ● ● ● ●

    ● ●


    ● ●

    ● ●●
    ● ● ●
    ● ●
    ● ●

    ● ●

    ● ●


    ● ● ● ●

    ● ●
    ● ●


    ● ●
    ● ●
    ● ●
    ● ●

    ● ● ●









    ● ●



    ● ●
    3,000
    4,000
    5,000
    6,000
    mysql2 new−parser
    benchmark
    mbit
    benchmark


    mysql2
    new−parser
    Dafuq?
    Dafuq?

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  88. tl;dr

    View Slide

  89. 1. Write a benchmark
    2. Write/change a little code
    3. Collect data
    4. Find problems
    5. Goto 2

    View Slide

  90. Thank you

    View Slide

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

    View Slide

  92. View Slide

  93. View Slide

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

    View Slide