Fast by default: everyday algorithmic thinking for developers [RU]

Fast by default: everyday algorithmic thinking for developers [RU]

6d07e6d95a43357254698ce9723350e6?s=128

Vladimir Agafonkin

October 06, 2018
Tweet

Transcript

  1. Vladimir Agafonkin ⚡Fast by default: everyday algorithmic thinking 2018

  2. rain.in.ua

  3. None
  4. None
  5. None
  6. None
  7. одержимый скоростью кода

  8. ❤❤❤ open source

  9. 1. Найти узкую задачу 2. ⚡ Создать для нее самую

    быструю и простую в мире JavaScript-библиотеку 3. Перейти к пункту №1
  10. 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, delaunator-rs, 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
  11. github.com/mapbox/delaunator

  12. github.com/d3/d3-delaunay

  13. 1.delaunay: 150s 2.delaunay-fast: 117s 3.faster-delaunay: 5s 4.delaunator: 1s⚡ 5.delaunator-cpp: 0.9s

    6.delaunator-rs: 0.9s триангуляция 1 миллиона точек в JS
  14. mapbox/earcut (JS) mapbox/earcut.hpp (C++)

  15. пространственные индексы

  16. github.com/mourner/rbush github.com/mourner/kdbush github.com/mourner/flatbush github.com/mourner/rbush-knn github.com/mourner/geokdbush github.com/mourner/geoflatbush

  17. mapbox/supercluster (JS) mapbox/supercluter-hpp (C++)

  18. mapbox/supercluster (JS) mapbox/supercluter-hpp (C++)

  19. ~ mapbox/geojson-vt (JS) mapbox/geojson-vt-cpp (C++)

  20. github.com/mapbox/webgl-wind

  21. github.com/mapbox/potpack

  22. mapbox/pixelmatch (JS) mapbox/pixelmatch-cpp (C++)

  23. None
  24. математическое образование? %

  25. None
  26. В такой чудесный, светлый день Мне хочется писать стихами... Но,

    право, ведь порою лень Вы не желали обуздать и сами? Контрольная, смотрю, весьма сложна, И отвечать совсем уж неохота, Когда за окнами прекрасная весна, И о ассемблере не мыслиться чего-то...
  27. Владимир Агафонкин Идиотское введение в алгоритмы 2018

  28. зачем понимать алгоритмы?

  29. None
  30. 99% проблем с быстродействием — алгоритмического характера

  31. медленный код: код, выполняющий лишнюю работу

  32. None
  33. алгоритмическое мышление: искусство отлынивать от лишней работы (в коде)

  34. приложение фреймворки

  35. None
  36. rollup/rollup#2062 rollup: map = magicString.generateMap() rollup: obj = decode(map)

  37. rollup/rollup#2062 rollup: map = magicString.generateMap() magic-string: ... map = encode(obj)

    rollup: obj = decode(map)
  38. rollup/rollup#2062 rollup: map = magicString.generateDecodedMap() magic-string: map = encode(obj) rollup:

    obj = decode(map) source map’ы на 40% быстрее
  39. требует алгоритмического мышления 1. найти узкие места 2. выяснить, почему

    они медленные 3. оптимизировать оптимизация:
  40. None
  41. O(1) O(log n) O(n) O(n log n) O(n2) O(n3)

  42. алгоритмическая сложность: (= понять, почему тормозит и что с этим

    делать) способ описать, как быстродействие меняется с размером данных
  43. array[0] + array[1]; O(1) — моментально

  44. O(n) — подозрительно for (const item of array) { sum

    += item; }
  45. O(n2) — тормозное говно for (let i = 0, n

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

    = item + 10; } } O(n2) — тормозное говно
  47. function foo(array) { for (const item of array) { bar(array,

    item); } } function bar(array, item) { array[array.indexOf(item)] = item + 10; } O(n2) — тормозное говно
  48. accidentallyquadratic.tumblr.com

  49. O(n3) — невыносимо, выкинуть нафиг 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]; } } }
  50. 1. O(1) — моментально 2. O(n) — подозрительно 3. O(n2)

    — тормозное говно 4. O(n3) — выкинуть нафиг
  51. 1. O(1) — 1 2. O(n) — 1000 3. O(n2)

    — 1,000,000 4. O(n3) — 1,000,000,000 (n = 1000)
  52. чорти б мене побрали!!! хай йому грець!! дідько! 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
  53. array.indexOf array.lastIndexOf array.splice array.includes array.reverse array.every Object.values array.find array.some array.findIndex

    array.reduce array.reduceRight array.some Object.keys O(n) — подозрительно
  54. None
  55. array.slice array.concat array.map array.filter str.split подозрительные аллокации

  56. a.slice().concat(b).map(foo) .filter(bar).reduce(bla, 0); выделить память и сразу выкинуть (4 раза)

  57. for (const b of items) { a.slice().concat(b).map(foo) .filter(bar).reduce(bla, 0); }

    выделить память и сразу выкинуть (4 раза)
  58. имьютабилити! реактивность! функциональное программирование! чертовы аллокации

  59. JIT-оптимизатор в JS-движках не всегда понимает, чего вы хотите

  60. пишите код максимально предсказуемо, чтобы движок поменьше угадывал

  61. 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) { ... } } }
  62. 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) { // ";" ... в три раза быстрее
  63. None
  64. O(1) O(n) O(log n) O(log n) — очень быстро

  65. 1 1,000,000 20 O(log n) — очень быстро

  66. бинарный поиск o(log n)

  67. None
  68. None
  69. None
  70. None
  71. None
  72. None
  73. rollup/rollup#2228 … в 40 раз быстрее

  74. 1. O(n) → O(log n) 2. O(n log n) →

    O(n) 3. O(n2) → O(n log n) 4. O(n3) — выкинуть алгоритмическая оптимизация:
  75. медленно медленно медленно алгоритмическая оптимизация:

  76. организовать данные алгоритмическая оптимизация:

  77. алгоритмическая оптимизация: сделать больше в начале, чтобы делать меньше каждый

    следующий раз
  78. структуры данных: как организорвать данные для быстрого поиска и обновления

  79. • hash map • hash set • binary search tree

    • priority heap • linked list • interval tree • grid • r-tree • quadtree • kd-tree структуры данных:
  80. отсортированный массив o(n log n) ❤ любимая структура данных:

  81. отсортировать вокруг элемента, чтобы все слева были меньше o(n) github.com/mourner/quickselect

    39, 28, 28, 33, 21, 12, 22, 50, 53, 56, 59, 65, 90, 77, 95
  82. github.com/mourner/kdbush

  83. priority queue: push: o(1) top: o(1) pop: o(log n) github.com/mourner/tinyqueue

    github.com/mourner/flatqueue
  84. { '1': 10, '2': 20, '3': 30 }; { '0':

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

    '0': 10, '1': 20, ‘2': 30 }; в 15 раз быстрее
  86. все необходимое уже изобрели до вас* *но реализовали через ж

  87. как я читаю научные публикации и прилагаемый код

  88. 1. думайте, как оно работает 2. не бойтесь лезть в

    чужой код + 3. не бойтесь изобретать велосипеды 4. участвуйте в open source ❤ 5. постоянно упрощайте 6. практикуйте оптимизацию , и вы научитесь писать код, который сразу работает быстро
  89. спасибо agafonkin.com