14

Взгляните на этой части кучи снимки Chrome:Chrome/V8 не мусор собирает круговую ссылку?

Chrome circular reference

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

«Самый короткий» путь к корню - это, в конце концов, циклический путь (он никогда не достигает корня). Что заставляет задуматься, как средство просмотра снимков даже может назначить ему расстояние до 12? Это просто количество шагов, которые потребовались в цикле, прежде чем сдаться? Обратите внимание, как расстояние никогда не становится ниже 11.

Я читал, что для очистки подграфов с круговыми ссылками может потребоваться несколько итераций. Но повторные принудительные коллекции (с кнопкой корзины на вкладке Timeline) не смогли очистить эти объекты.

Обратите внимание, что поиск по ссылкам «185» в конечном итоге приводит к тому же system/Context @862399, поэтому на самом деле нет пути от корня к этому объекту (по крайней мере, здесь не видно).

Я схожу с ума, или сборщик мусора действительно сломан? Я не помню, чтобы эта проблема была в прошлом. Я нахожусь в Chrome 45.0.2454.101. Бета 46.0.2490.64 ведет себя одинаково.

+0

Являются ли эти методы даже способными собирать мусор? Вы создаете закрытие? Не могли бы вы случайно создать утечку памяти? – Jesse

+0

В [Руководстве по стилю JavaScript JavaScript] (https://google.github.io/styleguide/javascriptguide.xml?showone=Closures#Closures) приведен пример закрытия, который создает циклическую ссылку, приводящую к утечке памяти. Если это относится к OP, то это ничего нового: [1] (http://stackoverflow.com/questions/19550253), [2] (http://stackoverflow.com/questions/16442201), [3 ] (http://stackoverflow.com/questions/11186750). Не знаю, почему, но современные двигатели JS, похоже, не имеют решения для решения этого очень распространенного источника утечек памяти. –

+0

@ GOTO0 Я знаю, что замыкание содержит ссылки на охватывающие переменные, которые он использует (как он мог функционировать иначе?), Но что он также сохраняет неиспользуемые закрывающие переменные, для меня новичок, и на самом деле довольно разочаровывает. Однако в этом руководстве по стилю говорится «круговая ссылка и, следовательно, утечка памяти». Разве это не устаревшее утверждение, которое применяется только к счетчику GC? Я думал, что марка-и-sweep должна была сделать это без проблем? И если эта часть неверна, остальная часть этого руководства заслуживает доверия? –

ответ

1

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

Как вы, кажется, уже знаете, чтобы «очистить», Javascript не хочет больше ссылок на элемент, который хочет быть освобожденным.

Простой пример:

// Currently not eligible for garbage 
var myObj = { 
    data : 'test' 
}; 

// Reference data inside myObj 
// A unique identifier to myObj.data now exists 
var myData = myObj.data; 

// Whoops 
myObj = 'something else'; 

// Because myData exists, so does data and can not be freed either, understandable 
// This sounds simple and logical but most do not understand what is happening in the engine 
// A relationship has been born between 'myData' and 'data' and as long as it exists, it is not eligible for garbage and remains in memory 
console.log(myData); 

Ваш код, вероятно, более сложным, чем это, но это могло бы помочь объяснить, как, где, мусор не может быть собрана как цепочка областей видимости может следовать до ссылки.

Рассмотрим следующий

function oops(text){ 

    function doStuff(){ 
     return text.toLowerCase(); 
    } 
    return doStuff(); 
} 

// 'doStuff' stays alive thanks to 'test' below. 
var test = oops('closure'); 

doStuff функция не будет собран сборщиком мусора, так как он ссылается test.

// You can see where this is headed. We have 2 references to the same 'doStuff' function object with separate unique identifiers now below. 
var test2 = oops('closures...'); 

// This is now another unique identifier to 'doStuff' 
var test3 = test2; 

// doStuff survives yet still 
test = 0; 
test2 = 0; 

// Now we let the function object of 'doStuff' be freed because there is no longer any references to it 
test3 = 0; 

Это по существу утечка памяти, которую мы создали. Каждый раз, когда вы вызываете oops, вы создаете объект функции doStuff с уникальным идентификатором.

Способ избежать этого может быть

function doStuff(text){ 
    return text.toLowerCase(); 
} 

function oops(text){ 
    return doStuff(); 
} 

var test = oops('closure'); 

Теперь у нас нет никаких утечек памяти. doStuff был был использован и не создано.

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

Если вы возитесь с элементами, и я думаю, что вы можете быть, IBM has a good article about circular references, вы можете взглянуть на них.


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

+0

Спасибо за ваш ответ , но, как отмечалось выше, я уже знал о сохраняющейся силе закрытия, хотя, видимо, не полностью. Тем не менее, если значения в моем снимке кучи достижимы из корня GC, почему нет полного пути, показываемого с уменьшением расстояния до 1? Означает ли это, что средство просмотра снимков на самом деле не заслуживает доверия? И, как сказано в этом вопросе, я не испытывал этой проблемы в прошлом (хотя трудно сказать, изменилось ли изменение в приложении или Chrome). –

+0

Я попытался воспроизвести проблему в примере кода, но не удалось. Следует сказать, что реальное приложение, в котором оно встречается, довольно велико, являясь значимой одностраничной игрой.Его использование памяти (до утечек) может достигать нескольких сотен мегабайт. Я не знаю, готов ли браузер к этому еще? –

+0

Уверенный человек, браузеры могут обрабатывать несколько сотен мегаграмм, если использование памяти оправдано, но чем больше памяти, тем выше латентность. Если я могу что-то порекомендовать. Сделайте снимок, немного используйте свое приложение и возьмите другое и сравните. С элементами dom вы можете найти места для оптимизации, как это сделал человек в этой статье: https://blog.newrelic.com/2012/07/17/using-chrome-developer-tools-to-find-memory-leaks/ – Jesse