Почему этот код потребляет память, и он не восстанавливается полностью? - PullRequest
3 голосов
/ 14 апреля 2011

У меня есть простой код JavaScript, который потребляет память при бесконечной работе.Потребление памяти контролируется профилировщиком внутренней памяти Google Chrome.

  setInterval(function(){
     var xhr = new XMLHttpRequest();
     xhr.open('GET', 'json.txt', true);
     xhr.onreadystatechange = function() {
        if(this.readyState == 4 && this.status == 200) {
           console.log(this.responseText);
        }
     };
     xhr.send('');
  }, 500);

HTML-файл с примером кода выше и json.txt размещен на моем локальном сервере, получение файла занимает не более 500 мс (этовсегда около 7-10 мс).

В долгосрочной перспективе график памяти выглядит так: Initial memory consumption graph

РЕДАКТИРОВАТЬ Такое же окно Chrome через часработа Graph after a hour of work

РЕДАКТИРОВАНИЕ В долгосрочной перспективе (часы) не вся память восстановлена, график все еще возрастает.Я понимаю почему память используется, я не понимаю, почему она не полностью восстановлена ​​.

РЕДАКТИРОВАТЬ Вот как я могууменьшить утечку памяти

  var callback = function(){
      if(this.readyState == 4 && this.status == 200) {
          console.log(this.responseText);
      }
  } 

  setInterval(function(){
     var xhr = new XMLHttpRequest();
     xhr.open('GET', 'json.txt', true);
     xhr.onreadystatechange = callback;
     xhr.send('');
  }, 500);

Это улучшение позволяет не связывать закрытие обратного вызова с xhr вар.

Ответы [ 5 ]

6 голосов
/ 14 апреля 2011

Для одного вы многократно загружаете содержимое json.txt, для чего потребуется немного памяти.Кроме того, самому XHR также может понадобиться память.Однако я не вижу в этом особой проблемы, так как память, похоже, все равно восстанавливается.

0 голосов
/ 20 апреля 2011

Я полагаю, этот интервал не устанавливается в вакууме. Функция, которую вы передаете в setInterval, может иметь доступ к лексической области, в которой она была определена. Это означает, что каждая переменная вокруг нее всегда будет доступна в глазах сборщика мусора, даже если вы не используете эти переменные внутри функции. Сборщик мусора никогда не очистит его. Возможно, было бы лучше определить функцию в более санитарной среде, где она не будет иметь закрытого доступа к любым переменным большого размера.

РЕДАКТИРОВАТЬ : Извините, я постараюсь прояснить себя. Это не имеет ничего общего с XHR - вы можете поместить что-нибудь (или даже ничего) в эту функцию setInterval, и она все равно будет утечка, если в ее лексической области видимости есть переменные, которые вы хотите очистить. Вам просто нужно убедиться, что функция setInterval не имеет закрытого доступа ни к каким переменным, которые вы хотите очистить. Например:

(function() {
  var a = readFile('a-very-big-file.txt');

  setInterval(function() {
    console.log('im leaking!');
  }, 500);
})();

Это будет течь. Несмотря на то, что setInterval не делает ничего особенно значимого, он все еще имеет доступ к «a», и сборщик мусора считает его достижимым.

0 голосов
/ 19 апреля 2011

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

0 голосов
/ 14 апреля 2011

Если цикл запрос-ответ занимает больше времени, чем указанный интервал, безусловно, будут некоторые накладные расходы памяти.

Поскольку память будет освобождена только после завершения запроса (Успех или Ошибка).

0 голосов
/ 14 апреля 2011

Почему бы и нет?По крайней мере, var xhr = new XMLHttpRequest ();должен потреблять память на каждой итерации и собираться GC (возможно, это видно на вашем графике).

...