Как-то раз мне понадобилось реализовать промежуточный слой для трансляции событий из объектов C++ в процедуры скриптового языка 1С. Реализовал. С большим количеством шаблонов и с применением Буста. В результате, генерация события в C++ выглядит как обычный вызов функции. Проходя через транслятор событий, событие превращается в вызов процедуры модуля 1С, в которую передается автоматически сформированный массив объектов CValue. Все замечательно, но возникла проблема: без добавления функционала конечный dll-модуль Йокселя вырос на 700K. Было 2.8 Мб, а стало 3.5 Мб. Более того, добавление одного контекст-класса (объекта языка 1С) стало приводить к увеличению модуля на 100К. Естественно, меня не может это устроить – я собираюсь добавить целый ряд объектов 1С.
Изучение asm-кода показало, что основным виновником распухания можно считать компилятор Intel C++. Этот компилятор просто помешан на инлайне. Он просто инлайнит все, что шевелится, причем по самые помидоры. Я сначала подумал, что это я виноват – раз включил инлайнинг «всего, что возможно» в настройках. Но нет – переключение опции инлайна с Any suitable на Only inline ни к чему не привело. Проблема инлайна еще усугубляется тем, что в большинстве функций, реализующих контекст-обертку, используется статическая переменная. В результате компилятор создает кучу совершенно одинаковых функций, которые различаются только используемым адресом статической переменной. Поэтому линкер не может выкинуть дубликаты – функции одинаковые, но «все-таки разные».
В результате основной задачей стало «усмирение» компилятора – уменьшение инлайнинга. Другой задачей стал вынос нешаблонного кода из шаблонных классов – чтобы при инстанцировании шаблонов нешаблонный код не копировался каждый раз. Итак, проведенные мероприятия:
а стало:
Как ни странно, такое описание функции все же оказывает влияние на IC++. Но только для определенного размера функции – мелкие, по его мнению, функции компилятор все равно инлайнит. В моем случае эффект не слишком большой, но все же довольно заметный – отключился инлайн одной весьма здоровой функции, что дало возможность поработать линкеру.
Общий итог всех манипуляций. Изначально у нас было 2.8 Мб. После добавления событий стало 3.5 Мб. После усмирения компилятора стало 2.7 Мб. По моему, неплохо.
Кстати:
Ссылок на эту страницу нет