DivideByZeroException слишком медленно - PullRequest
7 голосов
/ 02 февраля 2010

Это очень медленно:

try
{
    x = k / y;
}
catch (DivideByZeroException) { }

Это примерно в 5 раз быстрее:

if (y > 0) x = k / y;

Кто-нибудь может сказать мне, почему?

Ответы [ 6 ]

11 голосов
/ 02 февраля 2010

Только в 5 раз быстрее? Вы меня удивляете. Предположительно, это означает, что в ваших выборочных данных мало нулей.

Исключения дороже, чем простые сравнения. При правильном использовании (т. Е. Для исключительных обстоятельств) они не имеют тенденций к значительному снижению производительности - потому что, если вы создаете достаточно исключений, чтобы это оказало большое влияние, скорее всего, ваша служба уже заблокирована. Это вызывает проблему, когда вы используете исключения, чтобы попытаться игнорировать условия, которые вы могли бы очень легко протестировать для начала - как этот.

Одна вещь, которую следует отметить относительно стоимости исключений: они стоят намного больше в отладчике, чем при работе без подключенного отладчика; в частности, первое исключение, которое должно загружать кучу ресурсов, может занимать секунды, а не микро / миллисекунды. Если вы собираетесь тестировать код, очень важно, чтобы вы не делали это в отладчике - это верно в целом, но особенно для исключений.

10 голосов
/ 02 февраля 2010

Потому что исключения дорогие.

Когда выдается исключение, среда выполнения должна выбрать довольно много информации (например, трассировки стека) и скопировать ее. Это требует времени и ресурсов, когда тест на значение 0 очень дешев в сравнении.

См. этот SO вопрос , спрашивающий, насколько дорогими являются исключения для получения дополнительной информации.

5 голосов
/ 02 февраля 2010

Ошибка, поскольку исключения выполняются медленнее, чем проверка. Исключения, как правило, имеют много инфраструктуры вокруг них, чего нет у простого оператора if.

Они не являются эквивалентными операциями, поскольку у вас есть много информации, доставленной в исключении , даже если вы решите не использовать , как в этом случае.

3 голосов
/ 02 февраля 2010

Почему исключения медленные?

Потому что много вещей происходит, когда генерируется исключение и ловится. Подробности см. В статье Криса Брамме о модели управляемых исключений и в этой статье о базовой модели Win32 SEH .

Почему простой тест быстрый?

Потому что он просто выполняет одну инструкцию для перехода в зависимости от результата сравнения двух целых чисел, что гораздо меньше работы, чем исключение.

Значит ли это, что я всегда должен стараться избегать исключений?

Нет, это зависит от семантики. Если деление на ноль является действительно исключительным случаем, которого вы не ожидаете, и который ваша программа не может разумно обработать, тогда дайте исключению произойти и выведите из строя вашу программу. Однако, если это ожидаемый случай, и вы можете справиться с ним разумным образом, то было бы разумно избежать исключения.

2 голосов
/ 02 февраля 2010
1 голос
/ 02 февраля 2010

Исключения очень медленные - это причина того, что .Net Framework имеет методы TryParse:

// This is much quicker...
double result;
if (!double.TryParse("Twelve", out result))
{
    result = -1;
}
return result;

// Than this...
try
{
    return double.Parse("Twelve");
}
catch 
{
    return -1;
}

, вы всегда должны стараться избегать исключений (за исключением исключительных случаевхаха ...)

...