10. Что такое inlining и зачем нужен @inline?Теория

Дополнительные вопросы

1. Какие недостатки есть у inlining?

2. Почему @inline не ставят на каждую функцию?

Темы

Компании

Ответ

Inlining (инлайнинг) это подстановка тела функции на место вызова.

Обычно тело функции лежит отдельно в памяти программы. В месте вызова программа переходит к этому телу и потом возвращается.

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

Чтобы управлять этим в Swift, используют атрибуты:

  • @inlinable. Нужен, когда функцию объявили в другом модуле, например в пакете SPM, а вызываем у себя. Тело попадает в интерфейс модуля, и компилятор нашей программы может подставить его на место вызова.
  • @inline(__always). Просим компилятор использовать инлайнинг. Однако это не дает гарантии. Например, для рекурсивных функций и debug-сборок атрибут не сработает.
  • @inline(never). Явно запрещаем инлайнинг.

Дополнительные вопросы

1. Поскольку при компиляции тело функции копируется в места вызова, бинарный файл программы разрастается.

2. Компилятор и так инлайнит короткие функции, где это выгодно. @inline(__always) на всё раздует код.

Inlining подставляет тело функции в место вызова. Пропадает сам вызов, и компилятор оптимизирует уже общий код. @inline(__always) просит встроить всегда, @inline(never) запрещает. Это подсказки. Компилятор и без них встраивает маленькие функции, когда это выгодно.

Дополнительные вопросы

1. Раздувается код: одно тело копируется в каждый вызов. Растёт бинарь, хуже попадает в кэш инструкций, дольше сборка. По шагам отладчика такой код тоже читать труднее.

2. Крупную функцию встраивать вредно, а маленькую компилятор и так часто встроит. @inline(__always) на всех вызовах раздувает модуль. Публичный метод библиотеки через границу модуля часто нельзя встроить: у клиента нет тела.