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

Android 놓치기 쉬운 안드로이드 성능 향상 팁

by 돼지왕 왕돼지 2014. 4. 3.
반응형


 Android 놓치기 쉬운 안드로이드 성능 향상 팁

 

 Android 놓치기 쉬운 안드로이드 성능 향상 팁

출처 : http://developer.android.com/training/articles/perf-tips.html


아래 두가지 규칙이 모든 성능 향상의 기본 법칙이다.


1. 필요 없는 일은 하지 말아라.


2. 피할 수 있다면 memory 를 잡는 일을 하지 말아라.


참고로 micro-optimization 을 한다고 해도 모든 단말에서 똑같은 성능향상이 있는 것이 아니다.

VM 의 종류, Processor 의 종류에 따라서도 조금씩 다르고, JIT 의 유무에 따라서도 다르다.


아래 항목들은 대부분의 환경에서 최적화시킬 수 있는 micro-optimization 기술을 소개한다.



쓸 데 없이 객체를 생성하지 말자.


GC 를 유발하며, GC 는 concurrent gc 가 진저브레드부터 도입되어 hiccups 현상은 완화되었지만, 

그래도 전체적 성능하향으로 버벅대는 효과를 가져온다.


new String 같은 것도 피하고, Integer 대신 int 를 사용하며, multidimension array 보다는 single array 로 multidimension 을 커버하는 것이 좋다.


잠깐만 사용되는 임시 오브젝트는 가능하면 생성하지 않는 것이 좋다.




Virtual 보다는 Static


어떤 함수가 class 의 field 를 접근하지 않는다면 static method 로 바꾸자.

이 경우 invocation 할 때 15~20% 더 빠르게 작동한다.




Constants 에는 static final 을 부여하자.


field 들이 final static 으로 정의되어 있으면 class 를 초기화할 때 clinit 함수를 통하지 않아도 된다.

이들은 이미 dex file 의 static field initializer 에 포함되어 있다.

 

참고로 primitive type 과 String type 의 constants 외에는 static final 로 부여한다고 해도 성능향상은 없다.

하지만 상수에 final static 을 붙이는 것은 여전히 좋은 습관이다.







Avoid Internal Getter / Setter


일반 환경에서는 internal getter, setter 를 사용해도 큰 지장이 없지만,

Android 와 같은 mobile 환경에서는 잦은 getter, setter 호출 역시 expensive 하게 여겨질 수 있다.

JIT 이 없는 환경에서는 3배정도 성능향상이 있고,

JIT 이 있는 환경에서는 7배정도 성능향상이 있다.


proguard 를 사용하는 경우에는 inline accessor 를 제공하기 때문에 어떤 것을 사용해도 괜찮다..




Enhanced For Loop 를 사용하자.


Enhanced For Loop 라 하면 for-each loop 를 이야기한다.

for-each 는 Iterable interface 를 구현한 collection 혹은 array 에 대해 사용할 수 있다.

ArrayList 의 경우는 for-each loop 를 쓰지 않은 것이 약 3배 정도 빠르다!!!!!

하지만 그 외의 collection 의 경우에는 iterator 를 사용하는 것과 for-each 를 사용하는 것이 더 좋다.


loop 를 사용할 때는 length 부분을 local variable 로 만들어 사용하고,

collection 혹은 array 를 localize 해서 사용해야 더 좋다.

하지만 가능하면 for-each 를 사용하는 것이 가장 빠르다.

JIT 이 없는 환경에서는 for-each 가 더 빠르지만, JIT 이 있는 환경에서는 최적화된 일반 for 와 성능이 비슷하다.


결론적으로 일반적으로는 for-each 를 사용하는 것이 가장 좋고, ArrayList 에 대해서만 일반 for 문을 사용하는 것이 좋다.




Private inner class 에서 Outer class 의 variable 을 접근하는 경우 private 보다는 package accessor 를 사용하자.


public class Foo {

    private class Inner {

        void stuff() {

            Foo.this.doStuff(Foo.this.mValue);

        }

    }


    private int mValue;


    public void run() {

        Inner in = new Inner();

        mValue = 27;

        in.stuff();

    }


    private void doStuff(int value) {

        System.out.println("Value is " + value);

    }

}


 사실 자바 언어에서는 위와 같은 inner class 에서의 outer class 의 private variable 의 접속을 문법적으로는 허락하지만,

VM 에서도 그런 것은 아니다. VM 에서는 static method 를 생성해서 접속하도록 한다.







/*package*/ static int Foo.access$100(Foo foo) {

    return foo.mValue;

}


/*package*/ static void Foo.access$200(Foo foo, int value) {

    foo.doStuff(value);

}


이는 성능저하가 나타날 수 있기 때문에 private field 를 package accessor 로 만드는 것이 좋다.

단 이럴 경우 외부에서 바로 접근할 수 있기 때문에 좋지 않다는 단점이 있기에, public API 같은 데서는 피해야 한다.




Floating-Point 사용하지 않기.


floating point 는 integer 에 비해 안드로이드 단말에서 약 2배정도 느리다.

desktop 에서는 double 과 float 의 차이가 거의 없기 때문에 double 을 쓰는 것이 좋다.




Library 를 잘 알고 사용하자.


System library 의 경우는 성능을 위해 aseembly 로 작성된 것도 있고, inline 처리를 하기도 해서 성능이 좋다.

JIT 가 생성한 같은 기능의 JAVA 코드보다 대부분 속도가 빠르다.

String.indexOf() 가 한 예고, System.arraycopy() 는 똑같은 로직을 하는 최적화된 코드로 작성했을 때에 비해 9배 빠르다.




Native Method 는 조심해서 사용하자.


NDK 를 사용해서 개발하는 것이 무조건 항상 효율적인 것이 아니다.

Java-native transition cost 가 그 대표적 이유이다.

게다가 native heap 에 memory allocation 을 하면 이를 해제하는 것이 pure java 만큼 쉽지 않다.

그리고 native code 가 architecture ( CPU, VM 등 ) 에 dependent 하기 때문에 호환성 문제도 생긴다.


native code 는 기존의 native codebase 가 있을 때 사용하는 것이 좋고,

그저 코드 일부분을 speed up 하기 위해 사용하는 것은 권장되지 않는다.




성능에 대한 미신.


JIT 이 없는 device 에서는 정확한 type 으로 method call 하는 것이 더 효과적이다.

예를 들면 HashMap map 을 param 으로 가지고 있는 함수보다 Map map 을 param 으로 가지고 있는 함수가 2배정도 느리다고 알져 있다.

하지만 실제로는 6% 정도만 느리다고 한다.

그리고 JIT 가 있는 경우에는 둘의 차이가 크지 않다.


JIT 가 없는 경우에는 local field access 가 global field access 보다 20% 더 빠르다.

하지만 JIT 환경에서는 거의 비슷하다.







항상 측정하라.


Optimization 을 하기 전에 해결하고 싶은 문제를 확실히 구체화시켜라.

현재 성능을 측정하고, 최적화 후의 성능을 또 측정하라.


TraceView 도 profiling 에 좋다.

하지만 traceview 를 사용할 때는 JIT 가 disable 된다.

그래서 traceview 가 도는 동안에는 속도가 좀 저하된다.






반응형

댓글