$30 off During Our Annual Pro Sale. View Details »

Fast by default: everyday algorithmic thinking ...

Fast by default: everyday algorithmic thinking for developers

We've grown to rely on high level frameworks so much that we no longer know how computers work. So when we're stuck with bad performance, simply changing frameworks won't help — you have to understand what's going on under the hood, and what to do with it. That's what algorithmic thinking is about.

Does the app have a bottleneck, and how do you identify it? Does this code really have to be slow, or is it doing unnecessary work? How do we achieve the same result while doing less? Can we delay a part of the work? Can we order the data differently for faster processing? When you practice algorithmic thinking, answering those questions becomes second nature, and eventually you learn to write code that's fast from the start, by default. So let me introduce you to algorithms again, from scratch, in a way that is useful for your everyday work.

Vladimir Agafonkin

September 12, 2018
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. Back to step 1
  2. Leaflet, mapbox-gl-js, mapbox-gl-native, earcut, earcut.hpp, rbush, rbush-knn, kdbush, kdbush.hpp, geokdbush,

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

    bottleneck 3. optimize the bottleneck performance optimization: requires understanding algorithms
  4. algorithmic complexity: and where to look for unnecessary work a

    way to describe how performance scales with input size
  5. 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]; } }
  6. 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
  7. O(n3) — unbearable, throw away 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]; } } }
  8. 1. O(1) — instant 2. O(n) — suspicious 3. O(n2)

    — terribly slow 4. O(n3) — throw away
  9. 1. O(1) — 1 2. O(n) — 1000 3. O(n2)

    — 1,000,000 4. O(n3) — 1,000,000,000 (n = 1000)
  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. for (const b of items) { a.slice().concat(b).map(foo) .filter(bar).reduce(bla, 0); }

    allocate memory and throw it away immediately (4 times)
  12. 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) { ... } } }
  13. 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) { // ";" ... 2.7x faster decoding
  14. 1. O(n) → O(log n) 2. O(n log n) →

    O(n) 3. O(n2) → O(n log n) 4. O(n3) — throw away algorithmic optimization:
  15. do more at the beginning to do less every next

    time algorithmic optimization:
  16. • hash map • hash set • binary search tree

    • priority heap • linked list data structures: • interval tree • grid • r-tree • quadtree • kd-tree
  17. sorting an array so that smallest k items come first:

    o(n) github.com/mourner/quickselect
  18. • how often do you insert items? • how often

    do you remove items? • how often do you access items, and how? data structures:
  19. { '1': 10, '2': 20, '3': 30 }; { '0':

    10, '1': 20, ‘2': 30 }; HashTable Array [10, 20, 30];
  20. 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