parsing性能(如果,TryParse,Try-Catch)
我知道很多关于处理信息parsing文本的不同方法。 例如,parsing整数可以预期什么样的性能。 我想知道是否有人知道这个好的数据。 我正在寻找一些经过testing的人的真实数字。
哪些在哪些情况下提供最佳性能?
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(stringstr,out T值) 。 投掷exception是昂贵的,应该避免,如果你能事先处理这种情况。 使用try-catch块来“保存”性能(因为无效的数据速率很低)是以可维护性和良好编码实践为代价的滥用exception处理。 遵循健全的软件工程开发实践,编写testing用例,运行应用程序,然后进行基准testing和优化。
“我们应该忘记效率很低,约97%的时间: 过早优化是万恶之源 ,但我们不应该把这个关键的3%放在一边”–Donald Knuth
因此,您可以像碳信用一样任意指定try-catch的性能更差 ,TryParse的性能更好 。 只有当我们运行我们的应用程序,并确定我们有某种放缓的stringparsing,我们甚至会考虑使用TryParse以外的任何东西。
(编辑:因为看起来提问者希望计时数据能够得到很好的build议,下面是要求的计时数据)
来自用户的10000次input的各种失败率的时间(对于不信的人):
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); }
虽然我没有亲自介绍不同的方式,但这一章有:
Try-Catch将永远是较慢的。 TryParse会更快。
IF和TryParse是相同的。
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.
exception处理相对昂贵,所以如果可以的话,尽量避免。
特别是不好的投入是预料不到的,所以你不应该在这种情况下使用它们。
(尽pipe在TryParse之前,它可能是最好的select。)