Как использовать память браузера?
Когда набор данных, который может заинтересовать отдельного пользователя, может уместиться в памяти браузера, рекомендуется загрузить все данные сразу в браузер.
Возьмем, к примеру, клинические данные. В клинических исследованиях ученые работают с когортами пациентов. В доминирующем в настоящее время исследовании COVID-19 когорты пациентов включают в лучшем случае десятки тысяч пациентов. Если все данные загружаются в защищенное веб-приложение, подобное Excel, нет необходимости полностью отображать их. Его наличия в памяти браузера достаточно для обеспечения лучшего взаимодействия с пользователем. Пользователи будут счастливы, потому что они смогут фильтровать, искать, сортировать, строить графики и экспортировать, не дожидаясь выполнения дополнительных SQL-запросов и связанных сетевых запросов. Веб-приложения с современной файловой системой API готовы полностью заменить Excel, предпочтительный инструмент исследователей.
Также с точки зрения разработчика обработка данных в браузере с помощью JavaScript намного проще, чем в бэкэнде. Разработка, тестирование и отладка в браузере происходят быстро и просто по сравнению с разработкой внутреннего кода. Бэкэнд-разработка особенно медленна, если код написан на многословной и относительно ограниченной Java, которую также необходимо скомпилировать перед выполнением.
Итак, сколько памяти доступно для веб-страницы, открытой во вкладке браузера? Каков предел памяти для веб-приложения?
Насколько мне известно, в Chrome скрипты не имеют возможности оценить размер доступной свободной памяти. Я буду использовать альтернативный подход для оценки ограничений памяти - я буду заполнять память до тех пор, пока браузер не выйдет из строя.
Как измерить используемую память?
Есть два надежных способа измерить объем памяти, используемый страницей, загруженной во вкладку Chrome:
- в столбце Объем памяти диспетчера задач.
- программно с использованием нового API памяти. Оба подхода дают похожие результаты. Единственное неудобство
performance.measureUserAgentSpecificMemory()
в том, что это метод, предназначенный для разработчиков. Это медленно, если браузер не запущен с дополнительным флагом, что не должно быть проблемой для разработчиков.
Оба подхода дают схожие ценности. Например, когда сценарий на примере веб-страницы https://outofmemory.onrender.com/ создает в общей сложности 11 строк, содержащих 1100 миллионов символов, API памяти возвращает 1100,8 МБ. Диспетчер задач показывает аналогичное значение 1105 МБ.
Как исчерпать память
Для этого мой пример сценария постепенно, раз в секунду, создает строки длиной 100 миллионов символов.
const MB = 1_000_000; function toMB(num) { return (num / MB).toFixed(1); } function tableRow(count, len, mbs) { return `<tr><td>${count}</td><td>${toMB(len)}</td><td>${toMB(mbs)}</td></tr>` } const strs = []; runBtn.onclick = async function addString() { strs.push('X'.repeat(100 * MB)); strs.at(-1)[0]; const memory = await performance.measureUserAgentSpecificMemory(); const chars = strs.reduce((t, s) => t + s.length, 0); table.insertAdjacentHTML('beforeend', tableRow(strs.length, chars, memory.bytes));; setTimeout(addString, 1000); }
Чтобы размер строки в памяти и длина в символах были равны, вновь созданная строка должна быть сглажена. Я получаю последнюю созданную строку, которая является последней строкой в массиве strs
, используя сокращенный метод at()
с отрицательным индексом.
После создания новой строки сценарий добавляет в таблицу строку с количеством созданных строк, общей длиной строк и размером заполненной памяти.
В конце концов, когда не остается свободной памяти, страница вылетает. Страницу можно только закрыть.
На моем обычном компьютере с 8 ГБ страница вылетает после заполнения 2,1 ГБ. Я не уверен, как доступная память зависит от общего объема памяти компьютера. В любом случае результат означает, что большой объем данных может быть безопасно загружен в браузер обычного пользователя.
Образец кода можно загрузить с https://github.com/marianc000/outOfMemory или просмотреть непосредственно на веб-странице образца.