본문 바로가기

Game/Unity

[Unity] 유니티 프로그래머가 알아야 할 최적화 코드작성법

하나하나 내용에 대해서 깊고 자세하게 작성할 수 없습니다.
자세한 내용에 대해서는 직접 검색해보시길 권합니다.


개인블로그에서 그룹블로그로 전환하면서 많은 글들을 삭제했습니다.
천천히 다시 정리합니다. 테스트는 모바일 기준입니다.



1. Loop


C# 자료구조에는 여러가지 루프문이 제공된다.
for, foreach, enumerator
어느 루프문을 사용해야 할까?
보통 본인에게 편한 루프문을 택한다.
하지만 성능이 다르다면?

- 테스트과정
각각루프를 도는 스크립트를 만들고, 하나의 스크립트에서 컴포넌트로 통합한다.
모바일로 빌드, 프로파일러를 확인한다.

테스트모바일은 갤럭시 노트3다.


-- 소스코드 --






-- 결과 --



- 정리 

Foreach는 속도도 가장 느리고, GC도 24Byte를 남겼다.

Enumerator는 Foreach보다 빠르게 동작했으며,

For는 Enumerator의 2배나 빠르게 동작한다.


가끔 프로파일러의 변동이 있을 때도 있지만 평균적으론 위 성능을 보인다.



- 추가

Dictionary<int, string>


-- 소스코드 --




--  결과 --



foreach

enumerator



이 부분을 보이는게 더 명확할듯 하다.

foreach문의 경우 그래프가 깨지는 구간이 더 많이 존재 한다. (프레임이 끊길 수 있다)

enumerator는 foreach에 비해 안정적이다.



- 결론

For문으로 루프문을 작성하지 못할 경우, enumerator

For문으로 루프문을 작성할 수 있을 경우, for






2. Parse


C#에서 지원하는 Parse는 여러가지가 존재한다.

그 중에서 가장 많이 사용하는 자료형은 string을 다른자료형으로 변환하거나 그 반대로 다른자료형을 string으로 변환하는 일이 잦다.

이번 테스트는 변환방법에 따른 성능을 테스트해본다.

string은 특수한 자료형이지만

그 외 기본자료형들은 비슷한 속도를 낼 거라고 생각한다.


- 테스트과정

string -> int, int -> string 각각루프를 도는 스크립트를 만들고, 하나의 스크립트에서 컴포넌트로 통합한다.
모바일로 빌드, 프로파일러를 확인한다.

테스트모바일은 갤럭시 노트3다.

(루프 10만번 돌렸다가 폰이 죽었다...)




-- 소스코드 --







-- 결과 --




- 정리

int -> string은 사실 이 결과를 믿을 수 없다.

최대한 평균값을 뽑으려고 노력했으나 그냥 뒤죽박죽이다.

코드로 평균값을 뽑아도 오르락 내리락한다.

그냥 입맛에 따라 쓰면 될 것 같다.


string -> int는 의외의 결과다.

tryParse가 눈에 띄게 느리지 않다.

코드로 평균값을 뽑아보면 1000회당 0.01ms정도 느리다.

안전한 코드를 위해 tryParse를 쓰는게 좋을 듯 하다.



- 결론

int -> string은 작성자의 입맛에 따라, string -> int는 tryParse를 사용한다.






3. string concat


C#에는 문자열병합하는 방법이 여러가지 존재한다.

그 중 가장 많이쓰는 + 연산자, string.concat

그리고 StringBuilder에 대해서 성능측정을 해보겠다.


- 테스트과정

딱 한번 이뤄지는 string 병합의 경우 프로그램에 영향을 미치지 않는다.

하지만, TableNumber_1,TableNumber_2,TableNumber_3...

이런식의 루프를 도는 구조는 말이 달라진다.

"abcd" + loopIndex 로 루프를 도는 Update문을 작성하고 ,

모바일로 빌드, 프로파일러를 확인한다.
테스트모바일은 갤럭시 노트3다.

마지막에 GC.Collect를 추가했다. 많은 GC를 남겨서 Collect가 자동실행되는 경우가 많아 프로파일러 확인이 어려웠다.



-- 소스코드 --





-- 결과 --






- 정리

프로파일러 결과는 변동 폭이 조금 있었으며, 위 결과는 가장 평균적이라고 보이는 결과다.

프로파일러를 보다시피 정리할 내용이 별로 없다. 바로 결론으로 넘어간다.



- 결론

StringBuilder가 속도도 가장 좋았으며 GC도 가장 적게 남겼다.

무조건 위와 같은 string 병합은 StringBuilder를 써야한다.






4. callback


c#은 간단한 방법의 callback을 제공한다.

그 중에 System.Action, System.Func<T>를 성능 테스트를 해본다.


- 테스트과정

System.Action을 인자로 받는 함수는 두가지 케이스로 나눈다.

인자가 null이면 실행하지 않는 함수

인자를 빈 delegate로 채우는 함수


System.Func는 그냥 콜하고 처리시간 정도만 알아본다.


모바일로 빌드, 프로파일러를 확인한다.
테스트모바일은 갤럭시 노트3다.


-- 소스코드 --





-- 결과




- 정리

UseDelegateEmpty와 UseFunction은 순서가 자주 뒤바뀐다.

평균적으로 비슷한 속도를 뽑아낸다.

null 체크의 경우 약 3배 빠르다.




- 결론

빈 delegate를 작성하지 말자.

소스코드의 안정성과 속도를 위해 callback을 받는 부분에선 무조건 null체크를 하고, null을 인자로 작성한다.







5. transform caching


우리는 유니티에서 transform에 접근 하는 경우가 잦다.

하지만 transform에 접근하는 게 성능에 부담된다는 사실은 잘 모른다.

그리고, 이 성능의 부담은 caching으로 해결 할 수 있다.


- 테스트 과정

루프를 돌며 this.transform.localPosition을 가져오는 두개의 스크립트 작성

하나의 스크립트는 transform을 재정의한다.


모바일로 빌드, 프로파일러를 확인한다.
테스트모바일은 갤럭시 노트3다.


-- 소스코드 --






-- 결과 --





- 정리

이 전에 정리된 사례들을 보면 어느정도 부담되는 지 감이 온다.

caching된 transform이 non-caching trnasform보다 2배정도 빠르다.




- 결론

transform에 자주 접근하게 되는 객체에선 caching은 선택이 아닌 필수다.



출처 : http://geekcoders.tistory.com/entry/Unity-%EC%9C%A0%EB%8B%88%ED%8B%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EA%B0%80-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%A0-%EC%BD%94%EB%93%9C%EC%9E%91%EC%84%B1%EB%B2%95

'Game > Unity' 카테고리의 다른 글

[unity3d] swipe  (0) 2015.03.27
[unity3d] fadein, fadeout  (0) 2015.03.27
Unity 5.0에서의 새로운 AssetBundle  (0) 2015.03.20
[unity3d]안드로이드에서 암호화 팁 - PlayerPref 암호화  (0) 2015.03.18
UNITY CLOUD BUILD 따라하기  (0) 2015.03.09