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

[android] 성능에 대한 미신들을 때려잡자! ( from Dev Summit 2019 )

by 돼지왕 왕돼지 2019. 11. 16.
반응형




-

Performance 에 대해서는 항상 measure 를 해봐야 한다.





* Kotlin


-

Kotlin app 은 더 size 가 크고 느릴 것이다.



-

단순한 밴치마킹용 심플 코드가 아닌, Google Drive 를 converting 해보았다.


16K lines / 171 Files / 41 Build Target


Startup time 은 동일 / 25% code line 줄어듬 / 2% 정도 compile code size 가 줄어듬

성능은 동일하지만, 유지보수해야 하는 코드가 줄어들었다는데 큰 의미가 있다.





* Code pattern


Fields Access Patterns (getter/setter)

    getter/setter 는 expensive 할 것이다.

    Jetpack benchmark lib 으로 측정했다. ( prewarm 도 진행해준다. )


    no difference

    ART team 에서 예상했던 데로다. ART 가 이런 access 를 compile 시 inline 시킨다.

    

    그러므로 encapsulation 을 해치지 않는 get/set 을 쓰자.




Using Lambdas

    Lambda 는 inner class 사용보다 느릴 것이다.

    

    no difference

    lambda, nested class, top level class 모두 동일하다.

    lambda 가 anonymous inner class 로 변신하기 때문에 동일할 수밖에 없다.


    그러므로 가독성 측면에서 이로우며, 추후 개선 여지가 있는 lambda 를 사용하자.





* Memory


안드로이드의 Memory allocation 은 느리다.

    지속적으로 개선해서 빨라지고 있다.

    L 에서는 Custom Allocator

    O 에서는 Bump Pointer

    O부터는 super fast 라고 부를 수 있을 정도이다.




    Myth 로 인해 Pool 을 사용하는 방식이 많이 사용되었다. ( no allocation & no gc )

    Pool 에서 put/retrieve 하는 과정에서 synchronize 를 보통 하게 되는데, 이와 allocation 을 비교하면 거의 비슷한 성능을 보인다.

    Pool 이 장점을 가질 때가 있지만, Pool 은 foot print 측면에서 단점이 있다.

    보관하는 object 의 size 가 클 경우는 성능상의 단점을 보이기도 한다.

    그래서 꼭 필요한 경우가 아니라면, 이미 memory allocation 과 gc 는 출분히 빠르니 pool 대신 그냥 로직을 짜는 것이 조금 더 추천된다고 볼 수 있겠다.

    물론 Pool 을 쓰지 말라는 것은 아니다. create 가 expensive 한 것은 pool 을 쓰는게 더 유용할 수 있다. 잘 보고 쓰자.




안드로이드의 GC 는 느리다.

    GC 도 지속적으로 개선해서 빨라지고 있다.

    GC 는 더 이상 Stop-the-World collection 을 사용하지 않는다.

    jank 등은 최소화되었다.

    Android 10 에서는 generational concurrent collection 이 더 빨라졌다.

    Google Sheet 에서는 68% 정도의 개선이 있었다.








* Profiling


Debuggable app 을 profiling 하는 것은 괜찮다.

    debuggable=true 일 때는 측정결과가 중구난방이었다.

    그러나 동일한 것을 debuggable=false 로 두니 일관된 결과를 보였다.


    또한 비교가 아닌 절대적 시간을 볼 때는 더 이슈가 되는데,

    debuggable=true 와 false 의 view inflating 에서는 성능이 2배 차이가 났다.


    그 이유는 runtime 에서 debuggable 일 때는 코드 최적화를 별로 하지 않는다.

    그래서 production build 에서의 코드와는 한참 다를 것이다.





* Strange things


Multidex 가 성능에 영향이 있니? Dex file 이 클수록 영향이 있니?

    계산기앱을 single dex 와 multi dex 로 나누었을 때

    

    startup time 은 차이 없음.

    Apk size 는 조금 늘어남.

    메모리 사용도 조금 늘어남.  ( 중복 data 를 가진다. cache, symbol table 등의 영향으로 )


    Custom 으로 dex 를 split 할 떄는 main dex 에 뭐가 들어있느냐가 성능에 영향을 미칠 수 있다.

    따라서 R8/D8 을 통해 가 알아서 하도록 두는게 최선이라고 본다.




니 생각보다 Dead code 가 많을 것이다.

    ART profile 이 Android P 이상에서는 자주 쓰이는 함수들에 대해 profile 을 진행한다.

    그리고 시스템은 이 profile 정보를 바탕으로 optimization 을 진행한다.


    구글 코드를 봤을 때 앱의 14% 정도만 profile 되었다.

    86% 는 거의 실행되지 않았다고 볼 수 있다.

    많은 에러 핸들링, 호환성 코드 등이 있기 때문이다.

    그리고 자주 사용되지 않는 기능들도 당연히 있을 것이다.


    R8 을 사용해서 shrink 를 하라.

    자주 사용하지 않는 코드를 제거하라. (apk 사이즈 줄이자)





* 직접 해봐라


-

Android Studio 가 profiler 를 가지고 있다.

Kotlin, Java, Native code 모두 가능하다.



-

Perfetto & Systrace

아주 자세한 정보를 보여준다.



-

Jetpack Benchmark lib





끝!



반응형

댓글