C++ 코드를 작성하다 보면 분기 처리가 길어지는 순간이 있다
처음에는 하나만 했다가 나중에 점점 예외처리 요구가 늘어서 스위치로 변경 해야할꺼같은 상황에서 하는것이다
if (cmd == 0)
{
HandleMove();
}
else if (cmd == 1)
{
HandleAttack();
}
else if (cmd == 2)
{
HandleJump();
}
보통 이런식으로 점점 늘어가는경우이다
처음에는 단순하지만 명령어가 많아질수록 코드도 길어지고 유지보수도 어려워진다
이런 상황에서 자주 언급되는 것이 바로 Jump Table 이다
먼저 점프 테이블이 동작하는 구조를 보면
using Handler = void(*)();
void Move() { std::cout << "Move\n"; }
void Attack(){ std::cout << "Attack\n"; }
void Jump() { std::cout << "Jump\n"; }
Handler table[] =
{
Move,
Attack,
Jump
};
int cmd = 1;
table[cmd]();
이런씩으로 사용된다 배열 인덱스를 통해 바로 함수로 점프하는 방식이다
기존의 if-else 혹은 switch-case 처럼
조건을 하나씩 비교하는 것이 아니라
인덱스를 이용해 직접 함수에 접근한다
사실 코딩 하다보면 굳이 직접 Jump Table을 구현할 일이 많지는 않다
그래도 다음과 같을땐 사용하면 좋다
맨위에 적은것처럼 if 가 많아 지면 사용하면 좋다
매 프레임 실행되는 게임 루프
VM Interpreter
패킷 처리 시스템처럼
분기 처리가 엄청 자주 발생하는 환경에서는 의미가 커질 수 있다
연속적인 정수 인덱스에서 가장 효율적이다
예를 들면
인덱스가 12345... 순으로 증가하는 기본적인 enum 값에 사용하는게 좋다
1 10000 9999999 이렇게 값을 지정 하면 효율이다.
많은 경우 컴파일러는 이미 switch-case를
Jump Table 형태로 최적화한다
switch(value)
{
case 0:
case 1:
case 2:
case 3:
}
이렇게 스위치 문으로 코딩 해도 이미 컴파일러가 최적화를 통해서 코드를 변경해서 빌드 해주고 있을 가능성이 매우 높다
특히 최신 컴파일러인경우 더욱 그러하다
직접 구현하지 않아도 컴파일러가 이미 해주고 있을 수 있다
Jump Table은 무조건 빠른 기술이 아니다
가독성 저하
디버깅 어려움
잘못된 인덱스 접근 위험
branch predictor 이점 감소
간접 호출(indirect branch) 비용
특히 현대 CPU는 성능이 굉장히 좋아서 단순한 switch-case가 더 효율적인 경우도 많다
그래서 나는 그냥 스위치 사용할꺼같다 그래도 개념은 알아두면 좋을꺼같다