Коли слід використовувати inline в Rust?


85

Іржа має вбудований атрибут, який можна використовувати в одному з цих трьох ароматів:

#[inline]

#[inline(always)]

#[inline(never)]

Коли їх слід застосовувати?

У посиланні Rust ми бачимо розділ вбудованих атрибутів, в якому сказано

Компілятор автоматично вбудовує функції на основі внутрішньої евристики. Неправильно вбудовані функції можуть насправді зробити програму повільнішою, тому їй слід користуватися обережно.

На форумі Rust internals Huon також був консервативним щодо вказівки вбудованого .

Але ми бачимо значне використання джерела Rust, включаючи стандартну бібліотеку. Багато вбудованих атрибутів додаються до однорядкових функцій, що компіляторам повинно бути легко визначити та оптимізувати за допомогою евристики відповідно до посилання. Вони насправді не потрібні?

Відповіді:


69

Одне обмеження поточного компілятора Rust полягає в тому, що якщо ви не використовуєте LTO (Оптимізація часу зв'язку), він ніколи не вбудує функцію, не позначену #[inline] в ящиках. Rust використовує окрему модель компіляції, подібну до C ++, оскільки реалізація LTO LLVM погано масштабується для великих проектів. Отже, невеликі функції, що піддаються дії інших ящиків, потрібно позначати вручну. Це не є чудовою ситуацією, і це, мабуть, буде виправлено в майбутньому за допомогою деякої комбінації вдосконалень LTO та MIR.

#[inline(never)]іноді корисний для налагодження (відокремлення фрагмента коду, який не працює належним чином). Теоретично його можна використовувати для порівняльного тестування, але це, як правило, погана ідея: вимкнення вставки не заважає іншим міжпроцедурним оптимізаціям, таким як постійне розповсюдження. Що стосується звичайного коду, це може зменшити розмір коду, якщо у вас є часто використовувана допоміжна функція, яка використовується лише для обробки помилок.

#[inline(always)]загалом погана ідея; якщо функція достатньо велика, щоб компілятор не вбудовував її за замовчуванням, вона досить велика, щоб накладні витрати на виклик не мали значення (а надмірне вбудовування збільшує тиск кешу інструкцій). Є винятки, але для обґрунтування вам потрібні виміри продуктивності. Цей приклад - це ситуація, коли варто розглянути. #[inline(always)]також можна використовувати для поліпшення -O0якості коду, але це зазвичай не варто турбуватися.


19
зауважте, що inline(never)використовується на властивостях паніки, щоб переконатися, що оптимізатор не вбудовує функції, які викликаються лише у випадку паніки.
oli_obk

4
-1, бо до першого пункту чогось не вистачає. Загальні елементи можна вставляти в ящики, оскільки вони ефективно компілюються, коли створюються екземпляри, тому код, необхідний для вставки, легко доступний. А це означає, що величезна кількість таких предметів, які не позначені, все ще може бути вкладене в поперечний ящик. У деяких видах основних бібліотечних ящиків кожен предмет є загальним!
bluss
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.