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

Разработка JS библиотеки для визуализации и обработки больших объёмов данных в браузере

Разработка JS библиотеки для визуализации и обработки больших объёмов данных в браузере

В процессе разработки общей библиотеки, занимающейся визуализацией и обработкой данных в браузере, мы сталкивались с различными проблемами производительности и нюансами реализации JavaScript. В этом докладе я расскажу о том, какие возможности предоставляют современные браузеры для разработки и диагностики, с какими сложностями мы столкнулись и что делаем, чтобы код исполнялся быстро, а сайт оставался работоспособным даже при работе с большими объёмами данных.

JSC “Arcadia Inc.”

October 19, 2019
Tweet

More Decks by JSC “Arcadia Inc.”

Other Decks in Programming

Transcript

  1. Разработка JS библиотеки для визуализации и обработки больших объёмов данных

    в браузере Дмитрий Левченко, Ведущий разработчик, Arcadia
  2. О чём буду говорить •Какой наш проект и почему на

    клиенте много данных •Какие компоненты используем в работе •Оптимизация работы с памятью в JS •Оптимизация использования CPU 2
  3. 5

  4. 6

  5. 7

  6. Сколько доступно ресурсов? Chrome, 64bit, Windows • v75: JS Heap

    от 2 до 3.2Гб на вкладку window.performance.memory.jsHeapSizeLimit • v76+: JS Heap до 4Гб Firefox 69, 64bit, Windows • <4Гб 9
  7. Меньше временных объектов arr.map(old => new).filter(item => condition(item)); arr.filter(item =>

    condition(item)).map(old => new); first10filtered = _(arr) .map(old => new) .filter(item => condition(item)) .take(10) .value(); 15
  8. Уменьшение объёма памяти •Устраняем утечки памяти •Избегаем лишнего клонирования объектов

    •Меньше временных объектов •Оптимизация работы со строками 16
  9. Flatstr 'use strict’ // You may be tempted to copy

    and paste this, // but take a look at the commit history first, // this is a moving target so relying on the module // is the best way to make sure the optimization // method is kept up to date and compatible with // every Node version. function flatstr(s) { s | 0 return s } module.exports = flatstr 18
  10. Представление строк в V8 20 let part = 'This is

    long part of long string'; let str = part + '. This is another part';
  11. Экспорт CSV — оригинальный код 21 let result = '';

    rows.forEach(row => { let csvLine = ''; const colData = getColumnsData(row); for (let i = 0; i < colData.length; i++) { csvLine += colData[i]; if (i !== colData.length - 1) { csvLine += ','; } } result += csvLine + '\r\n'; }); return result;
  12. Экспорт CSV — join 23 const csvLines = []; rows.forEach(row

    => { const csvLine = getColumnsData(row).join(','); csvLines.push(csvLine); }); return csvLines.join('\r\n');
  13. Экспорт CSV — правильный вариант 25 public *getCsv(data, getColumnsDataFn) {

    for (const row of data) { const colData = getColumnsDataFn(row); yield '"' + colData.join('","') + '"'; } }
  14. Уменьшение объёма памяти •Устраняем утечки памяти •Избегаем лишнего клонирования объектов

    •Меньше выделений памяти •Оптимизация работы со строками •Гриды — не отдаём все данные сразу 28
  15. Меньше работы в циклах return this.exportService.getCsv(headers, dt.rows, lineData => uniqueCols.map(col

    => dt.dataColumn(col.id)(lineData))); const dataCols = uniqueCols.map(col => dt.dataColumn(col.id)); return this.exportService.getCsv(headers, dt.rows, lineData => dataCols.map(col => col(lineData))); 31
  16. Порядок исполнения условий naturalSort = (a, b) => { const

    aNumber = isFinite(a) ? a : this.isNumber(a) ? parseFloat(a) : null; const bNumber = isFinite(b) ? b : this.isNumber(b) ? parseFloat(b) : null; if (isFinite(aNumber) && isFinite(bNumber)) { return aNumber - bNumber; } return this.compareFn('' + a, '' + b); } 33
  17. naturalSort = (a, b) => { if (isFinite(a) && isFinite(b))

    { return a - b; } const aStr = '' + a; const bStr = '' + b; const strCompareResult = this.compareFn(aStr, bStr); if (strCompareResult === 0) { return 0; } const aNumber = this.parseFloatEx(aStr); if (isFinite(aNumber)) { const bNumber = this.parseFloatEx(bStr); if (isFinite(bNumber)) { return aNumber - bNumber; } } return strCompareResult; } Порядок исполнения условий 34
  18. Set и Map const set = new Set<number>(); set.add(42); if

    (set.has(42)) ... const map = new Map<string, ISomeObject>(); map.set('myId', {a: 42}); const obj = map.get('myId’); if (map.has('myId’)) ... 36
  19. Оптимизация производительности •Не делаем лишней работы. Кешируем •Порядок исполнения условий

    важен •Используем подходящие структуры данных: Set, Map •Цена callback-ов: for vs forEach 37
  20. Архитектурные моменты •Взгляд на систему с высокого уровня •Сторонние библиотеки

    •Доверяй, но проверяй •Лучше обновляйтесь, но… •Должен ли код быть оптимальным? 38