Я много знаю о различных способах обработки текста для получения информации. Например, для анализа целых чисел, какой производительности можно ожидать. Мне интересно, знает ли кто-нибудь хорошую статистику по этому поводу. Я ищу реальные цифры от того, кто это проверял.
Что из этого предлагает лучшую производительность в каких ситуациях?
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
}





Всегда используйте 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: Меня почему-то отключили ... Думаю, правда болит.
Спасибо за быстрый тест, даже если версия try-catch ошибочна, поэтому тот факт, что TryParse () работает быстрее, даже не нужно доказывать ...
@Mike B, чрезвычайно важно запускать тесты и тестировать вещи, независимо от того, знаете ли вы ответ или нет. Я просто изменил этот код, чтобы добавить случай, не обрабатывающий исключения для случая 0%. Это один из аспектов, который я тоже хотел, и обнаружил, что он эквивалентен TryParse.
Извините - я добавил туда «неправильный» бит, потому что «sixlettervariables» несколько уколов тот факт, что, по его мнению, версия Parse (), генерирующая исключения, просто плохой дизайн / неправильный.
@Mike B: теперь я умный человек, но я не могу поверить в разумные рекомендации, сделанные множеством умных людей в Microsoft / Sun / et al. : D
Если вы собираетесь использовать эту цитату, вам следует использовать полную цитату: «Мы должны забыть о небольшой эффективности, скажем, примерно в 97% случаев: преждевременная оптимизация - это корень всех зол. Однако мы не должны упускать наши возможности. в этих критических 3% ».
Известно, что 82% всей статистики составляются на месте.
Try-Catch всегда будет медленнее. TryParse будет быстрее.
IF и TryParse одинаковы.
Чтобы быть полностью ясным, Try-Catch будет медленнее, только если синтаксический анализ не удастся; не выбрасывать / не перехватывать исключение ничего не стоит.
Да, я спрашивал отчасти потому, что мне интересно, сколько стоит выполнение блока try-catch по сравнению с тем, что, возможно, вообще ничего не делать.
Если возникновение ошибки маловероятно, на какую производительность можно рассчитывать? Вот почему я попросил некоторую статистику по этому поводу, а не просто «Этот быстрее».
@benrick: это скорее злоупотребление фреймворком исключений, чем проблема производительности. Поэтому вы предполагаете, что try-catch всегда будет медленнее, а TryParse всегда будет быстрее.
@Daok: +1, статистика не нужна, если только вы не член немытых масс.
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
Что делает TryParse: linksource.microsoft.com/#mscorlib/system/…
Некоторое время назад Джон Скит провел несколько тестов для этого. Извините, у меня нет готовой ссылки - Может, зайти в Google?