본문 바로가기
프로그래밍 놀이터/안드로이드, Java

[android/안드로이드] 최적의 성능을 위한 앱 설계 방법. ( High Performance, 최적화를 위한 앱 설계 방법 )

by 돼지왕 왕돼지 2012. 2. 9.
반응형


안녕하세요 돼지왕왕돼지입니다.
오늘은 최적의 성능을 위한 앱 설계 방법에 대해 알아보고자 합니다.
최적의 성능이라는 말은, 최적화가 잘 된 앱, 또는 High Performance 를 내는 것을 말하는 것이겠지요?


안드로이드는 Mobile Device 라는 것을 명심하세요.


  이제 안드로이드폰에 쿼드코어를 장착하는 시대가 왔습니다. 즉 하드웨어가 엄청난 속도로 support 하고 있다는 말이죠. 하지만, 그래도 Desktop 에 비할 수는 없겠죠. 제한된 컴퓨팅 파워와 데이터 저장 공간은 모바일 장비가 가지고 있는 대표적 특성입니다. 이 부분을 항상 고려하여 설계를 해야 합니다.

 두번째는 작은 스크린입니다. 요즘 테블릿도 나오고, 아트릭스같은 경우 노트북 형태에 닥시킬 수 있는 등, 스크린은 조금씩 커지고 있지만, 역시나 일반적인 모니터에 비할 바가 아니죠. 요즘 대중적인 모니터는 21인치가 넘죠? 그러므로 View 를 효과적으로 배치하기 위해서, 작은 스크린이라는 특성을 반드시 고려해야 합니다.
 
 한정적 베터리 수명도 역시 고려사항입니다. 즉, 베터리 소모를 최소화하는 앱을 설계해야 합니다.

 
 

에뮬레이터에서의 성능 테스트 결과를 믿지 마세요.

 
에뉼레이터의 성능은 에뮬레이터를 돌리는 PC 의 성능에 크게 좌우됩니다. 아무리 에뮬레이터 옵션으로 이것 저것 잘 맞췄다고 해도, 에뮬레이터는 에뮬레이터입니다. 그러니 성능 등을 측정할 때는 실장비, 기왕이면 Target Device 에 테스트를 해야합니다. 간혹, 에뮬레이터에서는 잘 되도, 실 장비에서는 작동 안 하는 경우도 많이 발생합니다. ( 실 장비의 Framework 는 수정된 버전이기 때문에.. )
  


효율적인 코드를 짜는 것은 당연히 매우 중요하죠.


 최소한의 메모리 할당타이트한 코드미묘한 성능저하를 초래하는 언어와 프로그래밍 문구 피하기 등이 기초적으로 이루어져야 합니다.
자 그럼 최적성능을 위한 설계 및 코딩방법에 대해 자세히 살펴볼까요? 


오브젝트 생성을 피하라.


 오브젝트 생성은 메모리를 할당하는 작업으로, 일반 operation 에 비해 load 가 큰 편입니다. Java의 GC 는 매우 큰 operation 으로 구분되는데, 쓸데없는 메모리 할당으로 GC 를 초래하게 되면, 성능저하를 가져오죠. 물론 Ginger Bread 부터는 Stop-the-world GC 방식이 아니기 때문에 다행이긴 하지만, 그래도 딸꾹질 현상이라고 부르는, hiccups 현상을 초래합니다. ( 잠시 버벅대다가, 확~ 진행되는 현상 ).

Loop 에서의 새로운 오브젝트 생성은 특히나 피해야 할 이슈입니다.

다차원 배열을 1차원 배열로 만드는 것도 중요하죠.

결론적으로 이야기하자면, 단기적으로 사용되는 임시적 성격의 오브젝트는 생성부터 피해야 합니다.


Native Method를 사용하라.

 
 Native Method 들은 C/C++ 등으로 구현되어 있어 Java 코드보다 약 10~100배 빨리 실행됩니다. 따라서 Long Operation 의 경우 Native Method 들을 이용하여 구현하는 것이 좋습니다. ( 매우 사소한 연산을 지속적으로 호출하는 것은 피해야겠죠? )
 
 

내부적인 getters/setters를 피하라


일반적인 OOP 개념의 getter/setter 는 합리적입니다. 하지만 class 내부에서의 변수 접근에도 getter/setter 를 사용하는 것은 낭비지요.
 
 

Cache Field Loop ups


 맴버변수에 접근하는 것은 지역 변수에 접근하는 것보다 훨씬 속도가 느립니다. 그러므로 맴버변수를 여러번 사용하는 함수에서는 맴버변수 값을 지역변수로 가져와서 처리하는 것도 좋은 방법입니다.
 
예를 볼까요?
 
<느린 방법들>

1.
for (int i = 0; i < this.mCount; i++)
 dumpItem(this.mItems[i]);

2.
 for (int i = 0; i < this.getCount(); i++)
 dumpItems(this.getItem(i));

<빠른 방법>

int count = this.mCount;
Item[] items = this.mItems;
for (int i = 0; i < count; i++)
   dumpItems(items[i]);

 
한번 이상 맴버 인스턴스에 접근한다면 지역변수로 생성하는 것이 좋다고 합니다.
 

Constants 를 final로 선언하라


 컴파일러는 <clinit>라고 불리는 class initializer method 생성하며 이는 클래스가 처음 생성될 때 실행됩니다.
 final로 설정되지 않은 값들은 reference될 때 field lookup을 사용해서 접근하여 속도가 조금 느린 편입니다.
 반면 final로 설정하면 필드 룩업을 거치지 않고 바로 사용할 수 있습니다.

 변수에 이어, class와 function도 final로 설정함으로서 약간의 최적화는 노릴 수 있습니다.
 그래서 보통 익명의 inner class는 보통 final로 설정해서 사용을 하죠.
 

Enhanced For Loop 문법을 주의하여 사용


  for 문을 여러번 사용할 경우에는 특히나 object 생성에 주의해야 합니다. 횟수가 기하학적으로 증가할 수 있고, 이를 발견하기 어려울 수도 있기 때문이죠.


Enums를 피하라


 Enums 의 장점은 이미 익히 알려져 있습니다. 하지만 자주 쓰인다면 문제가 될 수 있습니다. Enums 의 접속 속도가 느리기 때문이죠. 
 따라서 Enums를 지속적으로 사용해야 할때는 local 변수로 돌린 후 사용해야 좋습니다.


모두가 알지만, 간과할 수 있는 2가지!

 
- 부동소수점(Float)을 가능한한 피하라

- 가능하면 곱셈 연산으로 (not 나눗셈)
 

자 그럼 어떤 Action 이 얼마만큼의 load 를 가지는 지 한번 살펴볼까요?
아래 시간은 비교값을 보기 위한 시간이지 절대적인 시간이 아닙니다.
그~렇게 유용한 자료는 아니지만, 어떤 작업들이 오래걸리는 작업인지는 "감" 정도 잡는데는 괜찮다고 생각하여 넣어봤습니다.


 액 션                                                                                                         시 간
하나의 로컬 변수 추가                                                                                      1
하나의 멤버 변수 추가                                                                                      4
String.length() 호출                                                                                         5
빈 정적(static) 네이티브 메쏘드 호출                                                                  5
빈 정적(static) 메쏘드 호출                                                                              12
빈 버추얼 메쏘드 호출                                                                                   12.5
빈 인터페이스 메쏘드 호출                                                                               15
HashMap에서 Iterator:next() 호출                                                                   165
HashMap에서 put() 호출                                                                               600
XML로부터 1개의 뷰 인플레이트(Inflate)                                                       22,000
1개의 TextView를 가지는 1개의 LinearLayout 인플레이트                               25,000
6개의 뷰 오브젝트를 가지는 1개의 LinearLayout 인플레이트                           100,000
6개의 TextView 오브젝트를 가지는 1개의 LinearLayout 인플레이트                 135,000
하나의 빈 액티비티 런치                                                                         3,000,000


자 모두들 최적의 앱을 짜도록 오늘도 화이팅 해봅시다요. 

 
로그인 없이 추천 가능합니다. 손가락 꾸욱~

반응형

댓글