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

Разработка JS библиотеки для визуализации и обр...

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

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

Avatar for JSC “Arcadia Inc.”

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