Роясь недавно в исходниках TPL Dataflow я заметил некоторый паттерн: многие функции разбиты на две. Основная называется обычным образом, AddElement или что-то в этом роде, а вторая – AddElement_Slow.
При этом мне очень понравилась причина, по которой это дело делалось: эта оптимизация позволяет заинлайнить метод в типовом кейсе. Казалось бы, а есть ли в этом толк? И, как оказалось, что есть (я бы удивился, если бы камрад Тауб решил бы использовать подобную оптимизацию не проверив, что она имеет смысл).
В результате, если вы пишите библиотеку или работаете над очень горячим куском вашего приложения, то такой подход вполне оправдан: если метод имеет типовой быстрый и нетиповой медленный пути исполнения, то второй кейс разумно выделить в отдельный метод, что сделает основной метод более пригодным для инлайна.
Ну, и подробности, у меня в англоязычном посте: “A common execution path optimization”.
В англоязычном блоге какой-то неправильный code highlighter - не добавляется горизонтальная прокрутка, поэтому с телефона, например, читать пост бесполезно.
ОтветитьУдалитьА в этом блоге хайлайтинг не так выглядит? Я посмотрел в мобильной версии этот и новый блог и разницы не увидел. Да, и там и там прокрутки нет, но это потому, что я не использую хайлайтеры, а копирую код из студии с сохранением форматирования.
УдалитьИнтересная статья. Мне в ней нравится то что там нет каких-то прямо "хаков" для производительности - просто идея "вынести долгий и нечасто исполняемый код в отдельный метод" здравая сама по себе и не ухудшает читабельности и поддерживаемости.
ОтветитьУдалитьИ еще вопрос - а заинлайнится ли
Удалитьif (not_enough_space)
{
Resize();
}
array[i] = val;
где Resize вынесен в отдельный метод и вызывается нечасто?
По умолчанию, лимит для инлайна - 20 IL инструкций. Кажется, что этот лимит не будет достигнут и в этом случае. Плюс, если метод будет вызываться из цикла, то данный лимит будет немного увеличен.
УдалитьТ.е. я думаю, что этот метод заинлайнится тоже.
Конечно, гадание с (не) заинлайнится вещь всё же неочевидная. Я например далеко не настолько крут чтобы быстренько на глаз посчитать во сколько IL команд скомпилируется мой код.
УдалитьА есть какой-то способ для проверки - инлайнится метод или нет?
Ну кроме ковыряния результирующего байт-кода руками.
Тут даже не IL смотреть нужно, а генерируемый JIT-ом asm.
УдалитьЕсть еще одна подобная фишка: если имеется здоровенный If-then-else-if-then-else... или switch - самые часто встречающиеся варианты выносить в начало списка.
УдалитьПравда, обязательно надо тестировать: компилятор может много чего наменять, плюс не уверен в соблюдении порядка switch-eм.
Да, интересный момент. Как-то не думал в эту сторону, но частенько итак это делал.
УдалитьВ приведенном примере реалокация/ресайз явно обладает достаточной ответсвенностью для выделения в отдельный метод. Хотелось бы отметить, что это не только не ухудшает читаемость, это улучшает читаемость, да и код "в общем". И я думаю, что зачастую можно выделить подобную ответственность у такого куска кода, а если так, то можно будет использовать вменяемый нейминг, вроде Reallocate/Resize etc. То, что в примере осознанно сохранен стиль нейминга я понимаю.
Как можно выйти с Вами на связь? На этом сайте нашел только как комментарии оставлять. У меня есть к Вам предложение. Моя почта zemlyanikin@recursion.ru
ОтветитьУдалитьsergey dot teplyakov sobak gmail dot com
УдалитьThanks for sharing, nice post! Post really provice useful information!
ОтветитьУдалитьAn Thái Sơn chia sẻ trẻ sơ sinh nằm nôi điện có tốt không hay võng điện có tốt không và giải đáp cục điện đưa võng giá bao nhiêu cũng như mua máy đưa võng ở tphcm địa chỉ ở đâu uy tín.