Slide 1

Slide 1 text

Владимир Агафонкин высокопроизводительные визуализации данных в браузере март 2013

Slide 2

Slide 2 text

agafonkin.com /mourner

Slide 3

Slide 3 text

rain.in.ua

Slide 4

Slide 4 text

визуализации данных

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

интерактивность

Slide 12

Slide 12 text

•реагирование на действия пользователя интерактивность

Slide 13

Slide 13 text

•реагирование на действия пользователя •навигация по данным интерактивность

Slide 14

Slide 14 text

•реагирование на действия пользователя •навигация по данным •фильтрация данных интерактивность

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

No content

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

потребность в интерактивности увеличивается

Slide 21

Slide 21 text

ответственность за обработку данных всё больше смещается от сервера к клиенту

Slide 22

Slide 22 text

чистый JS — быстро рендеринг, DOM — медленно

Slide 23

Slide 23 text

правило №1 чем меньше всего отображаем, тем быстрее

Slide 24

Slide 24 text

обработка данных рендеринг

Slide 25

Slide 25 text

обработка данных рендеринг

Slide 26

Slide 26 text

•фильтрация объектов уменьшение данных

Slide 27

Slide 27 text

•фильтрация объектов •геометрическое отсечение уменьшение данных

Slide 28

Slide 28 text

•фильтрация объектов •геометрическое отсечение •геометрическое упрощение уменьшение данных

Slide 29

Slide 29 text

•фильтрация объектов •геометрическое отсечение •геометрическое упрощение •кластеризация (группировка) уменьшение данных

Slide 30

Slide 30 text

фильтрация

Slide 31

Slide 31 text

поиск 2D-объектов •поиск объектов в текущей прямоугольной видимой области

Slide 32

Slide 32 text

поиск 2D-объектов •поиск объектов в текущей прямоугольной видимой области •поиск объектов в точке (под курсором)

Slide 33

Slide 33 text

загрузка данных — 1 раз поиск/фильтрация — много раз

Slide 34

Slide 34 text

сетка

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

древовидные структуры данных •binary heap •binary search tree •range tree •k-d tree •quadtree •R-tree

Slide 37

Slide 37 text

точки в quadtree

Slide 38

Slide 38 text

прямоугольники в R-tree

Slide 39

Slide 39 text

var tree = new RTree(); tree.insert( {x: 5, y: 10, w: 10, h: 15}, obj); ... tree.search( {x: 7, y: 7, w: 5, h: 5}); github.com/imbcmdth/RTree

Slide 40

Slide 40 text

kothic.org/js

Slide 41

Slide 41 text

определение коллизий

Slide 42

Slide 42 text

Crossfilter (для многих измерений)

Slide 43

Slide 43 text

отсечение ломаных линий алгоритм Коэна-Сазерленда

Slide 44

Slide 44 text

отсечение полигонов алгоритм Сазерленда-Ходжмана

Slide 45

Slide 45 text

упрощение ломаных линий

Slide 46

Slide 46 text

упрощение по расстоянию

Slide 47

Slide 47 text

алгоритм Дугласа-Пекера

Slide 48

Slide 48 text

mourner.github.com/simplify-js

Slide 49

Slide 49 text

кластеризация группировка похожих объектов

Slide 50

Slide 50 text

No content

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

иерархическая кластеризация 1 раз для всех масштабов

Slide 53

Slide 53 text

загрузка и обработка данных

Slide 54

Slide 54 text

UI JS UI

Slide 55

Slide 55 text

UI JS браузер залипает на объемных вычислениях UI

Slide 56

Slide 56 text

Web Workers

Slide 57

Slide 57 text

... worker.postMessage(HUGE_DATA_ARRAY); ... загрузка и пересылка в Worker

Slide 58

Slide 58 text

UI Worker JS загрузка данных UI

Slide 59

Slide 59 text

UI Worker JS браузер залипает на загрузке и пересылке данных загрузка данных UI

Slide 60

Slide 60 text

importScripts('data.js'); ... onmessage = function (e) { var result = searchData(e.data.query); postMessage(result); } загрузка в Worker

Slide 61

Slide 61 text

UI Worker JS загрузка данных UI UI

Slide 62

Slide 62 text

UI Worker JS браузер залипает на получении данных загрузка данных UI UI

Slide 63

Slide 63 text

var array = new Float16Array(len); ... var buffer = array.buffer; postMessage(buffer, [buffer]); // с этого момента buffer недоступен transferable objects (Chrome, Firefox)

Slide 64

Slide 64 text

UI Worker JS загрузка данных UI UI

Slide 65

Slide 65 text

UI Worker JS браузер не залипает, данные пересылаются как ArrayBuffer загрузка данных UI UI

Slide 66

Slide 66 text

function addNumbers(a, b) { 'use asm'; a = a | 0; // int b = +b; // double return +(a + b); // double } светлое будущее — asm.js

Slide 67

Slide 67 text

светлое будущее — asm.js •оптимизация узких мест вычислений

Slide 68

Slide 68 text

светлое будущее — asm.js •оптимизация узких мест вычислений •пока только в FF Nightly

Slide 69

Slide 69 text

светлое будущее — asm.js •оптимизация узких мест вычислений •пока только в FF Nightly •обратная совместимость!

Slide 70

Slide 70 text

технологии рендеринга SVG, Canvas, HTML, WebGL

Slide 71

Slide 71 text

SVG •быстрые нативные события для интерактивности

Slide 72

Slide 72 text

SVG •быстрые нативные события для интерактивности •легко обновлять отдельные объекты

Slide 73

Slide 73 text

SVG •быстрые нативные события для интерактивности •легко обновлять отдельные объекты •тормозит страницу (при большом кол-ве объектов)

Slide 74

Slide 74 text

Canvas •после отрисовки не влияет на отзывчивость страницы

Slide 75

Slide 75 text

Canvas •после отрисовки не влияет на отзывчивость страницы •повторяющиеся части можно отрисовать один раз и раскопировать

Slide 76

Slide 76 text

Canvas •после отрисовки не влияет на отзывчивость страницы •повторяющиеся части можно отрисовать один раз и раскопировать •можно попиксельно рисовать/ обрабатывать в Worker

Slide 77

Slide 77 text

Canvas •дорого перерисовывать при каждом обновлении

Slide 78

Slide 78 text

Canvas •дорого перерисовывать при каждом обновлении •очень сложно с реализацией интерактивности

Slide 79

Slide 79 text

WebGL •основной способ для 3D- визуализаций

Slide 80

Slide 80 text

WebGL •основной способ для 3D- визуализаций •очень быстро в 2D, если нужно отрисовать много спрайтов

Slide 81

Slide 81 text

WebGL •основной способ для 3D- визуализаций •очень быстро в 2D, если нужно отрисовать много спрайтов •в остальных случаях преимущество в скорости перед Canvas-2D спорно

Slide 82

Slide 82 text

WebGL •основной способ для 3D- визуализаций •очень быстро в 2D, если нужно отрисовать много спрайтов •в остальных случаях преимущество в скорости перед Canvas-2D спорно •API намного сложнее и неудобнее

Slide 83

Slide 83 text

WebGL •основной способ для 3D- визуализаций •очень быстро в 2D, если нужно отрисовать много спрайтов •в остальных случаях преимущество в скорости перед Canvas-2D спорно •API намного сложнее и неудобнее •поддержки в IE и iOS не ожидается

Slide 84

Slide 84 text

HTML •удобно использовать для текста и элементов интерфейса

Slide 85

Slide 85 text

HTML •удобно использовать для текста и элементов интерфейса •очень удобно анимировать с помощью CSS Transitions

Slide 86

Slide 86 text

HTML •удобно использовать для текста и элементов интерфейса •очень удобно анимировать с помощью CSS Transitions •тормозит страницу при большом кол-ве объектов

Slide 87

Slide 87 text

производительность Canvas

Slide 88

Slide 88 text

частичная перерисовка

Slide 89

Slide 89 text

частичная перерисовка

Slide 90

Slide 90 text

частичная перерисовка

Slide 91

Slide 91 text

function drawStar(x, y) { ... // нарисовать звезду в x, y } drawStar(10, 20); drawStar(50, 70); ...

Slide 92

Slide 92 text

function drawStar() { var canvas = document.createElement('canvas'); ... // нарисовать звезду return canvas; } var star = drawStar(); ctx.drawImage(star, 10, 20); ctx.drawImage(star, 50, 70); ... копирование

Slide 93

Slide 93 text

группируйте отрисовку по стилям, минимизируйте stroke/fill

Slide 94

Slide 94 text

function drawLine(x1, x2, y1, y2) { ctx.strokeStyle = 'red'; ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); ctx.stroke(); } drawLine(10, 20, 30, 40); drawLine(200, 10, 0, 50); drawLine(30, 40, 70, 0);

Slide 95

Slide 95 text

function drawLine(x1, x2, y1, y2) { ctx.beginPath(); ctx.moveTo(x1, y1); ctx.lineTo(x2, y2); } ctx.strokeStyle = 'red'; drawLine(10, 20, 30, 40); drawLine(200, 10, 0, 50); drawLine(30, 40, 70, 0); ctx.stroke();

Slide 96

Slide 96 text

var data = ctx.getImageData(0, 0, width, height).data; worker.postMessage(data, [data]); ... worker.onmessage = function (e) { var imageData = ctx.createImageData(width, height); imageData.data.set(e.data); ctx.putImageData(imageData, 0, 0); } Canvas + Worker

Slide 97

Slide 97 text

var pixels = new Uint8ClampedArray( width * height); function drawPixel(x, y, r, g, b, a) { var i = 4 * (256 * y + x); pixels[i] = r; pixels[i + 1] = g; pixels[i + 2] = b; pixels[i + 3] = a; } ... postMessage(pixels.buffer, [pixels.buffer]); рисование пикселей в Worker

Slide 98

Slide 98 text

var pixels = new Uint8ClampedArray(data); for (var x = 0; x < width; x++) { for (var y = 0; y < height; y++) { var i = 4 * (256 * y + x); pixels[i] = 2 * pixels[i]; pixels[i + 1] = 2 * pixels[i + 1]; pixels[i + 2] = 2 * pixels[i + 2]; } } ... postMessage(pixels.buffer, [pixels.buffer]); обработка пикселей в Worker

Slide 99

Slide 99 text

UTFGrid

Slide 100

Slide 100 text

UTFGrid •65535 разных символов

Slide 101

Slide 101 text

UTFGrid •65535 разных символов •каждый символ — 4х4 пикселя

Slide 102

Slide 102 text

UTFGrid •65535 разных символов •каждый символ — 4х4 пикселя •сетка + маппинг

Slide 103

Slide 103 text

UTFGrid •65535 разных символов •каждый символ — 4х4 пикселя •сетка + маппинг •в среднем 1-3 КБ на тайл 256х256

Slide 104

Slide 104 text

Спасибо! Вопросы? Владимир Агафонкин [email protected]