Производительность парсинга (если, TryParse, Try-Catch)

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

Что из этого предлагает лучшую производительность в каких ситуациях?

Parse(...)  // Crash if the case is extremely rare .0001%

If (SomethingIsValid) // Check the value before parsing
    Parse(...)

TryParse(...) // Using TryParse

try
{
    Parse(...)
}
catch
{
    // Catch any thrown exceptions
}

Некоторое время назад Джон Скит провел несколько тестов для этого. Извините, у меня нет готовой ссылки - Может, зайти в Google?

Michael Burr 29.09.2008 23:21
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
33
1
15 621
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Всегда используйте T.TryParse (строка str, выходное значение T). Создание исключений обходится дорого, и этого следует избегать, если вы можете справиться с ситуацией априори. Использование блока try-catch для «экономии» производительности (из-за низкой скорости передачи недопустимых данных) является злоупотреблением обработкой исключений за счет удобства обслуживания и хороших практик кодирования. Следуйте разумным методам разработки программного обеспечения, напишите свои тестовые примеры, запустите приложение, ЗАТЕМ тестируйте и оптимизируйте.

"We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%" -Donald Knuth

Поэтому вы произвольно назначаете, как в углеродных кредитах, что производительность try-catch равна хуже, а производительность TryParse равна лучше. Только после того, как мы запустили наше приложение и определили, что у нас какое-то замедление по w.r.t. при синтаксическом анализе строк, не могли бы мы даже рассмотреть возможность использования чего-либо, кроме TryParse.

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

Времена для разной интенсивности отказов на 10 000 входов от пользователя (для неверующих):

Failure Rate      Try-Catch          TryParse        Slowdown
  0%           00:00:00.0131758   00:00:00.0120421      0.1
 10%           00:00:00.1540251   00:00:00.0087699     16.6
 20%           00:00:00.2833266   00:00:00.0105229     25.9
 30%           00:00:00.4462866   00:00:00.0091487     47.8
 40%           00:00:00.6951060   00:00:00.0108980     62.8
 50%           00:00:00.7567745   00:00:00.0087065     85.9
 60%           00:00:00.7090449   00:00:00.0083365     84.1
 70%           00:00:00.8179365   00:00:00.0088809     91.1
 80%           00:00:00.9468898   00:00:00.0088562    105.9
 90%           00:00:01.0411393   00:00:00.0081040    127.5
100%           00:00:01.1488157   00:00:00.0078877    144.6


/// <param name = "errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryCatch(double errorRate, int seed, int count)
{
    Stopwatch stopwatch = new Stopwatch();
    Random random = new Random(seed);
    string bad_prefix = @"X";

    stopwatch.Start();
    for(int ii = 0; ii < count; ++ii)
    {
        string input = random.Next().ToString();
        if (random.NextDouble() < errorRate)
        {
           input = bad_prefix + input;
        }

        int value = 0;
        try
        {
            value = Int32.Parse(input);
        }
        catch(FormatException)
        {
            value = -1; // we would do something here with a logger perhaps
        }
    }
    stopwatch.Stop();

    return stopwatch.Elapsed;
}

/// <param name = "errorRate">Rate of errors in user input</param>
/// <returns>Total time taken</returns>
public static TimeSpan TimeTryParse(double errorRate, int seed, int count)
{
    Stopwatch stopwatch = new Stopwatch();
    Random random = new Random(seed);
    string bad_prefix = @"X";

    stopwatch.Start();
    for(int ii = 0; ii < count; ++ii)
    {
        string input = random.Next().ToString();
        if (random.NextDouble() < errorRate)
        {
           input = bad_prefix + input;
        }

        int value = 0;
        if (!Int32.TryParse(input, out value))
        {
            value = -1; // we would do something here with a logger perhaps
        }
    }
    stopwatch.Stop();

    return stopwatch.Elapsed;
}

public static void TimeStringParse()
{
    double errorRate = 0.1; // 10% of the time our users mess up
    int count = 10000; // 10000 entries by a user

    TimeSpan trycatch = TimeTryCatch(errorRate, 1, count);
    TimeSpan tryparse = TimeTryParse(errorRate, 1, count);

    Console.WriteLine("trycatch: {0}", trycatch);
    Console.WriteLine("tryparse: {0}", tryparse);
}

Аристотель никогда бы не запачкал руки, поставив эксперимент. Позор, позор. Вам нужно что-то утверждать как очевидную истину. Это Интернет-путь !!!

Chris Cudmore 29.09.2008 23:39

@chris: Меня почему-то отключили ... Думаю, правда болит.

user7116 29.09.2008 23:42

Спасибо за быстрый тест, даже если версия try-catch ошибочна, поэтому тот факт, что TryParse () работает быстрее, даже не нужно доказывать ...

Michael Burr 30.09.2008 00:03

@Mike B, чрезвычайно важно запускать тесты и тестировать вещи, независимо от того, знаете ли вы ответ или нет. Я просто изменил этот код, чтобы добавить случай, не обрабатывающий исключения для случая 0%. Это один из аспектов, который я тоже хотел, и обнаружил, что он эквивалентен TryParse.

Brendan Enrick 30.09.2008 01:03

Извините - я добавил туда «неправильный» бит, потому что «sixlettervariables» несколько уколов тот факт, что, по его мнению, версия Parse (), генерирующая исключения, просто плохой дизайн / неправильный.

Michael Burr 30.09.2008 01:31

@Mike B: теперь я умный человек, но я не могу поверить в разумные рекомендации, сделанные множеством умных людей в Microsoft / Sun / et al. : D

user7116 30.09.2008 01:36

Если вы собираетесь использовать эту цитату, вам следует использовать полную цитату: «Мы должны забыть о небольшой эффективности, скажем, примерно в 97% случаев: преждевременная оптимизация - это корень всех зол. Однако мы не должны упускать наши возможности. в этих критических 3% ».

Scott Dorman 29.08.2009 06:54

Известно, что 82% всей статистики составляются на месте.

drobertson 16.03.2016 02:31

Try-Catch всегда будет медленнее. TryParse будет быстрее.

IF и TryParse одинаковы.

Чтобы быть полностью ясным, Try-Catch будет медленнее, только если синтаксический анализ не удастся; не выбрасывать / не перехватывать исключение ничего не стоит.

technophile 29.09.2008 22:59

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

Brendan Enrick 29.09.2008 23:13

Если возникновение ошибки маловероятно, на какую производительность можно рассчитывать? Вот почему я попросил некоторую статистику по этому поводу, а не просто «Этот быстрее».

Brendan Enrick 29.09.2008 23:14

@benrick: это скорее злоупотребление фреймворком исключений, чем проблема производительности. Поэтому вы предполагаете, что try-catch всегда будет медленнее, а TryParse всегда будет быстрее.

user7116 29.09.2008 23:18

@Daok: +1, статистика не нужна, если только вы не член немытых масс.

user7116 29.09.2008 23:38

Option 1: Will throw an exception on bad data.
Option 2: SomethingIsValid() could be quite expensive - particularly if you are pre-checking a string for Integer parsability.
Option 3: I like this.  You need a null check afterwards, but it's pretty cheap.
Option 4 is definitely the worst.

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

В частности, следует ожидать плохих вводов, а не исключений, поэтому вы не должны использовать их в этой ситуации.

(Хотя до TryParse, возможно, это был лучший вариант.)

Что касается вариантов 1 и 4: ОП действительно пытается определить, является ли стоимость броска незначительной, когда возможность броска незначительна (он говорит, что 0,0001%). Варианты 2 и 3 на самом деле одно и то же. TryParse за кулисами делает именно то, что делает Вариант 2, при условии, что Вариант 2 не открывает sqlconnections или что-то странное. Наконец, вариант 3 вам никогда не придется проверять значение null. Если вы собираетесь добавить чек, просто проверьте возврат попытки. Итак, хотя на данный момент у вас высокий балл и, вероятно, вы все это знаете, я считаю, что нужно добавить ясность, почему этот старый ответ имеет -2

Suamere 07.07.2015 18:46

Что делает TryParse: linksource.microsoft.com/#mscorlib/system/…

Suamere 07.07.2015 18:46

Другие вопросы по теме