Switch 문은 일반적으로 컴파일러 최적화로 인해 동등한 if-else-if 문 (예 :이 기사 에서 설명 ) 보다 빠릅니다 .
이 최적화는 실제로 어떻게 작동합니까? 누구에게 좋은 설명이 있습니까?
답변
컴파일러는 해당되는 경우 점프 테이블을 빌드 할 수 있습니다. 예를 들어 리플렉터를 사용하여 생성 된 코드를 살펴보면 문자열의 큰 스위치에 대해 컴파일러가 실제로 해시 테이블을 사용하여이를 디스패치하는 코드를 생성한다는 것을 알 수 있습니다. 해시 테이블은 문자열을 키로 사용하고 case
코드를 값으로 위임 합니다.
이것은 많은 체인 if
테스트 보다 점근 적으로 더 나은 런타임을 가지며 실제로 상대적으로 적은 문자열에서도 더 빠릅니다.
답변
이것은 if..else if ..
사람에 의해 사소하게 switch 문으로 변환 될 수 있는 시퀀스 를 만나는 현대 컴파일러처럼 약간 단순화 된 것입니다. 컴파일러도 마찬가지입니다. 그러나 재미를 더하기 위해 컴파일러는 구문에 의해 제한되지 않으므로 범위, 단일 대상 등이 혼합 된 내부적으로 “switch”와 같은 명령문을 생성 할 수 있으며 switch와 if 모두에 대해이 작업을 수행 할 수 있습니다. .else 문.
Anyhoo, Konrad의 답변에 대한 확장은 컴파일러가 점프 테이블을 생성 할 수 있지만 반드시 보장되는 것은 아닙니다 (바람직하지 않음). 다양한 이유로 점프 테이블은 최신 프로세서의 분기 예측 자에 나쁜 일을하고 테이블 자체는 행동을 캐시하기 위해 나쁜 일을합니다.
switch(a) { case 0: ...; break; case 1: ...; break; }
컴파일러가 실제로 이에 대한 점프 테이블을 생성했다면 점프 테이블이 if..else if..
분기 예측을 무너 뜨리기 때문에 대체 스타일 코드 보다 느릴 수 있습니다 .
답변
불일치 통계는 좋지 않을 수 있습니다.
실제로 소스를 다운로드하는 경우 일치하지 않는 값은 if 및 switch 케이스 모두에서 21로 알려져 있습니다. 컴파일러는 어떤 문이 항상 실행되어야하는지 알고 추상화 할 수 있어야하며 CPU는 올바르게 분기 예측할 수 있어야합니다.
더 흥미로운 경우는 내 생각에 모든 사례가 깨지는 것은 아니지만 그것이 실험의 범위가 아닐 수도 있다는 것입니다.
답변
Switch / case 문은 일반적으로 1 단계 깊이에서 더 빠를 수 있지만 2 개 이상을 시작하면 switch / case 문이 중첩 된 if / else 문보다 2-3 배 오래 걸리기 시작합니다.
이 기사에는 이러한 문이 중첩 될 때 속도 차이를 강조하는 몇 가지 속도 비교 가 있습니다.
예를 들어 테스트에 따르면 다음과 같은 샘플 코드가 있습니다.
if (x % 3 == 0)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 1)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else if (x % 3 == 2)
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
else
if (y % 3 == 0)
total += 3;
else if (y % 3 == 1)
total += 2;
else if (y % 3 == 2)
total += 1;
else
total += 0;
동등한 switch / case 문을 실행하는 데 걸린 시간의 절반으로 완료되었습니다 .
switch (x % 3)
{
case 0:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 1:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
case 2:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
default:
switch (y % 3)
{
case 0: total += 3;
break;
case 1: total += 2;
break;
case 2: total += 1;
break;
default: total += 0;
break;
}
break;
}
예, 이것은 초보적인 예이지만 요점을 보여줍니다.
따라서 결론은 한 레벨 깊이의 단순 유형에 대해 스위치 / 케이스를 사용하는 것일 수 있지만 더 복잡한 비교 및 다중 중첩 레벨의 경우 클래식 if / else 구문을 사용합니까?
답변
if over 케이스의 유일한 장점은 첫 번째 케이스의 발생 빈도가 눈에 띄게 증가 할 때입니다.
임계 값이 정확히 어디에 있는지 확실하지 않지만 첫 번째 “거의 항상”이 첫 번째 테스트를 통과하지 않는 한 케이스 구문을 사용합니다.
답변
