Chrome не может освободить память, сборка мусора происходит не так, как ожидалось (библиотека Mootools / MochaUI) - PullRequest
26 голосов
/ 31 октября 2010

Справочная информация : В настоящее время я работаю на сайте интрасети, который использует библиотеку MochaUI (работает с демонстрационной программой виртуального рабочего стола ). Я использую Mootools 1.2.4 и MochaUI 0.9.7. Окна, которые открываются в моей реализации «виртуального рабочего стола», загружают свой контент через фреймы. Некоторые из загруженных страниц довольно трудоемки с точки зрения CSS и сценариев, поэтому важно, чтобы объекты Window собирались надлежащим образом, когда пользователь закрывает окно. Якобы об этом позаботится библиотека (она делает хорошую работу при использовании Firefox).

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

Вот основные моменты:

  1. Хром обманывает, как это:

    • Chrome не может освободить память, выделенную для объектов окна MochaUI, когда они закрыты. Вместо этого использование памяти Chrome останавливается (буквально) на уровне, достигнутом после того, как окно завершило загрузку содержимого iframe, устанавливая нижнюю границу использования памяти до тех пор, пока страница не будет обновлена.
    • Память, используемая процессом, продолжает увеличиваться с последующими открытиями / закрытиями окон. В конце концов, достигается некоторый тип ограничения, и использование памяти перестает расти как круто / начинает колебаться вместо резкого скачка.
    • Эта проблема наиболее очевидна, когда рассматриваемые окна загружают довольно большой (с точки зрения памяти) контент iframe. Окно, которое я использую для всех целей тестирования, загружает страницу 580 КБ (без кэширования) в свой iframe.
  2. Как ни странно, ожидаемая сборка мусора происходит , когда

    • браузер впоследствии свернут
    • другая вкладка открывается в том же окне браузера
    • временная шкала памяти записывается в Developer Tools. (комедийный вариант)
    • Предлагает ли такое поведение какие-либо возможные подходы к решению # 1?

Ответы [ 2 ]

6 голосов
/ 31 октября 2010

Я не уверен, было ли это проверено в Windows, но если это так, имейте в виду, что всякий раз, когда вы минимизируете окно в окне, оно перемещает все данные в файл подкачки.При повторном открытии окна оно не будет перемещать блоки памяти назад, пока программа не попытается получить к ним доступ, и, таким образом, любой мусор останется в файле подкачки, но фактически не будет собран.

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

см. Следующий URL для получения дополнительной информации

https://micksmix.wordpress.com/2010/01/08/why-does-task-manager-show-an-applications-memory-usage-drop-after-minimizing-it-to-the-the-taskbar/

3 голосов
/ 02 ноября 2010

Обновление
Следующие изменения в функции ClochaJobs в MochaUI представляют собой большое улучшение по сравнению с тем, что я ранее разместил здесь.Основное изменение теперь заключается в том, что событие onraload iframe вызывается вручную, изменяя свойство src, а не вызывается, когда метод windowEl.destroy удаляет iframe из DOM.(идея пришла из здесь ).

Если вы хотите использовать этот код, просто удалите существующую функцию закрытияJobs и скопируйте и вставьте этот код на его место.Он должен работать с 0,9,7 и 0,9,8 MochaUI, а также с Mootools 1.2.4 или 1.3.


closingJobs: function(windowEl){        
    windowEl.setStyle('visibility', 'hidden');
    var instances = MUI.Windows.instances;
    var instance_id = windowEl.id   
    var cleanup_delay = 50;

  /*
  Reset canvases with width/height = 0.
  This pretty reliably frees a few hundred Kb of
  memory in chrome.
  */        
    instances[instance_id].canvasControlsEl.width = 0;
    instances[instance_id].canvasControlsEl.height = 0; 
    instances[instance_id].canvasEl.width = 0;
    instances[instance_id].canvasEl.height = 0;         

    if(instances[instance_id].options.loadMethod == 'iframe')
    {
 /*
 The following line determines how long to delay the execution of
 the windowEl.destroy function. The line below gives 10 milliseconds 
 per DOM element in the iframe's document.
 You could probably do just as well with a hard-coded value.
 */         
        cleanup_delay = instances[instance_id].iframeEl.contentDocument.getElementsByTagName("*").length * 10;              

 /*
 Set the Browser property in the iframe's window to Internet Explorer.
 This causes Mootools to run its purge function, which iterates over
 all the iframe document's DOM elements, removing events/attributes etc.
 Assuming you have mootools included in the iframe content.     
 */
        if(instances[instance_id].iframeEl.contentDocument.defaultView.MooTools)
        {           
            if(instances[instance_id].iframeEl.contentDocument.defaultView.MooTools.version.contains("1.3"))                
                instances[instance_id].iframeEl.contentDocument.defaultView.Browser.ie = true;
            else        
                instances[instance_id].iframeEl.contentDocument.defaultView.Browser.Engine.trident = true;
        }                   

        instances[instance_id].iframeEl.src = "javascript:false";
    }       

    MUI.cleanWindow.delay(cleanup_delay, null, windowEl);       
},  

cleanWindow: function(windowEl)
{                               
    var instances = MUI.Windows.instances;
    var instance_id = windowEl.id
    if (Browser.ie){
        windowEl.dispose();
    }
    else {
        windowEl.destroy();
    }       
    instances[instance_id].fireEvent('onCloseComplete');

 /*
 Changed - Only execute getWindowWithHighestZindex() and focusWindow() 
 functions if there will actually be open windows after the 
 current one closes.
 */
    if (instances[instance_id].options.type != 'notification' && instances.__count__ > 1){
        var newFocus = MUI.getWindowWithHighestZindex();
        MUI.focusWindow(newFocus);
    }       
    if (this.loadingWorkspace) this.windowUnload();
    if (MUI.Dock && $(MUI.options.dock) && instances[instance_id].options.type == 'window'){
        var currentButton = $(instances[instance_id].options.id + '_dockTab');
        if (currentButton != null){
            MUI.Dock.dockSortables.removeItems(currentButton).destroy();
            currentButton = null; //Is this necessary?
        }           
        MUI.Desktop.setDesktopSize();
    }

    //Changed - moved this to the end of the function.
    delete instances[instance_id];  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...