пытаемся ускорить выделение памяти

Только технические вопросы по ЯОС и MINOS. Терминология и прочее - в других форумах.
Ответить
БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

пытаемся ускорить выделение памяти

Сообщение БудДен » 01.07.21 12:34

Профайлер (под Win32) показал, что бОльшую часть времени ЯОС занимается ленивым подметанием (LazySweep). Пытаемся для начала понять,
какую статистику можно собрать об этом процессе, например, посчитать количество актов выделения памяти, количество сборок мусора, количество действий по поиску нужного блока.

Аватара пользователя
Лис [Вежливый]
Сообщения: 561
Зарегистрирован: 08.10.18 13:32

Re: пытаемся ускорить выделение памяти

Сообщение Лис [Вежливый] » 01.07.21 12:53

Скорость выделения в правильных GC не зависит от скорости сборки.
А скорость сборки ограничена сверху и не должна превышать 50% всей вычислительной мощности.
Какой тогда смысл экономить электричество?

Тут одно из двух, либо что-то неясно, либо GC неправильный.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: пытаемся ускорить выделение памяти

Сообщение БудДен » 01.07.21 13:57

https://gitlab.com/budden/ja-o-s/-/blob ... s.Mod#L844 - там ленивое подметание, поэтому зависит.
Но дело оказалось не в том, а тупо в том, что при замере длины литеры UCS32 (а в ЯОС используются нуль-терминированные строки, это ужасно, но переделывать, очевидно, нет ресурсов) на каждую литеру UCS32 вызывалась функция.
Стоило убрать вызов - поиск ускорился сразу в 10 раз.

Профайлер промахивается и показывал узкое место не там, где надо.

Хотя ускорения в 10 раз недостаточно, нужно в 100.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: пытаемся ускорить выделение памяти

Сообщение БудДен » 01.07.21 15:25

Действовал по мотивам https://forum.oberoncore.ru/viewtopic.p ... 6&p=112980, где сказано, что для просмотра сведений о куче нужно запустить WMPerfMonPluginHeap.Install ~ и посмотреть в Системное меню->Диагностика->Производительность->Plugins

Там я смотрел на скорость выделения блоков в секунду, на общий объём выделенных блоков и их распределение по размерам.

Было две версии:

- дело в блокировках, которые нужно захватить при каждом выделении - в этом случае должна быть абсолютно ограничено к-во выделений в секунду, причём независимо от размера кучи
- дело в большом общем количестве блоков, что замедляет LazySweep (как перевести - ленивое подметание?) - в этом случае скрость должна была падать по мере роста кучи

Путём запуска тяжёлых задач, таких, как компиляция многих файлов или открытие среды разработки со многими вкладками, я убедился, что обе гипотезы не выдерживают критики. Тогда я заподозрил, что профайлер "мажет" и показывает места, соседние с узкими. Я стал искать, что он ещё показывает, и убедился, что он недоволен функцией UCSStrings32.Substring и UCSStrings32.Length. Тут я последовательно обнаружил и вычистил две вещи:

- при измерении длины строки UCS32 на каждую литеру UCS32 вызывается функция - это я заменил на обращение к полю записи, и поиск ускорился в 10 раз.
- в функции Substring исключительно для проверки корректности выходных параметров измеряется длина строки. А мы выкусываем лексемы прямо из
файла целиком, поэтому эта строка является длинной. Здесь я сделал версию ф-ии substring, которая не меряет длину строки, и поиск ускорился ещё раз в 5.

БудДен
Сообщения: 2839
Зарегистрирован: 07.10.18 14:01

Re: пытаемся ускорить выделение памяти

Сообщение БудДен » 01.07.21 15:43

В итоге теперь поиск по всем исходникам занимает порядка 30 секунд (а VS Code делает такой поиск практически мгновенно). А изначально только по одному файлу искало 30 секунд, а файлов 700. Если так считать, то может быть, что поиск ускорился не в 50 раз, а в 500, но суть не в том, а в том, что всё равно 30 секунд - это кажется слишком долго.

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

Собственно говоря, один из вариантов ускорения состоит в том, чтобы реализовать "срезы массивов" как в Go, тогда нагрузку на кучу можно снизить. Например, вместо того, чтобы создавать строчки в лексемах, можно брать срезы. Хотя тогда нужно и сами лексемы хранить в виде массива, а не массива указателей, а здесь мы упрёмся в ограничения языка, т.к. у нас контейнер реализован на массиве указателей, а без дженериков придётся вручную реализовывать контейнер на массиве записей.

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

Ответить