Утечка памяти при извлечении JSON из WEB - PullRequest
2 голосов
/ 19 июля 2011

Я потратил несколько дней на это и ударил его со всех сторон, о которых я могу думать.Я работаю над простым гаджетом для Windows 7.Этот скрипт извлекает данные JSON с удаленного веб-сервера и помещает их на страницу.Я использую jQuery 1.6.2 для $ .getJSON.Скрипт занимает больше памяти в каждом цикле.

var count = 1;

$(document).ready(function () {
    updateView();
});

function updateView(){
    $("#junk").html(count);
    count++;
    $.getJSON( URL + "&callback=?", populateView);
    setTimeout( updateView, 1000 );
}

function populateView(status) {
    $("#debug").html(status.queue.mbleft + " MB Remaining<br>" + status.queue.mb + " MB Total");
}

Любая помощь будет принята с благодарностью .... Спасибо!

РЕДАКТИРОВАТЬ: Добавить образец данных JSON

?({"queue":{"active_lang":"en","paused":true,"session":"39ad74939e89e6408f98998adfbae1e2","restart_req":false,"power_options":true,"slots":[{"status":"Queued","index":0,"eta":"unknown","missing":0,"avg_age":"2d","script":"None","msgid":"","verbosity":"","mb":"8949.88","sizeleft":"976 MB","filename":"TestFile#1","priority":"Normal","cat":"*","mbleft":"975.75","timeleft":"0:00:00","percentage":"89","nzo_id":"-n3c6z","unpackopts":"3","size":"8.7 GB"}],"speed":"0  ","helpuri":"","size":"8.7 GB","uptime":"2d","refresh_rate":"","limit":0,"isverbose":false,"start":0,"version":"0.6.5","new_rel_url":"","diskspacetotal2":"931.51","color_scheme":"gold","diskspacetotal1":"931.51","nt":true,"status":"Paused","last_warning":"","have_warnings":"0","cache_art":"0","sizeleft":"976 MB","finishaction":null,"paused_all":false,"cache_size":"0 B","finish":0,"new_release":"","pause_int":"0","mbleft":"975.75","diskspace1":"668.52","scripts":[],"categories":["*"],"darwin":false,"timeleft":"0:00:00","mb":"8949.88","noofslots":1,"nbDetails":false,"eta":"unknown","quota":"","loadavg":"","cache_max":"0","kbpersec":"0.00","speedlimit":"","webdir":"","queue_details":"0","diskspace2":"668.52"}})

РЕДАКТИРОВАТЬ 2: Сокращенный код до этого, и он все еще течет.Я думаю, что это исключает обход DOM как участника.

$(document).ready(function () {
    setInterval(updateView, 1000);
});

function updateView(){
    $.getJSON( URL + "&callback=?", populateView);
}

function populateView(status) {
}

РЕДАКТИРОВАТЬ 3: Это не jQuery.Я удалил jQuery и сделал это с прямыми js.Все еще течет.

function init(){
    setInterval(updateView, 1000);
}

function updateView(){
    var xhr = new XMLHttpRequest();
    xhr.open("GET", URL, false);
    xhr.setRequestHeader( "If-Modified-Since", "0");
    xhr.send('');
}

Так что ... если это не JQuery, не только в IE (Chrome тоже).Какого черта?!Идеи?

Спасибо!

Ответы [ 3 ]

2 голосов
/ 19 июля 2011

У меня такое ощущение, что функция setTimeout в updateView вызывает такое поведение. Чтобы проверить это, вы можете изменить свой код на:

$(document).ready(function () {
   setInterval(updateView, 1000);
});

function updateView(){
    $("#junk").html(count);
    count++;
    $.getJSON( URL + "&callback=?", populateView);
}

function populateView(status) {
    $("#debug").html(status.queue.mbleft + " MB Remaining<br>" + status.queue.mb + " MB Total");
}

EDIT: функция setInterval будет выполнять переданную функцию снова и снова каждые х миллисекунд. Здесь до документов.

РЕДАКТИРОВАТЬ 2: Еще одна потеря производительности (хотя это может и не иметь решающего значения) заключается в том, что вы проходите DOM каждую секунду, чтобы найти элемент $('#debug'). Вы можете сохранить это и передать как:

        $(document).ready(function () {
            var debug = $('#debug'); 
            var junk = $('#junk')          ;
            setInterval(function(){updateView(debug, junk)}, 1000);

        });

        function updateView(debug, junk){
           junk.html(count);
            count++;
            $.getJSON( URL + "&callback=?", function(status){populateView(status,debug)});
        }

        function populateView(status) {
            debug.html(status.queue.mbleft + " MB Remaining<br>" + status.queue.mb + " MB Total");
        }

Редактировать 3: Я изменил код выше, потому что я забыл принять ответ от сервера. Предполагая, что queue является свойством возвращаемого JSON, код должен быть таким, как указано выше.

Редактировать 4: Это очень интересный вопрос. Другой подход тогда. Предположим тогда, что есть еще некоторые клиентские скрипты, которые забивают память. Что бы это могло быть? Насколько я понимаю, остались только две вещи - setInterval и функция $ .getJSON. Функция $ .getJSON представляет собой простую оболочку запроса ajax, которая запускает запрос и ожидает ответа от сервера. Функция setInterval более специфична, поскольку она устанавливает таймеры, функции запуска и т. Д.

Я думаю, что если вам удастся имитировать это на вашем сервере или даже просто обновлять эту веб-страницу в браузере каждую секунду / 5 секунд, вы сможете увидеть, обрабатывает ли ваш запрос клиент или сервер.

2 голосов
/ 19 июля 2011

Редактировать 2:

Если это действительно диспетчер задач, показывающий здесь утечку, то я думаю, что следующим шагом будет исследование IE, так как я считаю, что IE - это механизм, используемый для размещения виджетов Windows.

Если вы можете воссоздать ваш скрипт в небольшом html-файле, вы можете запустить этот инструмент и посмотреть, делает ли это IE:

http://blogs.msdn.com/b/gpde/archive/2009/08/03/javascript-memory-leak-detector-v2.aspx

Кроме того, вы используете IE8 или 9?


Edit:

На основе строки JSON в операторе; в основном проблема здесь вводит в заблуждение. размещенный фрагмент javascript работает отлично.

Сервер, производящий JSON, является тем, который показывает разницу в использовании памяти, я бы исследовал веб-сайт / конечную точку, которая создает этот JSON, и выяснил, в чем проблема.


Только что подумал,

$. GetJSON - это просто сокращенная функция для вызова $ .ajax в jQuery.

Интересно, изменится ли он, если вы измените свой код на использование $ .ajax, но добавите к нему механизм кэширования:

$.ajax({
  url: URL + "&callback=?",
  dataType: 'json',
  cache: false,
  success: populateView
});

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

0 голосов
/ 02 октября 2012

Нашел этот поток, пытаясь найти основную причину этой проблемы, потому что у меня недавно была похожая проблема, хотя моя память увеличивалась примерно на 1 МБ в минуту ... Я в значительной степени изолировал ее от анализа json. Запустите команду ajax с типом: 'text', и вы должны увидеть, что память очищена.

Я нашел библиотеку json_parse.js , которая рекурсивно анализирует данные json с использованием механизма JS (не eval). Я вручную анализирую текстовые данные в json при успешном обратном вызове, и это хорошо работает.

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