IT story

사전에 키가 포함되어 있는지 확인하는 것이 왜 더 빠르지 않은지 예외를 잡는 것보다 더 빠른 이유는 무엇입니까?

hot-time 2020. 4. 13. 08:20
반응형

사전에 키가 포함되어 있는지 확인하는 것이 왜 더 빠르지 않은지 예외를 잡는 것보다 더 빠른 이유는 무엇입니까?


코드를 상상해보십시오.

public class obj
{
    // elided
}

public static Dictionary<string, obj> dict = new Dictionary<string, obj>();

방법 1

public static obj FromDict1(string name)
{
    if (dict.ContainsKey(name))
    {
        return dict[name];
    }
    return null;
}

방법 2

public static obj FromDict2(string name)
{
    try
    {
        return dict[name];
    }
    catch (KeyNotFoundException)
    {
        return null;
    }
}

두 함수의 성능에 차이가 있는지 궁금합니다. 첫 번째 함수는 두 번째 함수보다 느려 야합니다. 한 번만 와우, 그것은 실제로 반대입니다.

1 만개의 값에 대한 루프 (기존의 10 만개와 존재하지 않는 9 억의 경우) :

첫 번째 기능 : 306 밀리 초

두 번째 기능 : 20483 밀리 초

왜 그런 겁니까?

편집 :이 질문 아래 주석에서 알 수 있듯이 두 번째 기능의 성능은 실제로 기존 키가 0이 아닌 경우 첫 번째 기능보다 약간 우수합니다. 그러나 기존 키가 아닌 하나 이상의 키가 있으면 두 번째 키의 성능이 급격히 떨어집니다.


한편, 예외를 던지는 것은 본질적으로 스택이 풀려야하기 때문에 본질적으로 비싸다 .
반면에, 키로 사전의 값에 액세스하는 것은 값이 빠르다. 왜냐하면 O (1) 연산이 빠르기 때문이다.

BTW : 올바른 방법은 사용하는 것입니다 TryGetValue

obj item;
if(!dict.TryGetValue(name, out item))
    return null;
return item;

이것은 두 번이 아닌 한 번만 사전에 액세스합니다. 키가 존재하지 않으면
실제로 반환 null하려면 위 코드를 더 단순화 할 수 있습니다.

obj item;
dict.TryGetValue(name, out item);
return item;

이 때문에, 작동 TryGetValue세트 itemnull아무 키는 경우 name가 없습니다.


사전은 특히 초고속 키 조회를 수행하도록 설계되었습니다. 그것들은 해시 테이블로 구현되며 항목이 많을수록 다른 방법에 비해 빠릅니다. 예외 엔진을 사용하는 것은 메소드가 설계 한 작업을 수행하지 못한 경우에만 수행되어야합니다. 메소드는 오류 처리를위한 많은 기능을 제공하는 큰 객체 세트이기 때문입니다. try catch 블록으로 둘러싸인 모든 항목으로 한 번 전체 라이브러리 클래스를 작성했으며 600 개가 넘는 예외 중 하나에 대한 별도의 행이 포함 된 디버그 출력을 보도록 놀라게되었습니다!

참고 URL : https://stackoverflow.com/questions/16101795/why-is-it-faster-to-check-if-dictionary-contains-the-key-rather-than-catch-the

반응형