1/15/2008 7:11:00 PM

Несколько раз натыкался на рассуждения о вредности использования Try ... Catch для производительности. А сегодня даже поспорил с коллегой по этому поводу: он утверждал, что само по себе использование Try для этой производительности вредно. Мне же всегда казалось, что влиять на производительность  может только блок Catch, так как там нужно как минимум стек раскручивать.

Было решено сделать тесты и вынести рекомендации :) Результатами тестов и этими самыми рекомендациями я и поделюсь, хотя уверен, это все уже не раз было, да и каждый это сам сделать сможет... Словом, на новизну ни сокрального знания, ни идеи не претендую.

Итак, сделали функцию, которая принимала параметром число и возвращала его произведение самого на себя.
Поместили ее в цикл из 1 600 000 итераций. Использовалась функция так:

long res = Calculate(i);
//чтобы результат типа использовался
if (res < 0) throw new InvalidOperationException();

Этот код мы поместили один раз в Try ... Catch (Catch там сработать не мог, но нам нужно было протестировать влияние самого Try), а второй раз без него. Итого 1 раз 1 600 000 итераций с Try, другой - без. И так 50 раз для чистоты эксперимента.

Разница в этом случае ни разу не превысила 00:00:00.0023953, кроме того, примерно в 1/10 случае она оказывалась отрицательной. То есть, будем считать, что разницы-то никакой и нету :)

Теперь о вреде Catch.
Здесь я сделал такой же тест, но вместо умножения чисел я внутри цикла парсил число из строки. Int32.Parse в одном случае и Int32.TryParse в другом. Строка всегда была "неправильной", то есть Int32.Parse всегда возбуждала исключение, которое я перехватывал и возвращал 0. Int32.TryParse никогда не возбуждает исключения, поэтому в блок Catch в этом случае мы не попадаем.
Здесь я сделал всего 1600 итераций, так как иначе пришлось бы слишком долго ждать.

Выводы следующие:

With Catch: 00:00:04.2675105
Without Catch: 00:00:00.0012498
Diff: 00:00:04.2662607

Итак, рекомендации:

  1. Используйте Try ... Catch и Try ... Finally конструкции без страха повредить производительности своего приложения до тех пор, пока это не противоречит пункту "2".
  2. Не используйте Try ... Catch конструкции для того, чтобы проверить формат данных или преобразовать что-то во что-то, как было в указанном примере с числами. Иными словами, не используйте Try ... Catch для обработки штатных ситуаций.
  3. Используйте Try ... Catch для работы именно с исключительными ситуациями; не выбрасывайте исключение только для того, чтобы выше его перехватить и обработать как штатную ситуацию. Исключение должно возбуждаться только тогда когда с точки зрения подсистемы произошла действительно исключительная ситуация и подсистема просто не в состоянии разрулить ее самостоятельно. В противном случае пользуйтесь возвращаемыми значениями.

Вот и все.

P.S. Весь код собирался и тестировался в режиме Release.

 

 

Tags:

Comments (4) -

1/22/2008 9:38:53 AM

kastex

В принципе, ожидаемо. Само торможение должно происходить только при раскрутке стека, при срабатывании Catch. А try тормозить никак не может, т.к. на код не оказыват никакого влияния.

kastex

1/22/2008 11:19:57 AM

Alexey Raga

Что и требовалось доказать Smile

Alexey Raga

2/15/2008 9:05:44 AM

Michael

А можно увидеть полный код тестов?

Michael

2/23/2008 3:52:04 PM

Alexey Raga

К сожалению уже нет, они не сохранились Smile
Так это легко сделать и самостоятельно, там ничего "такого" не было - циклы да таймеры...

Alexey Raga

Comments are closed

Powered by BlogEngine.NET 2.5.0.6

About the author

Alexey Raga Alexey Raga
.NET software developer.

E-mail me Send mail

Twitter


Recent posts

Archive

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2012

Sign in