Насколько try-catch влияет на производительность
Підписуйтеся на Telegram-канал «DOU #tech», щоб не пропустити нові технічні статті
О try-catch есть много информации и еще больше мифов.
Некоторые считают грехом обувать огромные куски кода в этот блок, некоторые воспринимают его даром свыше, который решает многие их проблемы. Один раз говорили даже о фоновых потоках при работе try-catch. Итак,попытаемся разобраться в этом.
Внутри .Net-сборки
В сборке,если проигнорировать заголовки, имеются 3 составляющие:
-Байт-код(Bytecode): Низкоуровневые инструкции,которые определяют тело методов.
-Метаданные(MetaData): Набор таблиц,описывающих более высокий уровень конструкций,например таблицы классов, методов и т.д.
(Думаю вы слышали о таблицах,например — VMT(virtual method table) )
-Кучи(Heaps): Места,где хранятся строковые константы и другие подобные вещи.
То-есть, байт-код — то что на самом деле выполняется, а все остальное описывает дополнительные подробности. Что бы понять что-это, давайте рассмотрим пример вызова метода. Байт-код содержит ряд инструкций вызова, лексемы метода, которые на самом деле являются индексом в таблице методов. Методы таблицы позволят выяснять где находится начало байт-кода метода который мы ищем, по-этому мы можем его найти и выполнить.
Как хранятся обработчики исключений.
В .NET CLR есть такое понятие как "защищенный регион«(protection region). Такие регионы являют собой последовательность инструкций, которые имеют соответствующий обработчик. В C# или VB.Net инструкции в «защищенном регионе» являются кодом в блоке try. Существует много разных обработчиков, в том числе типизированных, которые ловят только определенные исключения.
Обратите вниманиена то,что блок try-catch-finally имеет 2 таких региона:
-один на блок try;
-второй на блок finally.
Они будут охватывать схожие наборы инструкций,но иметь разные адреса обработчиков.
Каждый блок,который имеет(comes with) защищенный регион имеет таблицу с ними. Для каждого защищенного региона имеется 4 записи:
-Начальные инструкции для байт-кода в этом регионе;
-Количество байт со стартовой позиции защищенного региона;
-Тип обработчика;
-Местоположение байт-кода обработчика.
Что происходит при выполнении.
Это важная часть — когда при выполнении не происходит исключения.
Поскольку защищенные регионы хранятся в таблицах,а не в байт-коде,и потому что CLR не нужно беспокоится о обработчиках исключения,когда оно происходит, никаких явных "штрафов выполнения«(runtime penalty) не происходит. Для обработчика finally это немного по-другому, потому что она работает даже тогда,когда исключения нету. Поскольку JIT-компилятор содержит код, который все-таки должен выполнятся,расходы идут не больше чем на jump или return.
Так вот,это большая часть ответа на вопрос, который был задан, но все же интересно, что происходит,когда исключение все же «выскакивает». При условии, что текущий метод находится в защищенном регионе (то-есть в блоке try-catch), происходит поиск по таблице, что-бы найти, есть ли какие-нибудь инструкции,что бы обработать это исключение. Если имеется
несколько вложенных обработчиков, которые смогли бы обработать "ошибку«(которые в свою очередь упорядоченные по порядку), мы найдем первый правильный обработчик.
Если мы находим обработчик — мы выполняем его.Но,если мы его не находит,то идем дальше и ищем есть ли вообще такой обработчик, пока не найдем нужный нам или обнаружим что исключение не обработано и вызывает завершение программы (что иногда является хорошим решением). Это значит,что затраты на обработку исключение равны тем ресурсам, которые будут потрачены на нахождение нужного нам обработчика.
С этого мы можем сделать вывод,что .net оптимизирован для варианта когда мы не получим исключения. То-есть исключение предназначены действительно для «исключительных» ситуаций,это обдуманное решение
разработчиков. Если вы решили делать исключение для управления потоком, то это еще одна причина не делать этого.
И стоимость блока try-catch =..
Исключение довольно дорогостоящая операция,но иногда необходимая. Если вы «ожидаете» ошибку, то лучше использовать все доступные средства проверки перед тем как подойти к try-catch. (Например вместо или перед отлавливанием FileNotFound — использовать File.Exists). Стоимость блока try-catch в случае, когда ошибок не будет — небольшая, хотя это верно только в большинстве случаев (Позже попытаюсь описать несколько таких).
Пользуйтесь на здоровье try-catch, но помните о поиске нужного обработчика и выбросе исключения. Ведь когда происходит исключение стек закрывается и разбирается для трассировки и поиска handler’a.
p.s. Буду благодарен за найденные очепятки, ошибки и помощь в форматировании
Оригинальная статья -
www.programmersheaven.com/...hurt-runtime-performance
33 коментарі
Додати коментар Підписатись на коментаріВідписатись від коментарів