Управление памятью в браузере с каждым вызовом функции? - PullRequest
0 голосов
/ 05 апреля 2020

Пытаясь определить, как наиболее эффективно выполнить серию повторяющихся шагов, я обнаружил, что очень мало знаю об использовании памяти в веб-браузере. Я читал о сборщике мусора и утечках памяти несколько раз прежде, но это все еще очень мало. Интересующий меня сценарий c выглядит следующим образом.

  1. Набор объектов данных извлекается из indexedDB с помощью оператора getAll в диапазоне ключей. Все данные являются текстовыми и никогда не будут превышать 0,25 МБ и, вероятно, всегда будут меньше 0,1 МБ.
  2. Массив объектов данных передается функции, которая создает узел во фрагменте документа и заменяет узел в DOM.
  3. Когда пользователь изменяет / добавляет / удаляет данные, состояние сохраняется в базе данных с использованием последовательности get/put и add, если создается новый объект. Это выполняется для одного объекта за раз, а не для всего массива.
  4. Когда пользователь завершает работу, извлекается следующий набор данных и узел DOM заменяется снова. Пользователи могут перемещаться вперед и назад по пакетам данных, которые они создают.

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

Предположим, пользователь быстро щелкает серию пакетов данных. Каждый раз, когда данные извлекаются, а новые узлы, создаваемые и заменяемые в DOM, являются одним и тем же пространством памяти, используемым снова и снова, или каждый вызов занимает больше места, а память, используемая в предыдущих вызовах, позже освобождается G C, такой, что быстрый щелчок по десяти узлам временно требует данных на десять узлов? Я имею в виду, что это включает в себя все данные, участвующие в этих шагах, а не только заменяемый узел DOM.

Одна из причин, по которой я спрашиваю, заключается в том, что я рассматривал возможность хранения массива объектов данных в ОЗУ и обновления объектов как пользователь выполняет редактирование / сборку большего количества объектов, а затем просто использует операцию put для записи в базу данных, а не последовательность get/put. И это заставило меня задуматься о том, что происходит, если этот массив содержится в свойстве одной из функций. Будет ли повторно использоваться распределение данных свойства функции при каждом новом вызове или оно будет занимать больше места каждый раз, пока не будут освобождены прежние вызовы?

Возможно, я думал, что даже когда переменные после того, как новые узлы построены, устанавливается в нуль, G C может все равно занять время для освобождения памяти, так что память всегда используется, и он может также содержать один пакет данных за раз и устранять необходимость в get и ожидание события onsuccess, чтобы обновить объект, а затем put вернуть его обратно.

Конечно, все это очень быстро работает с последовательностью get/put, но я бы хотел понять, что происходит с памятью; и если установка переменных на ноль и отсутствие удержания массива в ОЗУ действительно ничего не экономит, то нет смысла использовать get, и меньшая работа может снизить вероятность того, что после работы пользователя с этим инструментом в течение часа или двух будет проблема с памятью.

Спасибо за внимание к моему довольно новичку.


Спасибо за комментарии. Хотя они и интересны, они на самом деле не имеют отношения к тому, что я спрашиваю. Я не спрашиваю об утечках памяти, а только прокомментировал, что переменные устанавливаются в нуль при закрытии функций. Они установлены в нуль, потому что я прочитал, что если ссылки на область памяти «повреждены», это помогает алгоритму разметки и развертки G C определить, что конкретная область памяти может быть освобождена. И, если какой-либо тип ссылки на переменную останется, он будет по меньшей мере указывать на ноль, а не на область оставшихся данных. Правда это или нет, я точно не знаю; но это то, что я прочитал. Я прочитал много статей об утечках памяти, но эти три, статья 1 , статья 2 и статья 3 , я смог легко найти, чтобы привести примеры. В статье 3 на странице 5 показано, как установить для переменной значение null, чтобы защитить ее от утечек памяти, сделав объект недоступным.

Я не понимаю, почему этот вопрос можно считать микрооптимизацией. Это просто вопрос новичка о том, как используется память в браузере, когда происходит несколько вызовов функций между циклами G C. И это всего лишь пример того, что я изучал, и он не зависит ни от indexedDB, ни от того, существуют ли утечки памяти в правильно закодированных приложениях. Представленное мною описание, вероятно, приводило в замешательство.

Если функция использует локальные переменные для извлечения массива объектов данных из хранилища объектов indexedDB и в обработчике transaction.oncomplete передает ссылку на эту область памяти другой функции что использует его для создания фрагмента документа и замены узла DOM, что происходит с данными? Две функции имеют ссылку на массив и одну на фрагмент. Если ссылки будут разорваны вручную, установив переменные, которые указывали на них, в значение null (и даже если не установлено в значение null), в конечном итоге G C освободит эту память. Но если пользователь быстро щелкает, повторно вызывая эти функции в течение короткого промежутка времени, то есть между циклами G C, каждый вызов будет выделять новую область памяти для массива данных и фрагмента, так что между циклы G C, может ли быть десять наборов областей данных в ОЗУ, ожидающих передачи? Если массив содержится в свойстве функции, которая его извлекает, будет ли каждый вызов повторно использовать одну и ту же область памяти или свойство функции просто изменит свою ссылку на новую область памяти, содержащую новый массив и прерванную ссылку на область памяти, содержащая предыдущий массив, но между циклами G C все равно будет десять наборов областей данных?

Как я уже писал ранее, мне было интересно, есть ли способ повторно использовать та же область памяти для каждого вызова. Если это невозможно и если в ОЗУ всегда будет несколько наборов данных, ожидающих освобождения между циклами G C, может быть полезно сохранить ссылку на текущий набор данных и использовать ее для уменьшения объема работы, выполняемой браузер, чтобы сохранить текущее состояние, которое само по себе является отдельным вопросом, который зависит от того, как память используется браузером.

Когда я наблюдаю снимки памяти в Firefox разработчику инструменты, использование памяти растет, когда я перебираю эти наборы данных, многократно извлекаю новые данные и строю новый фрагмент для замены узла DOM; но объем этих данных относительно невелик и может накапливаться до тех пор, пока не будет запущен цикл G C. Из этого наблюдения видно, что каждый вызов использует новую область данных и прерывает ссылку на предыдущую область данных. Следовательно, сохранение ссылки на текущий набор данных не является проблемой памяти, поскольку в ОЗУ всегда остается много таких областей памяти между циклами G C.

Тем не менее у меня должна быть проблема с некоторыми сортировать, потому что после добавления 100 пакетов данных и перемещения вверх и вниз по ним с помощью кнопок Next / Previous, использование данных продолжает расти и почти все в разделе domNode. Он начинается с общего объема 7 МБ, 6 МБ в domNode и 5 МБ в #document. #document остается на 5 МБ, но domNode увеличивается как минимум до 150 МБ, так как ничего не делает, кроме как перемещается вверх и вниз по записям, извлекает данные, строит и заменяет узлы, но никогда не редактирует данные; и никогда не иметь более одного узла для него всегда замена одного и того же размера, потому что в этом тесте 100 пакетов данных являются идентичными копиями. Итак, просто getAll, создайте фрагмент, замените узел DOM, снова и снова.

Спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...