Pull to refresh

Comments 16

Странно, что локальные данные проблемной функции не занулялись после изменения ESP. Нелогично же. Или опять проблема в производительности, и зануление стека тупо отключили ради пары fps?
Да нет, это обычное поведение Си =) С самого начала же учат, что в только что созданной переменной находится мусор (возможно оставленный предыдущей функцией).

А так да, ради производительности. А точнее ради того, чтобы не платить за то, что не используешь. Все-таки случай приведенный в статье (когда мы анализируем данные со стека на наличие потенциальных указателей) — довольно редкий.
Привык я к нулям в локальных переменных в Турбо-Паскале 6.0, видимо. :)

Имхо всё же, если ты не собираешься использовать столько локальных переменных, незачем выделять место на стеке. Так или иначе, stack trace сейчас довольно штатная процедура, и пусть обычно она не лазает в локальные данные, но если сделан, скажем, минидамп, и туда попало что-то не то, это непорядок.
С самого начала же учат, что в только что созданной переменной находится мусор


Только если она не статическая.

Вообще можно добавить в clang какую-нибудь опцию, чтобы занулять на выходе из функции (или после последнего использования) стековые указатели, и компилировать с ней файлы, обрабатываемые GC. Или даже не все указатели, а только те, которые вообще могут собираться GC. Падение производительности будет минимальным.
С другой стороны, в нормальных условиях текущее поведение приводит к мизерной пессимизации GC (не собрали свежесдохший объект — соберем в следующий раз, проблем-то), так что решение разработчиков о таком tradeoff совершенно понятно

Не совсем понял почему esp двигается вниз на 0B8h. Это как раз из-за этого макроса VLOG? Он выделяет память и не использует его?
Предполагаю, что под макрос VLOG память в стеке выделяется всегда, но используется она лишь тогда, когда логгирование включено в рантайме. Поэтому включение логгирования тоже лечило эту проблему.
Вроде весь рассказ нить повествования не ускользала от меня, но переход от макроса VLOG к изменению esp я совершенно не уловил. Можно больше подробностей?
Также приведите, пожалуйста, ссылку на коммит в хромиум.
Разворачивание макроса VLOG подразумевает создание временных объектов, под которые требуется память в стеке. Эта память резервируется в начале функции путем уменьшения значения регистра esp на нужную величину.
Мы обсуждали эту ситуацию с разработчиками Chromium, однако изменения в Chromium вносить не стали, поскольку данная проблема — следствие консервативного сканирования стека и «удачного» стечения обстоятельств, у нее нет системного решения. Мы нарвались на эту проблему случайно в одном конкретном тесте, сильно нагружающем GC.
А можно внести в VLOG изменения, что если логирование отключено, переменные, под которые выделена память, заполняются нулями? Должно хватить, по логике.
тогда при его активном использовании и отключенном логировании можно схватить некоторую деградацию производительности на заполнении памяти
А насколько большую, если заполняться будет полу-нативно, скажем, через rep stosX, в результате отработки оптимизатора? Кроме того, насколько «активное использование» предусматривается в этой фразе? Не является ли она примером слишком ранней оптимизации? :) Хотя немного посмотрел, что это за VLOG такой — сдается мне, править надо не сам VLOG, а модуль логирования, а это может влиять на большее число мест, чем те, где используется именно VLOG. Да ещё эта проблема с разворачиванием макросов в препроцессинге, неясно в итоге, во что развернулся конкретный вызов макроса от макроса от макроса, и посмотреть бывает негде (правда, это воспоминания от работы с cc в универе 20-летней давности, может, сейчас и есть возможность развернуть макрос в конкретном месте и посмотреть, что за код получается). За это, собственно, я макросы и не любил — отлаживать неудобно.

То есть официально в Blink такой GC, который может недочищать память? Получается он на эвристиках?

Это зависит от ситуации, в которой происходит сбор мусора. Если в стеке нет ссылок на GC-объекты (например, в начале очередного цикла лупера главного потока) — тогда GC гарантированно соберет весь мусор. Когда в стеке могут быть ссылки на GC-объекты (например, если понадобилось освободить память для создания нового объекта), коллектор вынужден трактовать все похожие на ссылки значения как ссылки: иначе он может пропустить настоящую ссылку и удалить объект, не являющийся мусором.

Так вы сделали PR в Chromium? Разработчики обещали это поправить?

Выше уже отвечали:


«Мы обсуждали эту ситуацию с разработчиками Chromium, однако изменения в Chromium вносить не стали, поскольку данная проблема — следствие консервативного сканирования стека и «удачного» стечения обстоятельств, у нее нет системного решения.»

Sign up to leave a comment.