Недавно столкнулся с кодом, в ряде мест которого очень интенсивно используется inline. Код критичен к скорости.
Очень широко используются такие конструкции:
практически все функции рассматриваемого кода небольшого размера и описаны непосредственно по месту объявления, т.е. в теле описания класса.
Код рассчитан на Desktop-приложения (Mac, Linux, Windows) и приложения для встраиваемых устройств уровня современных КПК. Компиляторы — MSVC v. >= 6.0 и g++ v. >= 3.4.5
На мой взгляд широкое использование inline загрязняет код и не приводит к существенному изменению качества сгенерированного кода.
Так же я часто встречал в литературе (например у Саттера) рекомендации не использовать inline (со ссылками на то, что компилятор и так достаточно умен, чтобы соптимизировать такой код, а так же, что любая функция объявленная в теле класса считается встроенной безотносительно наличия квалификатора inline).
Однако люди писавшие этот код — очень хорошие профессионалы.
В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).
Здравствуйте, Аноним, Вы писали:
А>Однако люди писавшие этот код — очень хорошие профессионалы. А>В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).
Нет, представление компилятора об уме может разниться с твоим, в MSVC 7.0 да и вроде 2008-2010 студиях оставлена директива __forceinline. И она таки работает.
Если тело функции-члена находится в теле класса, то inline излишен, поскольку такие функции и так трактуются как inline:
9.3 Member functions
...
2 A member function may be defined (8.4) in its class definition, in which case it is an inline member function
(7.1.2),...
Поэтому код
class Foo
{
public:
Foo() { ... }
int getSomething() const { ... }
void setSomething(...) { ... }
};
будет эквивалентен ранее приведенному вами.
Другой вопрос — встроит или нет такие функции компилятор? Здесь гарантий никаких нет. Но и бить тревогу раньше времени тоже не стоит. Если профилировщик укажет, что узким местом системы является одна из этих функции, тогда и стоит что-либо предпринимать.
Здравствуйте, Анатолий Широков, Вы писали:
АШ>Если тело функции-члена находится в теле класса, то inline излишен, поскольку такие функции и так трактуются как inline:
... АШ>Другой вопрос — встроит или нет такие функции компилятор? Здесь гарантий никаких нет. Но и бить тревогу раньше времени тоже не стоит. Если профилировщик укажет, что узким местом системы является одна из этих функции, тогда и стоит что-либо предпринимать.
я, в общем-то, так и думал. Спасибо за ссылку из стандарта.
В общем меня интересовало — имеет ли какой-то вес для компилятора добавочное объевление inline для методов реализованных по месту объявления. Видимо стоит задать такой вопрос разработчикам компилятора...
Здравствуйте, StevenIvanov, Вы писали:
SI>Здравствуйте, Анатолий Широков, Вы писали:
... SI>В общем меня интересовало — имеет ли какой-то вес для компилятора добавочное объевление inline для методов реализованных по месту объявления. Видимо стоит задать такой вопрос разработчикам компилятора...
разработчики GCC ответили то же самое...
> I mean whether the code
>
> class A
> {
> inline void foo() { ... }
> };
>
> is absolutely equal to
>
> class A
> {
> void foo() { ... }
> };
>
> in *any* circumstances or not?
They are the same unless you do -fno-default-inline and then the
second version is not marked as inline.
Здравствуйте, Тролль-323, Вы писали:
Т3>Может, они делают так: объявляют платформенно-зависимый Т3>
#define inline
Т3>чтобы сделать inline, который по-настоящему работает, а не просто дает «совет» компилятору.
inline (явный или неявный, как в случае классов и шаблонов) — это не только совет, но и указание компилятору относительно линковки. В VC ему соответствует __declspec(selectany).
Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE
Здравствуйте, StevenIvanov, Вы писали:
SI>к тому же последняя конструкция не всегда хорошо работает на gcc 3.4.x (иногда могут возникать ошибки компиляции — "sorry — inlining failed")
Никакое указание относительно встраивания не может всегда хорошо работать. Есть вещи, которые в принципе не получится встроить — например, рекурсию или косвенный вызов.
Другое дело, что VC к этому относится снисходительно — не встроил, ну и ладно. А gcc ругается.
Здравствуйте, Кодт, Вы писали:
К>Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE
Дык эти вроде хаком и не пользовались...
А код насколько старый? Или кросс-платформенный?
Может это борьба с глюками какого-то редкого/старого транслятора?
А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
К>>Настоящие профессионалы, вместо хака с переопределением ключевого слова, лучше бы ввели своё #define FORCEINLINE E>Дык эти вроде хаком и не пользовались...
Переопределять ключевые слова — не хак?
E>А код насколько старый? Или кросс-платформенный? E>Может это борьба с глюками какого-то редкого/старого транслятора?
Вот это больше похоже на правду.
E>А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом...
Э? Почему inline foo() лучше для грепа, чем FORCEINLINE foo() ?
А>Так же я часто встречал в литературе (например у Саттера) рекомендации не использовать inline (со ссылками на то, что компилятор и так достаточно умен, чтобы соптимизировать такой код, а так же, что любая функция объявленная в теле класса считается встроенной безотносительно наличия квалификатора inline).
А>Однако люди писавшие этот код — очень хорошие профессионалы. А>В связи с чем вопрос — есть ли достоверные сведения о том, что от квалификатора inline можно безболезненно отказаться в случае использования вышеупомянутых компиляторов (интересует информация хотя бы по g++ версии 4 и выше).
1. В общем случае, компилятор недостаточно умен. По крайней мере вдумчивое расставление __forceinlinе для MSVC не раз приводило к заметному приросту производительности на критических участках.
2. модификатор inline в С++ имеет и другие эффекты кроме встраивания функций
3. Возможно, модификатор inline в коде написан с целью документирования того какие функции по мнению авторов должны быть заинлайнены, чтобы к примеру упростить портирование.
4. Ну и вполне возможно что авторы просто привыкли писать не то что "можно", а то, что они имели ввиду
Здравствуйте, Кодт, Вы писали:
К>Переопределять ключевые слова — не хак?
Я так понял, что в обсуждаемом случае никто ничего не переопределял, это было предположение комментаторов.
E>>Может это борьба с глюками какого-то редкого/старого транслятора? К>Вот это больше похоже на правду.
Мне эта версия, пока что, представляется самой правдаподобной...
E>>А ещё такое использование слова inline может быть полезно, чтобы искать подставляемые функции грепом... К>Э? Почему inline foo() лучше для грепа, чем FORCEINLINE foo() ?
Какой такой FORCEINLINE?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Так, как я написал, тоже можно (в документации GCC написано).
SI>к тому же последняя конструкция не всегда хорошо работает на gcc 3.4.x (иногда могут возникать ошибки компиляции — "sorry — inlining failed")
Да, есть такое дело.
Ну если авторы этого не делают, тогда, честно говоря, у меня возникают сомнения в их очень хорошем профессионализме, потому что я не могу придумать каких-нибудь других причин для того, чтобы так писать.
Кстати, тов. Саттер врет, что компилятор сам знает, когда инлайнить функции. Как показывает практика, ничего он не знает, и это одна из причин, по которой, например, STL тормозит. Из-за этого, например, фирма Electronic Arts написала свою реализацию STL.
SC>1. В общем случае, компилятор недостаточно умен. По крайней мере вдумчивое расставление __forceinlinе для MSVC не раз приводило к заметному приросту производительности на критических участках.
На самом деле, он часто не то, чтобы недостаточно умен, а просто откровенно туп. Например, может не заинлайнить крайне часто вызывающуюся функцию по каким-то неизвестным причинам, что катастрофически может сказаться на производительности программы.
Здравствуйте, Тролль-323, Вы писали:
Т3>На самом деле, он часто не то, чтобы недостаточно умен, а просто откровенно туп. Например, может не заинлайнить крайне часто вызывающуюся функцию по каким-то неизвестным причинам, что катастрофически может сказаться на производительности программы.
Когда ему нужно выбрать между оптимизацией размера и оптимизацией скорости — кто знает, что он предпочтёт?
Можно, конечно, поиграть с опциями favor speed / favor size и посмотреть.
Здравствуйте, Кодт, Вы писали:
К>Когда ему нужно выбрать между оптимизацией размера и оптимизацией скорости — кто знает, что он предпочтёт? К>Можно, конечно, поиграть с опциями favor speed / favor size и посмотреть.
Ни разу я от этой галочки никакого видимого профиту не поимел
Здравствуйте, Тролль-323, Вы писали:
Т3>Кстати, тов. Саттер врет, что компилятор сам знает, когда инлайнить функции. Как показывает практика, ничего он не знает, и это одна из причин, по которой, например, STL тормозит. Из-за этого, например, фирма Electronic Arts написала свою реализацию STL.
Это смотря какой компилер. ICC например отлично справляется если ему разрешить (/Ob2)
А писать свой STL обычно приходится потому, что зачастую надо добавить во главу угла такие первоочередной важности параметры как быстродействие и потребление памяти.
Бо в стандарте на STL про них почти не упомянуто. EA — крупные игроделы, а крупным игроделам производительность и потребление очень важны.