Каковы реальные издержки попытки/выгоды в C#?

Лучшим способом (рекомендуется) является использование пакета java.util.Concurrent. Используя этот пакет, вы можете легко избежать этого исключения. см. Модифицированный код

public static void main(String[] args) {
        Collection<Integer> l = new CopyOnWriteArrayList<Integer>();

        for (int i=0; i < 10; ++i) {
            l.add(new Integer(4));
            l.add(new Integer(5));
            l.add(new Integer(6));
        }

        for (Integer i : l) {
            if (i.intValue() == 5) {
                l.remove(i);
            }
        }

        System.out.println(l);
    }
91
задан HerbalMart 3 September 2015 в 09:38
поделиться

11 ответов

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

я не думаю, что это - проблема, пока Вы используете исключения для ИСКЛЮЧИТЕЛЬНОГО поведения (так не Ваш типичный, ожидаемый путь через программу).

49
ответ дан Mike Stone 24 November 2019 в 06:46
поделиться

Мне действительно нравится Hafthor сообщение в блоге , и добавить мои два цента к этому обсуждению, я хотел бы сказать, что, для меня всегда было легко иметь бросок СЛОЯ ДАННЫХ только один тип исключения (DataAccessException). Таким образом, моя БИЗНЕС-LAYER знает, какое исключение ожидать и ловит его. Затем в зависимости от дальнейших бизнес-правил (т.е. если мой бизнес-объект участвует в рабочем процессе и т.д.), я могу выдать новое исключение (BusinessObjectException) или продолжить двигаться без ре/броска.

я сказал бы, используйте попытку.. поймайте каждый раз, когда это необходимо, и используйте его мудро!

, Например, этот метод участвует в рабочем процессе...

Комментарии?

public bool DeleteGallery(int id)
{
    try
    {
        using (var transaction = new DbTransactionManager())
        {
            try
            {
                transaction.BeginTransaction();

                _galleryRepository.DeleteGallery(id, transaction);
                _galleryRepository.DeletePictures(id, transaction);

                FileManager.DeleteAll(id);

                transaction.Commit();
            }
            catch (DataAccessException ex)
            {
                Logger.Log(ex);
                transaction.Rollback();                        
                throw new BusinessObjectException("Cannot delete gallery. Ensure business rules and try again.", ex);
            }
        }
    }
    catch (DbTransactionException ex)
    {
        Logger.Log(ex);
        throw new BusinessObjectException("Cannot delete gallery.", ex);
    }
    return true;
}
1
ответ дан 24 November 2019 в 06:46
поделиться

Я сделал запись в блоге об этом предмете в прошлом году. Проверьте его. Нижняя строка - то, что нет почти никакой стоимости для блока попытки, если никакое исключение не происходит - и на моем ноутбуке, исключение было о 36μ s. Это могло бы быть меньше, чем Вы ожидали, но имейте в виду что те результаты где на мелком стеке. Кроме того, первые исключения являются действительно медленными.

2
ответ дан Hafthor 24 November 2019 в 06:46
поделиться

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

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

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

2
ответ дан 24 November 2019 в 06:46
поделиться

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

Так для завершения всего записанного здесь:
1) попытка Использования.. блоки выгоды для фиксации неожиданных ошибок - почти никакая потеря производительности.
2) не используют исключения для исключенных ошибок, если можно избежать его.

3
ответ дан dotmad 24 November 2019 в 06:46
поделиться

По моему опыту, самые большие издержки находятся в фактической выдаче исключения и обработке его. Я когда-то работал над проектом, где код, подобный следующему, использовался, чтобы проверить, имел ли кто-то право отредактировать некоторый объект. Этот HasRight () метод использовали везде на уровне представления и часто называли в течение 100 с объектов.

bool HasRight(string rightName, DomainObject obj) {
  try {
    CheckRight(rightName, obj);
    return true;
  }
  catch (Exception ex) {
    return false;
  }
}

void CheckRight(string rightName, DomainObject obj) {
  if (!_user.Rights.Contains(rightName))
    throw new Exception();
}

, Когда тестовая база данных стала более полной данных тестирования, этого вывода к очень видимому замедлению, в то время как openening новые формы и т.д.

, Таким образом, я осуществил рефакторинг его к следующему, которое - согласно более поздним быстрым и грязным измерениям - является приблизительно 2 порядками величины быстрее:

bool HasRight(string rightName, DomainObject obj) {
  return _user.Rights.Contains(rightName);
}

void CheckRight(string rightName, DomainObject obj) {
  if (!HasRight(rightName, obj))
    throw new Exception();
}

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

6
ответ дан Tobi 24 November 2019 в 06:46
поделиться

Вы спрашиваете об издержках использования попытки/выгоды/наконец, когда исключения не выдаются, или издержки использования исключений для управления технологическим маршрутом? Последний несколько сродни использованию динамитной шашки для зажигания свечи дня рождения малыша, и связанные издержки попадают в следующие области:

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

    • , например, выдавая исключение потребует, чтобы CLR нашел местоположение наконец и блоки выгоды на основе текущего IP и IP возврата каждого кадра, пока исключение не будет обработано плюс блок фильтра.
    • дополнительная стоимость строительства и определение имен для создания кадров в диагностических целях, включая чтение метаданных и т.д.
    • оба из вышеупомянутых объектов обычно код "холода" доступа и данные, таким образом, трудные отсутствия страницы вероятны, если у Вас есть давление памяти вообще:

        <литий> CLR пытается поместить код и данные, которые нечасто используются далекие от данных, которые используются часто для улучшения местности, таким образом, это работает против Вас, потому что Вы вынуждаете холод быть горячим. <литий> стоимость трудных отсутствий страницы, если таковые имеются, затмит все остальное.
  • , Типичные ситуации с выгодой часто глубоки, поэтому вышеупомянутые эффекты, имел бы тенденцию быть увеличенным (увеличение вероятности отсутствий страницы).

Что касается фактического влияния стоимости, это может варьироваться много в зависимости от того, что еще продолжается в Вашем коде в то время. Jon Skeet имеет хорошая сводка здесь с некоторыми полезными ссылками. Я склонен соглашаться с его оператором, что, если Вы переходите к сути дела, где исключения значительно повреждают Вашу производительность, у Вас есть проблемы с точки зрения Вашего использования исключений вне просто производительности.

18
ответ дан RoadWarrior 24 November 2019 в 06:46
поделиться

Три точки для создания здесь:

  • Во-первых, существует минимальная потеря производительности в фактическом наличии блоков try-catch в Вашем коде. Это не должно быть соображением, стараясь избегать наличия их в Вашем приложении. Хит производительности только играет роль, когда исключение выдается.

  • то, Когда исключение выдается в дополнение к операциям раскручивания стека и т.д., которые происходят, какие другие упомянули Вас, должно знать, что целый набор связанного с временем выполнения/отражением материала происходит для заполнения членов класса исключений, таких как объект отслеживания стека и различные участники типа и т.д.

  • , я полагаю, что это - одна из причин, почему общие рекомендации, если Вы собираетесь повторно бросить исключение, ко всего throw;, а не выдайте исключение снова или создайте новое как в тех случаях, все те данные стека повторно собраны, тогда как в простом броске это все сохраняется.

95
ответ дан Shaun Austin 24 November 2019 в 06:46
поделиться

Я написал статью об этом некоторое время назад, потому что было много людей, спрашивающих об этом в то время. Можно найти его и тестовый код в http://www.blackwasp.co.uk/SpeedTestTryCatch.aspx .

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

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

3
ответ дан BlackWasp 24 November 2019 в 06:46
поделиться

Мы можем прочитать в языках программирования Pragmatics Michael L. Scott, что в настоящее время компиляторы не добавляют никаких накладных расходов в общем случае, это означает, когда не происходит исключения. Таким образом, каждая работа выполнена в компиляционном времени. Но когда исключение брошено во время выполнения, компилятор должен выполнить двоичный поиск, чтобы найти правильное исключение, и это произойдет за каждый новый бросок, который вы сделали.

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

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

1
ответ дан 24 November 2019 в 06:46
поделиться

Давайте проанализируем одну из самых больших возможных затрат на блок try / catch, когда он используется там, где его не нужно использовать:

int x;
try {
    x = int.Parse("1234");
}
catch {
    return;
}
// some more code here...

И вот без try / catch:

int x;
if (int.TryParse("1234", out x) == false) {
    return;
}
// some more code here

Не считая незначительных пробелов, можно заметить, что эти два эквивалентных фрагмента кода имеют почти одинаковую длину в байтах. Последний содержит отступ на 4 байта меньше. Это плохо?

Чтобы добавить оскорбления к травме, ученик решает зациклить, в то время как ввод может быть проанализирован как int. Решение без try / catch может выглядеть примерно так:

while (int.TryParse(...))
{
    ...
}

Но как это выглядит при использовании try / catch?

try {
    for (;;)
    {
        x = int.Parse(...);
        ...
    }
}
catch
{
    ...
}

Блоки try / catch - это волшебный способ избавиться от отступов, и мы до сих пор даже не знаем причину этого не смогли! Представьте, что чувствует человек, выполняющий отладку, когда код продолжает выполнение после серьезной логической ошибки, а не останавливается с красивой очевидной ошибкой исключения. Блоки try / catch - это проверка / санация данных для ленивого человека.

Одна из меньших затрат заключается в том, что блоки try / catch действительно отключают определенные оптимизации: http: // msmvps.com / blogs / peterritchie / archive / 2007/06/22 / performance-implations-of-try-catch-finally.aspx . Думаю, это тоже положительный момент. Его можно использовать для отключения оптимизаций, которые в противном случае могли бы нанести вред безопасным, нормальным алгоритмам передачи сообщений для многопоточных приложений, а также для обнаружения возможных состояний гонки;) Это единственный сценарий, который я могу придумать для использования try / catch. Даже у этого есть альтернативы.

-4
ответ дан 24 November 2019 в 06:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: