문제

나는 정보를 얻기 위해 텍스트를 구문 분석하는 다양한 방법을 잘 알고 있습니다.예를 들어 정수를 구문 분석하는 경우 어떤 종류의 성능을 기대할 수 있습니까?이에 대한 좋은 통계를 아는 사람이 있는지 궁금합니다.나는 이것을 테스트한 누군가로부터 몇 가지 실수를 찾고 있습니다.

다음 중 어떤 상황에서 최고의 성능을 제공하는 것은 무엇입니까?

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, out T 값).예외를 던지는 것은 비용이 많이 들기 때문에 상황을 처리할 수 있다면 피해야 합니다. 선험적으로.성능을 "절약"하기 위해 try-catch 블록을 사용하는 것은(잘못된 데이터 비율이 낮기 때문에) 유지 관리 가능성과 좋은 코딩 방법을 희생하면서 예외 처리를 남용하는 것입니다.건전한 소프트웨어 엔지니어링 개발 관행을 따르고, 테스트 사례를 작성하고, 애플리케이션을 실행한 다음 벤치마킹하고 최적화하세요.

"약 97%의 경우 작은 효율성은 잊어야 합니다. 성급한 최적화는 모든 악의 근원이다.하지만 우리는 중요한 3%에 있는 기회를 놓쳐서는 안 됩니다." -Donald Knuth

따라서 탄소 배출권에서처럼 임의로 try-catch의 성능을 할당합니다. 더 나쁜 TryParse의 성능은 더 나은.애플리케이션을 실행하고 일종의 속도 저하가 있음을 확인한 후에야문자열 구문 분석에는 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);
}

다른 팁

나는 개인적으로 다른 방법을 프로파일하지 않았지만이 챕터는 다음과 같습니다.

http://blogs.msdn.com/ianhu/archive/2005/12/19/505702.aspx

Try-Catch는 항상 느리게됩니다. TryParse가 더 빠릅니다.

IF와 TryParse는 동일합니다.

여기에 있습니다 성능 차이를 프로파일 링 한 또 다른 챕터, 그리고 몇 가지 다른 데이터 유형으로, (전혀) 얼마나 많은 시간을 확인하면, 그것들은 본질적으로 성능에 영향을 미칩니다 : int, bool 및 dateTime.

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 이전에는 최선의 선택 일 수 있습니다.)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top