Поиск утечек памяти в Chrome 66 стал гораздо удобней. DevTools теперь могут проводить трассировку, делать снапшоты DOM-объектов из C++, отображать все доступные DOM-объекты из JavaScript вместе со ссылками на них. Появление этих возможностей стало следствием нового механизма трассировки C++ в сборщике мусора V8. Напомню, что стабильный Chrome сейчас (20.03.2018) имеет версию 65, поэтому чтобы подивиться на фичу, придётся установить одну из нестабильных сборок (например, Beta имеет версию 66, а Dev и Canary — 67). Утечки памяти в сборке мусора возникают, когда ненужный уже объект не собирается из-за неумышленно добавленных ссылок из других объектов. Утечки памяти в веб-страницах зачастую возникают при взаимодействии JS-объектов и DOM-элементов. Давайте посмотрим на игрушечный пример, показывающий утечку, возникающую, когда программист забывает убрать обработчик события. Обработчик ссылается на объекты, и их больше уже нельзя удалить. В частности, протекает окно iframe. Что ещё хуже, утекший iframe поддерживает живыми все свои JS-объекты. Чтобы найти причину утечки, важно осознать понятие подвешенного пути (retaining path). Подвешенный путь — это цепочка объектов, которые мешают сборке утекающего объекта. Цепочка начинается от какого-то корневого объекта, вроде глобального объекта основного окна. Цепь заканчивается утекающим объектом. Все промежуточные объекты имеют прямую ссылку на следующий объект в цепи. Например, подвешенный путь объекта Leak и этом ифрейме выглядит следующим образом:  Заметьте, что подвешенный путь проходит сквозь границу между JavaScript и DOM (они отмечены, соответственно, зелёным и красным цветом) целых два раза. JS-объекты живут в куче V8, а объекты DOM являются C++-объектами в Chrome.  Теперь мы можем изучить подвешенный путь любого выбранного объекта с помощью снапшота кучи. При этом будут сохранены в точности все объекты, находящиеся в куче V8. Совсем недавно там хранились только очень примерные данные о C++ DOM объектах. Например, Chrome 65 показывает неполный подвешенный путь для объекта Leak из предыдущего игрушечного примера:  Только первая строка достаточно точна: объект Leak действительно хранится в global_variable в окне ифрейма. Все остальные строки пытаются аппроксимировать настоящий путь, и это делает отладку утечки памяти весьма сложной. Начиная с Chrome 66, DevTools трассирует C++ DOM объекты, и точно захватывает объекты и ссылки между ними. Эта фича основана на новом мощном механизме трассировки C++ объектов, который создавался для кросс-компонентной сборки мусора. В резульатате, пути в DevTools стали правильными! 
 Файл для экспериментов: https://ulan.github.io/misc/leak.html DOM-объекты управляются с помощью Blink — движка рендеринга, используемого в Chrome, отвечающего за трансляцию DOM в реальный текст и картинки на экране. Blink и его внутреняя реализация DOM написаны на C++ — и это значит, что DOM нельзя напрямую отразить в JavaScript. Вместо этого, объекты в DOM как бы делятся на две части: доступную из JS объект-обёртку, и C++-объект, являющийся представлением узла из DOM. Эти объекты содержат прямые ссылки друг на друга. Определение времени жизни и области владения компонентов, которые пересекают границы нескольких систем, в данном случае — Blink и V8, — довольно сложная задача, поскольку в ней частвуют стороны, которым нужно предварительно договориться, какие компоненты всё ещё живы, а какие стоило бы утилизировать. В Chrome 56 и более старых версиях (например, до марта 2017), Chrome использовал механизм, называемый группировкой объектов (object grouping). Объекты связываются в одну группу, если принадлежат одному и тому же документу. Группа, и все её объекты, держатся живыми до тех пор, пока существует хоть один живой объект на конце другого подвешенного пути. Это имеет смысл в контексте узлов DOM, которые всегда связаны с содержащими их документами, формируя так называемые DOM-деревья. Но эта абстракция теряет все реальные подвешенные пути, что раньше очень осложняло отладку. Как только объекты переставали подходить под вышеописанный сценарий (например, замыкания в JavaScript, используемые как обработчики событий), реализовывать этот подход становилось затруднительно и приводило к багам, в которых JS-обёртки собирались раньше времени, что в свою очередь вело к их замене на пустые JS-обёртки с полной потерей всех свойств. Начиная с Chrome 57, этот подход заменён на "кросс-компонентную трассировку" — механизм, который определяет живость объектов, трассируя их от JavaScript вплоть до C++ реализации в DOM, и по тому же пути назад. На стороне C++ реализована инкрементальная трассировка, которая создаёт write barriers для того, чтобы не скатиться в stop-the-world. Кросс-компонентное тестирование не только улучшает латентность, но и лучше аппроксимирует живость объектов на границе компонентов, и чинит несколько часто случающихся сценариев, которые раньше приводили к утечкам. Кроме того, благодаря этому, DevTools получили возможность делать снапшоты, которые действительно отражают состояние DOM. Деврел Axiom JDK, продюсер в Failover Bar