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

Fast by Default: Algorithmic Optimization in Practice (JSCamp 2019)

Fast by Default: Algorithmic Optimization in Practice (JSCamp 2019)

Vladimir Agafonkin

July 19, 2019
Tweet

More Decks by Vladimir Agafonkin

Other Decks in Programming

Transcript

  1. 1.find a narrowly scoped task 2.⚡make the world’s fastest and

    simplest JavaScript library for it 3. repeat
  2. Leaflet, mapbox-gl-js, mapbox-gl-native, earcut, earcut.hpp, pixelmatch, rbush, rbush-knn, kdbush, kdbush.hpp,

    geokdbush, flatbush, geoflatbush, concaveman, pbf, supercluster, supercluster.hpp, dobbyscan, delaunator, d3-delaunay, delaunator-rs, linematch, lineclip, geojson-vt, geojson-vt-cpp, potpack, simplify-js, cheap-ruler, polylabel, tinyqueue, flatqueue, tile-cover, which-polygon, quickselect, webgl-wind, suncalc, flamebearer, simple-statistics, tiny-sdf, geobuf, tile-reduce, geojson.hpp, geometry.hpp, tile-decorator, mbtiles-extracts, simpleheat, road-orientation-map, rollup, magic-string, sourcemap-codec, binary-split
  3. 1. find a bottleneck 2. find out why it’s slow

    3. make it faster optimization:
  4. 1. find a bottleneck 2. find out why it’s slow

    3. make it faster optimization:
  5. 1. O(1) — 1 2. O(n) — 1000 3. O(n2)

    — 1,000,000 4. O(n3) — 1,000,000,000 (n = 1000)
  6. O(n2) — terribly slow for (let i = 0, n

    = array.length; i < n; i++) { for (let j = i + 1; j < n; j++) { sum += array[i] + array[j]; } }
  7. function foo(array) { for (const item of array) { bar(array,

    item); } } function bar(array, item) { array[array.indexOf(item)] = item + 10; } O(n2) — terribly slow
  8. O(n3) — rewrite from scratch for (let i = 0,

    n = array.length; i < n; i++) { for (let j = i + 1; j < n; j++) { for (let k = j + 1; k < n; k++) { sum += array[i] + array[j]; } } }
  9. 1. O(1) — instant 2. O(n) — suspicious 3. O(n2)

    — terribly slow 4. O(n3) — throw out
  10. if (j < 0) { if (triangles.length === 0) triangles.push([i]);

    return; } for (let n = triangles.length, a = 0; a < n; ++a) { let sa = triangles[a]; if (sa[0] === j) { for (let b = a + 1; b < n; ++b) { let sb = triangles[b]; if (sb[sb.length - 1] === i) { triangles.splice(b, 1); triangles[a] = sa = sb.concat(sa); return; } } sa.unshift(i); return; } d3/d3-delaunay#23
  11. Rich-Harris/sourcemap-codec#71 const lines = input.split(';'); for (const line of lines)

    { const segments = line.split(','); for (const segment of segments) { const decoded = decode(segment); for (const i of decoded) { ... } } }
  12. Rich-Harris/sourcemap-codec#71 for (let i = 0; i < input.length; i++)

    { const c = input.charCodeAt(i); if (c === 44) { // "," ... } else if (c === 59) { // ";" ... 3 times faster
  13. 1. O(n) → O(log n) 2. O(n log n) →

    O(n) 3. O(n2) → O(n log n) 4. O(n3) — throw out algorithmic optimization
  14. • hash map • hash set • binary search tree

    • priority heap • linked list • interval tree • grid • r-tree • quadtree • kd-tree data structures
  15. sort so that all items in the left are smaller

    o(n) github.com/mourner/quickselect 39, 28, 28, 33, 21, 12, 22, 50, 53, 56, 59, 65, 90, 77, 95
  16. { '1': 10, '2': 20, '3': 30 }; { '0':

    10, '1': 20, ‘2': 30 }; HashTable Array [10, 20, 30];
  17. istanbuljs/istanbul-lib-instrument#22 { '1': 10, '2': 20, '3': 30 }; {

    '0': 10, '1': 20, ‘2': 30 }; 15 times faster
  18. 1. learn how things work under the hood 2. don’t

    hesitate to dig inside frameworks 3. contribute to open source 4. don’t be afraid to reinvent the wheel 5. simplify your code constantly 6. practice optimization, and you’ll learn how to write fast code from the start