본문 바로가기
Minecraft Forge/기타 메모

Vanilla Minecraft MathHelper 에 관해

by 정우 :P 2016. 5. 18.

 편하게 쓸 수 있게 만들고 있는 라이브러리에 수학 관련 기능을 넣으려고 바닐라 소스를 참고하던 중에 MathHelper 클래스에서 의문점이 들었다.

다름이 아니라 MathHelper 클래스에서는 Sin 값을 테이블 형식으로 만들어 놓고 static 블럭을 이용해 처음에만 초기화하고 그 다음부터 그 테이블에서 찾아서 쓰는 방식을 이용했다.

 

(마인크래프트 소스 코드를 올리는건 불법이라 하기에 단순히 원리만 적었다.)

 

-> sin 메소드에선 인수로 오는 각도(라디안) * 10430.378 을 리턴한다.

-> static 블럭에선 테이블을 초기화하는데 (인덱스) * 2 * (파이) / 65536 으로 초기화한다.

 

 

여기서 sin 과 cos 메소드 모두 60분법의 각이 아닌, Java Math 클래스와 같이 호도법의 각 즉, 라디안을 이용한다.

그리고 각의 범위는 0 <= radian < 2π 이다.

위에서 10430.378F 의 의미는 static 블럭을 보면 이해하기 쉽다.

static 블럭에서 Sin 테이블을 초기화하는데, 이 때 총 65536 개의 sin값이 초기화 되므로 각 element 간 간격(각도)은

이 된다.

 

이 때, i 번쨰의 각도 Θi 는

이 되는 것을 알 수 있다.

 

이를 이용해서 sin 메소드에서 10430.378F 의 정체를 알기위해 i 에 대해 정리하면

가 된다. 즉, theta 의 값에 위에서 계산한 근사치의 역수를 곱해주면 된다.

이때, 근사치의 역수를 계산해보면

이 나오는 것을 알 수 있다.

 

따라서 위에서 각도에 10430.378 를 곱하는 이유를 알 수 있다. (계산할 때 단순히 65536을 2π로 나눈다면 저 값이 나오지 않는다. (컴퓨터 계산방식 상) 맨 위에 있는 근사치의 역수를 계산하면 위와 같은 결과를 얻을 수 있다.)

 

 

자 이제 본론을 말하자면, 위 계산방식으로 어느 정도의 성능 향상이 될지 궁금해서 간단하게 테스트를 해보았다.

 

 

 

 

소스는 간단하다. 자바에서 제공하는 Math 클래스의 sin 메소드와 바닐라의 MathHelper 클래스의 sin 메소드에

각각 각도를 0.1 씩 증가해가면서 0 에서 2π 까지 루프를 돌며 계산을 한 뒤, 걸린 시간을 측정한다.

위의 실험으로 아래와 같은 결과를 얻을 수 있었다.

 

(나노초 단위)

1회: Java: 59085ns
      Vanilla: 57727579ns

 

약 977배 차이

 

2회: Java: 41981ns
      Vanilla: 61755265ns

 

약 1471배 차이

 

3회: Java: 37316ns
      Vanilla: 60502677ns

 

약 1621배 차이

 

평균적으로 1356배 정도 바닐라 소스가 자바 소스보다 느리다는 것을 알 수 있다.

(물론 단순한 테스트기 때문에 정밀도도 측정을 해봐야겠지만 아마 자바가 더 정확하지 싶다.)

 

이렇게 시간이 차이가 나는 이유는 기본적으로 자바 sin 메소드는 네이티브 함수를 호출하는 방식에다가

자바가 유독 부동소수점 연산이 느리기 때문에 그런듯 하다.

 

이걸 보며 굉장히 의아한 부분은 분명 속도를 빠르게 하려고 저렇게 대량으로 테이블을 만들어놓고 찾는 것일텐데 오히려 속도가 아주아주 느려진 것 이었다. (혹은 정밀도를 낮추거나 원하는 값이 나오게 하려한 것일 수도...)

 

그래서 간격을 점점 더 줄여가면서 0.01, 0.001 이런식으로 테스트 해봤더니

간격이 아주 작을 때, 0.000001 정도 부터 바닐라 소스가 자바 소스보다 속도면에서 우위를 차지했다. (물론... 2.5배정도..?)

 

이로부터 얻은 결론은

역시 마인크래프트는 최적화는 개나 줘버렸다는 것이다. (하하.. 쓸데없는 짓만 했네..)

댓글