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

[도서 정리] 안드로이드 앱 성능 최적화 #3 하드웨어 성능과 배터리 수명

by 돼지왕 왕돼지 2018. 6. 24.
반응형


안드로이드 앱 성능 최적화 #3 하드웨어 성능과 배터리 수명



이 글은 “안드로이드 앱 성능 최적화” 의 일부 내용만 정리한 것입니다.

자세한 내용은 책을 구매하여 보세요~

activity manager proc, alarm, App Standby, battery historian, batterystats, bluetooth scan, charges, CPU, cpu 전력량, device position classier, doze, Doze Mode, dumpsys battery unplug, dumpsys betterystats, dumpsys deviceidle step, dumpsys usage stats, enable full-wake-history, exponential backoff, fallbacktime, Firebase Job Dispatcher, foreground process, framework-res.apk, GCMNetworkManager, geomagnetic, getpower, gps 전류 소모량, Gyroscope, idle_maintenance, inexact alarm, jobscheduler, Light, mobile radio activity per app, ms per packet, MSPP, Orientation, phone scan, phone state, Reset, rotation vector, SENSOR_DELAY_GAME, SENSOR_DELAY_NORMAL, syncmanager, system stats, system/frameworks, temp whitelist, userspace wakelock, wakelock, wifi scan, 데이터 사용량, 도즈 모드, 도즈 모드 조건, 도즈 모드 테스트, 도즈 프레임워크, 마시멜로, 무선 신호 전력, 무선망, 배터리 모니터링, 배터리 소모 원인, 배터리 수명, 배터리 정보, 센서 리스너 해지, 센서 사용 빈도, 센서 전력량, 안드로이드 앱 성능 최적화 #3 하드웨어 성능과 배터리 수명, 안드로이드 전력 프로파일, 앱 스탠바이, 앱별 배터리 소모량, 이동 통신망 와이파이 배터리, 전력 소모량 xml, 전력 프로파일, 전력 프로필, 전력량 xml, 전력량 기술 xml, 절전 모드, 하드웨어 성능, 화면 전력량, 활성화 전력 소모

3.1. 안드로이드의 하드웨어 기능





3.2. 덜 써야 더 쓴다.


-

구글에서는 단 1초동안 기기가 활성화되어도 2분 동안 대기하는 것과 비슷한 전력을 소모한다고 한다.

넥서스 5 기준 대기 시간(LTE 나 와이파이 연결되어 있지만 기기를 사용하지 않음) 은 약 300시간 ( 12.5일 ).

그러나 와이파이로 인터넷을 사용하기 시작하면 약 8.5시간 사용 할 수 있다.

즉 대략 5분 동안 일반적인 앱을 사용하면 약 1~1.6% 의 배터리가 소모된다.

앱이 더 많은 동작을 하면 더 많은 배터리가 사용된다.



-

광고를 포함한 앱에서 광고만 제거했을 경우 CPU 56%, 메모리 22%, 배터리 15% 를 덜 사용하는 것으로 나타났다.





3.3. 배터리가 빨리 소모되는 원인은 무엇인가?


3.3.1. 안드로이드 전력 프로파일


-

안드로이드 OS 내에는 기기의 주요 장치들을 사용할 때 얼마만큼의 전력이 소모되는지에 대한 정보를 기술해놓은 XML 파일이 있다. ( XML 내 단위는 mA )

앱이 실행되고 기기 내의 장치들이 사용되기 시작하면 시스템은 각 부품에서 사용하는 전력량을 이 프로필 기반으로 계산하고 이를 프로세서별 배터리 사용량으로 기록한다.



-

오늘날 모바일 기기에서 가장 높은 전력 사용량을 보이는 것은 화면, 무선망(이동통신망, 와이파이, 블루투스, GPS), CPU(특히 클럭이 높을 때) 이다.



-

전력 프로파일 XML 은 framework-res.apk 에 포함되어 있다.

이 apk 는 system/frameworks 폴더에 있다.




3.3.2. 화면


-

LCD 는 각 픽셀에 해당하는 다양한 색을 만들어내는 수천 개의 액정과 이걸 밝게 만드는 백라이트로 구성된다.

각 픽셀은 색상을 만드는 데는 최소한의 에너지만 사용한다.

대부분의 에너지 소모가 액정을 밝게 만드는 데 쓰인다.

즉 픽셀을 표현하는 비용은 어떤 색을 표시하든지 동일하다는 것이다.



-

LED 는 학 픽셀이 색상도 표현하고 발광도 한다.

각 픽셀은 R,G,B 의 LED 배열로 구성된다.

휘도와 각 LED 색을 변경해서 픽셀에 원하는 색을 표현한다.

한 픽셀이 색상별로 각각 강도가 다른 세 개의 광원에 의해 표현되기 때문에 색에 따라 사용하는 전력량이 다를 수 있다.

검정색은 각 색상 LED 를 가 꺼서 표현하기 때문에 전력을 사용하지 않는다.

반대로 하얀색의 경우는 세 가지 모든 LED 를 높은 밝기로 켜서 표현하기 때문에 가장 많은 전력을 사용한다.

다시 말해 어두운 색상이 밝은 색상보다 적은 전력을 표현한다는 것이다.




3.3.3. 무선 신호


-

전력 프로파일 값으로 보면 이동 통신망과 와이파이가 비슷한 전력을 소모한다.

일반적으로 이동 통신망은 전화신호 세션을 더 길게 유지하려고 와이파이보다 좀 더 오랜 시간동안 연결을 유지한다.

그래서 와이파이보다 더 많은 배터리를 사용한다.



-

무선신호를 사용하는 앱을 개선하는 가장 좋은 방법은 한 번에 가능한 많이 다운받고 작업이 끝나면 무선신호 사용을 빠르게 해제하는 방법이다.



-

위치 정보를 사용할 때 필요한 정보 정확도를 알고 있으면 많은 시간과 전력을 아낄 수 있다.

만약 대략적인 정보만 필요하면 GPS 없이 이동 통신망으로도 충분한 정확도의 위치 정보를 제공받을 수 있다.

현재 전화망이 연결된 통신 타워의 위치가 기기에 저장되어 있기 때문에 사용자가 움직이지 않고 위치 정보를 요청했다면 이동 통신망의 추가 연결조차 필요하지 않은 경우가 생길 수도 있다.



-

GPS 를 이용할 때 고객이 콘크리트 건물 안에 있을 수 있다.

이런 경우 적절한 시간 안에 GPS 정보를 얻지 못하면 GPS 사용을 멈춰야 한다.




3.3.4. CPU




3.3.5. 추가 센서


-

센서의 전력 사용량은 getPower() 메서드를 통해 얻을 수 있다.

Gyroscope, Light, Geomagnetic, Rotation Vector, Orientation, Device Position Classier 등이 전력을 많이 사용한다.



-

센서를 사용할 때는 앱에서 꼭 필요한 정도의 빈도를 지정해주는 것이 중요하다.

센서의 전력 소모뿐만 아니라 과도하게 수집된 데이터를 처리하기 위해 CPU 나 메모리도 낭비 될 수 있다.

안드로이드에는 미리 지정된 빈도(SENSOR_DELAY_NORMAL, SENSOR_DELAY_GAME 등) 값이 있다.



-

마지막으로 센서를 다 사용하고 난 후에는 꼭 해지해야 한다.

센서 리스너를 계속 유지시키면 센서들은 계속 앱에 데이터를 전달하게 된다.




3.3.6. 절전 모드!




3.3.7. wakelock 과 alarm


-

alarm 을 사용하면 앱이 포그라운드에 있지 않을 때는 물론 심지어 대기 모드에 있더라도 수행된다.



-

정확한 시간에 알림을 띄우기 위해서라면 시간을 지정해 alarm 을 사용 할 수 있다.

정확한 시간이 필요 없다면 inexact alarm 을 사용할 수 있다.

배터리 소모를 최소화하기 위해 OS 에서 alarm 의 발생 시간을 조정하는 방식으로 동작한다.




3.3.8. 도즈 프레임워크


-

배터리 용량의 70% 정도는 앱이 대기모드에서 업데이트를 위해 무선망 접속을 하면서 소모된다고 한다.



-

마시멜로(MOS) 부터는 기기가 자주 깨어나는 것을 시스템 차원에서 제한시키는 도즈 프레임워크(Doze framework)가 포함되었다.

도즈 프레임워크는 아래의 상태들이 있다.


ACTIVE

    화면이 켜져 있음

INACTIVE

    화면이 꺼져 있지만 기기는 활성화된 상태

IDLE_PENDING

    DOZE 모드에 빠지기 직전 상태

IDLE

    기기가 대기상태로 전환됨

IDLE_MAINTENANCE

    잠시 동안 대기열에 있던 alarm 과 업데이트를 처리하는 관리 상태



-

마시멜로우 기기에서 강제적으로 도즈 모드를 테스트하려면 아래와 같은 명령을 사용하면 된다.


adb shell dumpsys battery unplug // 전원 연결 해제 상태로 만드는 트릭

adb shell dumpsys deviceidle step // 특정 상태로 진입하기 위한 명령



-

실제로 도즈모드에 들어가려면 화면을 끄고 30분 정도 움직임이 없어야 INACTIVE -> IDLE_PENDING 으로 전환되고, 이 상태로 30분정도 더 지나야 IDLE 상태가 된다.


일단 IDLE 상태가 되면 모든 alarm 은 다음 번 관리 상태가 될 때까지 연기된다.

각 IDLE_MAINTENANCE 상태의 간격은 1시간, 2시간, 4시간, 6시간으로 반복될수록 증가한다.

그리고 모든 alarm 과 wakelock 은 다음 번 관리 상태가 될 때까지 연기된다.



-

개발자는 도즈 모드 상태에서 여러 번의 통보를 받아도 한 번만 알림 메시지나 소리가 출력되는지 등을 잘 확인해봐야 한다.






3.4. 기본적인 배터리 소모 분석


-

이제는 일반 사용자들도 쉽게 배터리 소모를 설정을 통해 볼 수 있기 때문에, 여기에 배터리 소모가 큰 앱으로 표시되지 않도록 하는 것이 매우 중요하다.




3.4.1. 앱별 배터리 소모량


-

배터리 메뉴에 나오는 데이터 사용량은 최종 충전 이후에 주고 받은 데이터 사용량만을 수집한다.

충전할 때에는 이 통계 데이터를 자동으로 초기화한다.

마지막 충전 이후의 데이터 사용량을 가지고는 데이터 사용이 효율적인지 판단하기 어렵다.



-

킷캣 베터리 메뉴에서는 데이터 사용량 표시가 데이터 총량 기준이었지만, 롤리팝부터는 패킷 수를 보여주도록 바뀌었고 와이파이와 무선 통신을 구분하도록 변경되었다.




3.4.2. 배터리 정보와 데이터 사용량의 결합


-

만약 패킷의 개수는 아주 많은데, 얼마되지 않는 데이터양을 전송하거나 아주 낮은 전송 속도를 보이는 앱이 있다면 데이터 사용을 제한하거나 앱 백그라운드 데이터 제한을 지정하는 것도 좋다.

이런 앱들은 비효율적으로 무선망을 사용하고 있는 것으로 판단되며, 잠재적으로는 추가 전력 소모를 일으키는 원인이 될 수도 있다.




3.4.3. App Standby


-

마시멜로(MOS)부터 App Standby 라는 새로운 기능이 추가되었다.

이는 기기가 배터리로 구동될 때 자주 사용되지 않는 앱들이 네트워크를 연결하거나 프로세스를 실행하는 등의 동작을 하지 못하도록 예방해주는 기능을 담당한다.

거의 사용하지 않는 앱 때문에 배터리가 소모되는 것을 방지할 수 있다.



-

adb shell dumpsys usage stats 명령을 사용하면 앱들이 최종 사용된 날/주/월/년 정보를 얻을 수 있다.

여기에는 각 프로세스가 언제 마지막으로 활성화되었는지가 표시된다.





3.5. 배터리 모니터링 심화 과정


3.5.1. batterystats


-

batterstats 는 기기가 배터리를 어떻게 사용했는지에 대한 거대한 데이터 덤프로 구성되어 있다.

킷캣에서 도입되었고 롤리팝부터는 모든 wakelock 관련 행위들의 로그를 포함하는 더욱 방대한 정보가 추가되었다.



-

adb shell dumpsys betterystats —reset // 분석용 정보 수집 위해 초기화, Setting 에 있는 값도 모두 초기화된다.

adb shell dumpsys batterystats —enable full-wake-history // 상세한 정보를 위해 wakelock 수집 옵션 on

adb shell dumpsys batterystats —charges // 완충된 상태의 배터리 정보를 가져온다.



-

data 중에는 mspp ( ms per packet ) 정보가 있는데 이 값은 작을수록 좋다.




3.5.2. Battery Historian


-

batterystats 을 통한 출력시 세부 사항들은 앱이 기기의 배터리 소모에 어떤 영향을 미치는지 파악하는 데 큰 도움이 된다.

그러나 텍스트로 된 아주 긴 출력을 살펴보는 데 많은 시간이 소요된다.

이를 좀 더 쉽게 분석할 수 있도록 구글에서는 Battery Historian 이라는 도구를 만들었다.

이 도구를 사용하면 batterstats 출력을 가지고 잘 분석된 보고서를 만들어준다.



-

Battery Historian 2.0 버전은 롤리팝 이후의 기기를 사용하여 배터리 정보를 더 상세하게 보여준다.

스크립트를 통해 웹페이지를 생성하지 않고(2.0 이전 방식) 서비스를 9999 포트로 구동해서 결과를 분석하고 보고서를 보여준다.



-

CPU running

    CPU 사용 여부

Kernel only uptime

    CPU 가 커널만을 위해 사용될 때 표시

Userspace wakelock

    wakelock 을 사용하는 앱 목록

Screen

    화면이 켜져 있는지 여부. 커서를 올리면 화면이 켜진 이유가 함께 표시

Top app

    화면에 보여지고 있는 앱 목록

Activity Manager Proc

    Activity Manager 가 구동되고 있을 때 표시

Doze

    시스템의 Doze 모드 여부.

Device active

    기기의 활성화 상태 여부

JobScheduler

    JobScheduler API 사용해 특정 작업 수행 시 표시

SyncManager

    서버와 동기화를 처리하는 SyncManager 작업 표시. 커서를 올리면 원인 정보 제공

Temp WhiteList

    일시적으로 네트워크 접속이 허용된 앱의 목록 (높은 우선순위를 갖은 GCM 메시지 수신 등)

Phone call

    전화 사용 여부

GPS

    GPS 를 사용하는 앱 목록

Bluetooth scan(logcat)

    블루투스 스캔 여부 표시

Phone scanning

    모바일 네트워크 신호가 없는 경우에 스캔을 시작한다.(배터리가 더 소모된다.)

Phone state

    셀룰러의 적용 범위가 변화하거나 전화를 사용하는 경우에 표시

Mobile network type

    현재 사용 중인 모바일 네트워크 타입을 보여준다.

Mobile radio active

    무선 통신망에 연결된 시간(꼭 송수신이 안 되어도), LTE, HSPA, HSDPA 등이 적용된다.

Mobile singal strength

    무선 통신망의 신호 강도 (poor, good, great 단계로 표시)

Wifi full lock

    와이파이를 강제로 활성화 상태로 유지시킬 때 표시

Wifi scan

    와이파이 접속을 위해 신호를 스캔

Wifi supplicant

    와이파이 접속 상태에 대한 정보 표시

Wifi radio

    와이파이 신호가 활성화 상태일 때 표시

Wifi signal strength

    접속되어 있는 와이파이 신호 강도, 와이파이 고급 설정에서 “와이파이 연결 유지”를 켜 놓으면 와이파이가 꺼져 있을 때도 신호를 검출

Wifi multicast

    와이파이 멀티캐스트가 사용될 때 표시

Wifi running

    와이파이가 동작 중인지의 여부 표시

Wifi on

    와이파이가 켜져 있는 상태인지 여부

Video

    비디오 재생 여부

Foreground process

    포그라운드 프로세스가 표시. 포그라운드에서 실행되는 앱은 메모리 제한을 덜 받아 죽을 가능성이 적다.

    대부분은 기기 내부에서 실행 중인 프로세스이다.

Package install

    앱이 설치될 때 그 목록이 표시된다.

Package active

    어떤 상호 작용으로 인해 앱이 활성화 될 때 표시

Temperature

    기기 온도 표시, 일반적으로 배터리 소모가 많아질 때 온도가 올라간다.

Battery level

    배터리 충전 상태가 표시

Plugged

    전원 연결 상태 여부

Charging on

    충전 상태 여부

Logcat misc

    기타 정보 표시



-

기기를 깨울 때 inexact alarm 이나 JobScheduler API 를 사용하게 되면 여러 동기화 또는 wakelock 이 한 번에 몰려서 발생하는 걸 확인할 수 있다.



-

Battery Historian 으로 과도한 wakelock 을 찾을 수 있다.

먼저 배터리 그래프가 가파르게 감소하는 부분을 찾는다.

그 부분에 마우스 커서를 올리면 경사 구간이 빨간색으로 표시된다.

만약 Screen 부분이 사용 중임을 의미하는 빨간색으로 표시되고 있지 않은 상태라면 이 부분을 의심해 보는 것이 좋다.


이 구간의 Userspace wakelock 으로 마우스 커서를 이동한다.

여기에 나열된 정보만으로 정확히 어떤 앱이 문제가 되는지 판단하기 어렵다.


이 때 하단의 System stats 부분의 Userspace wakelocks 와 Mobile Radio Activity Per App 부분을 확인해 보는 게 좋다.



-

Screen 이 켜져 있지 않은 상태에서 CPU 를 계속 사용하거나 네트워크를 사용하는 부분이 발견되면 이것도 배터리 소모의 주 원인이 될 수 있다.



-

wakelock 과 alarm API 의 상태와 같이 wakelock 의 행동을 의식하는 것이 중요하고 그것이 안드로이드 기기의 배터리 최적화에 많은 영향을 준다.

그러나 Doze 모드가 적용되어 이러한 wakelock 을 과도하게 발생시키는 앱을 찾아내기가 어려워졌다.

앱을 테스트해 보려면 마시멜로 이전(Doze 모드가 MOS 부터 적용) 기기를 이용해서 테스트해 보는 게 좋다.



-

Battery historian 구동법은 https://developer.android.com/studio/profile/battery-historian.html 참조





3.6. JobScheduler


-

롤리팝(5.0)부터 추가된 API 이다.

이 프레임워크를 사용하면 wakelock 과 alarm 을 직접 사용하지 않고도 앱에서 추가 작업을 수행할 수 있다.

wakelock 과 alarm 은 각각 앱별로 동작하지만 JobScheduler 는 기기를 깨우는 시점을 OS 가 적절히 조정할 수 있다.


예를 들어 5개의 앱이 매 30분마다 깨어난다고 하자.

알람이 동기화되어 있지 않다면 1시간 동안 10번 기기를 깨우게 된다.

JobScheduler 가 "8분에서 10분 사이” 와 같이 특정한 시간 범위를 지정할 수 있도록 API 를 제공하기도 하며, 이 정보들을 바탕으로 JobScheduler 는 기기를 깨우는 작업을 시스템이 담당하도록 위임한다.

그리고 시스템은 모든 예약된 작업에 대해 기기가 깨어나는 것을 최소화시키는 방향으로 구동하게 되어 작업을 효율적으로 동작시킬 수 있다.



-

JobScheduler(이하 JS)는 유용한 기능들이 많다.

    주기적으로 서비스를 실행하고 네트워크 연결을 보장한다.

    와이파이와 같은 무료 데이터망에서만 작업을 수행하도록 지정할 수 있다.

    기기가 대기(Idle) 중일 때만 동작하도록 지정할 수 있다.

    기기가 충전 중일때만 작업을 수행하도록 할 수 있다.

    작업이 처리가 안 되는 경우에 접속을 시도하는 시간 간격을 점차 증가시킨다. (linear or exponential)

    ...



-

JS 를 사용하게 되면 15%~20% 정도 배터리 소모를 줄일 수 있다고 한다.



-

재시도 시간 간격을 Linear 혹은 Exponential 로 지정할 수 있다.

Linear 는 현재 데드라인에 fallbacktime * (실패횟수-1) 을 더한다.

Exponential 은 데드라인에 fallback * 2^(실패횟수-1) 이 더해진다. 



-

JobScheduler 는 LOS 이상부터 지원되므로, JS 와 비슷한 기능을 제공하는 GCMNetworkManager를 사용하는 것도 좋다.

JobScheduler 의 API 와 비슷하게 수행할 시간을 지정하거나 반복적으로 수행하는 작업을 시스템이 스케줄링하게 만들어 배터리 효율성을 높인다.

GCMNetworkManager 는 구글 플레이 서비스(Google Play Service)가 설치되는 안드로이드 2.2부터 지원하므로 API 레벨 제한이 적으면서 JobScheduler 의 장점을 활용 할 수 있다.


https://developers.google.com/cloud-messaging/network-manager


구글 I/O 2016 에서 GCMNetworkManager 를 Firebase Job Dispatcher 로 교체한다고 발표했다.

비슷한 기능을 제공하며, 좀 더 명확한 API 를 가지고 있다.

따라서 새로운 앱에서는 Firebase 를 사용하는 것이 좋다.





3.7 결론


-

배터리 수명은 앱 성능을 판단하는 탁월한 지표이다.

배터리를 비효율적으로 사용하는 앱들을 살펴보면 기기를 과도하게 깨우거나 아예 대기 모드로 빠져들지 못하게 만드는 경우가 많다.

롤리팝 이후의 기기에서는 Battery Historian 을 이용해 자세한 분석 정보를 제공받을 수 있다.

또한 JobScheduler API 가 운영체제 수준에서 여러 앱들이 깨어나는 시간을 통합/관리하도록 해서 백그라운드 호출 횟수를 줄여주기도 한다.




반응형

댓글