1. CPU상태 확인하기
:Traceview
따라하기,
함수/ 클래스별 CPU 실행 시간 확인
:녹음기 사용하는 것과 비슷(녹음버튼 à 녹음 à 녹음종료버튼 à 녹음확
인)
STEP1.
프로파일 메소드 실행
STEP2.
어플리케이션 동작
STEP3.
프로파일 메소드 종료
분석
STEP1.
프로파일 메소드실행
3)Start
Method
Profiling 클릭
: 지금부터 어플리케이션의 모든 동작은 프로파일링
클릭을 하고나면 위와 같은 아이콘으로 변경(동작상태)
57.
STEP2.
어플리케이션 동작
ex
:
사진업로드 하는 과정에서 함수/클래스별 CPU사용 시간을 확인
-‐프로파일 메소드를 실행한 상태에서 확인하고자 하는 동작을 직접 실행
58.
STEP3.
프로파일 메소드종료 분석
Stop
Method
Profiling
를 클릭하면 아래와 같은 분석결과가 팝업
59.
STEP3.
프로파일 메소드종료 분석
1. A)는 CPU를 사용한 메소드/클래스를 시간대 별로 보여줍니다.
2. B)는 전체 CPU사용량을 100%라고 했을 때 각 메소드/클래스의 사용량을
보여줍니다.
A)
B)
60.
STEP3.
프로파일 메소드종료 분석
-‐
A
1. 시간의 범위를 지정하면 보다 자세히 시간대별 사용량을 볼 수 있습니다.
2. 각 색이 뜻하는 것은 사용량을 나타내는 표(B)의 색과 일치합니다.
ex)
Dalvik/system/VMDbbug.StargGC
()
61.
STEP3.
프로파일 메소드종료 분석 -‐
B
1. 차지하는 비중이 높은 순서대로 정렬합니다.
2. 항목을 클릭하면 Parent와 children으로 구성되어 있습니다.
ex)
1(android/os/Handler.dipatchMessage)을 기준으로 보면
-‐
Parents(0)는 1을 호출합니다.
-‐
Children(2,
39,
120,
1276,
2521)은 1이 호출한 것입니다.
62.
1. 부모가 차지하는비중에서 자신이 부모에게 차지하는 비중을 곱한 것입니다.
2. 아래의 예시를 통해 보면 2(android/os/Handler/handleCallback)은
부모의 사용량 75% 중에서 86%를 차지했기 때문에 75
X
0.86
=
65.6%가 됩니다.
왜 Percentage의 합이 100%가 아닌지 의문이 생길 수 있습니다.
전체에서 2가 차지하는 비중
부모에서 2가 차지하는 비중
전체에서 부모가 차지하는 비중
따라해보기
1) 본인의 어플리케이션의시나리오를 만든다.
2) 각 시나리오별 Method
Profiling을 해본다.
3) 시나리오별 CPU를 많이 사용하는 메소드/클래스를 확인한다.
65.
2. 메모리상태 확인하기
STEP1.
Plug-‐in설치
STEP2.
Dump
HPROF
file
STEP3.
분석
:MAT를 통해 heap의 정보를 얻어서 메모리 상태를 확인
[참고영상]
Google
I/O
2011:
Memory
management
for
Android
Apps
https://www.youtube.com/watch?v=_CruQY55HOk
66.
그전에 Android
Memory와 Garbage
collection
(이하 GC)에 대해서 알아보겠습니다.
구글에서
메모리누수 현상이 자주 발생해서 메모리 관리 체계를 변경합니다.
Honeycomb이전 Honeycomb이후
이미지 파일
이전에는
Native영역에서 이미지 파일을 관리했다면,
이후에는 Dalvik내부에서 관리를 하는
구조로 변경되었습니다.
!
Q
: 이미지파일의 저장위치가 핵심인가요?
A
:
이미지가 메모리 누수의 50~70%를 차지하기 때문에
69.
‘이미지 저장위치’의 변경만확인하시고 나머지는
이어서 자세히 설명하겠습니다.
Honey
Comb 이전 Honey
Comb 이후
이미지 저장 위치 Dalvik외부 native
Heap Dalvik 내부
GC 동작 전체 App이 멈춤 부분적으로 진행(partially)
Bitmap의 GC GC의 대상이 아님 GC의 대상
다른 App의 영향 메모리 누수가 발생하면 다른 App
도 함께 죽음
다른 앱에 영향이 없음
70.
!
1) Garbage
Collection(GC)는사용하지 않는 메모리를 정리하는 것입니다.
2) Mark
Sweep
-‐
Mark
:
GC
Roots를 통해서 연결된 객체를 표시(Mark)합니다.
-‐
Sweep
:
Mark되지 않은 객체는 사용하지 않는 객체로 간주하여 삭제(Sweep)합니다.
지금부터 GC에 대해서 알아보겠습니다.
71.
1. GC_CONCURRENT
:
heap영역이 계속 커질 때 새롭게 heap을 확대하지 않고,
메모리 회수로 가능한 경우
2. GC_EXPLICIT
:
System에서 주기적으로 GC를 호출하는 경우
3. GC_EXTERNAL_MALLOC
:
BITMAP처럼 외부의 메모리를 할당 받은 경우, 하지만 honey-‐comb
이후 버전부터는 bitmap을 dalvik
heap(internal
heap)에 할당하기 때문에 이전 버전에만 해
당
4. GC_FOR_MALLOC
:
heap영영이 가득 찬 경우 전체 어플리케이션을 멈추고 GC를 진행
5. GC_HPROF_DUMP_HEAP
:
메모리 분석을 위해 HPROF
file을 만든 경우
아래와 같은 이유로 GC가 일어납니다.
72.
Honey
Comb 이전Honey
Comb 이후
저장 위치 Dalvik외부 native
Heap Dalvik 내부
GC 동작 전체 App이 멈춤 부분적으로 진행(partially)
Bitmap의 GC GC의 대상이 아님 GC의 대상
다른 App의 영향 메모리 누수가 발생하면 다른 App
도 함께 죽음
다른 앱에 영향이 없음
1) GC동작 방식
-‐
HoneyComb 이전에는 전체 App이 멈추는 Serial
MarkSweep(Stop
the
world)방식이였습니다.
-‐ 이후에는
부분적으로 진행하는 Concurrent
MarkSweep으로 변경되었습니다.
2) Concurrent
MarkSweep 장점
-‐ 반응성/속도
부분적으로 동작하기 때문에 앱이 멈추지 않습니다.
Serial
MarkSweep
:
100ms,
Concurrent
MarkSweep
5ms
3) Concurrent
MarkSweep 단점
-‐ 이전보다 메모리와 CPU를 더 많이 사용하게 되었습니다.
앞에서 본 표입니다.
이번 슬라이드에서는 ‘GC동작 부분’만 확인해보겠습니다.
73.
(다른작업도 쓰레드로 진행가능)
[출처]
Hello
world
:
Android
앱 메모리 최적화편
Serial
MarkSweep과 Concurrent
MarkSweep 동작 비교
74.
직접 메모리를 관리하고싶다면,
Java에서는 C,
C++에서 사용하는 ‘free’,
‘delete’가 없기 때문에
주기적으로 혹은 특정 조건일 때 GC
를 하게 됩니다. 이로인해 프로그래머는 메모리 관리에 대해서 고민을 적게 할 수 있습니다.
!
하지만 임베디드 환경(모바일 포함)에서는 이 메모리 하나 하나가 매우 소중합니다.
예를들어 1회성으로 할당한 공간을
GC과정에서 ‘사용하는 메모리’라고 판단하여 공간을 계속 잡게
될 경우 불필요한 공간낭비로 메무리 누수의 위험이 생길 수 있습니다.
75.
기본적으로 할당하는 방식은Strong
Reference입니다.
!
Strong
-‐
기본적으로 할당하는 방식을 Strong
Reference
라고 부릅니다.
mLauncher
=
new
Launcher(launcher);
!
-‐
GC과정에서 연결된 객체들을 Mark하고 Mark되지 않은 객체들을 Sweep합니다.
즉 메모리 관리에 프로그래머가 신경쓰지 않습니다.
76.
Strong
이외에 3가지가더 있습니다.
!
1.
종류
Soft
reference,
Weak
reference,
Phantom
reference
Private
WeakReferenceLauncher
mLauncher;
mLauncher
=
new
WeakReferenceLauncher(launcher);
!
2. 원리
-‐
GC동작에서 Strong이 아닌 경우 Mark하지 않고 Reference
Queue라는 공간에 객체를 넣고,
Sweep하는 과정에서 제거 Queue에 있는 객체들을 제거 합니다.
!
3.
차이점
이름에서 느낄 수 있듯이 객체간의 연결정도를 나타냅니다. 그리고 이 연결정도가 강할수록 제거가
되지 않습니다. 객체간의 연결정도를 수식으로 나타내면 Strong
Soft
Weak
Phantom
순서입니다.
77.
더 자세히 보겠습니다.
!
1. Soft
reference
Mark가 되기도 하고 Reference
Queue에 담기기도 합니다.
Soft
reference로
참조된 객체는 메모리가 절대적으로 부족한 상황이 되기전에는 참조가 유지됩니다.
각 앱마다 할당된 메모리가 절대적을 부족할 때 그 Reference가 Soft이면 제거, 여유롭다면 Strong과 같이 제거
하지 않습니다.
!
2.
Weak
reference
Referene
Queue에 담깁니다.
Weak
reference로
참조된 객체는 Soft
Reference보다 더 약한 연결고리를 가집니다.
메모리의 상태와 관계없이
GC가 동작되는 순간
Marked
Object라도 회수됩니다.
!
!
Strong Soft
Weak
Phantom
Mark
Reference
Queue
78.
!
3.
Phantom
reference
-‐
GC가 아닌 코드 내에서 바로 Reference
Queue에 넣습니다.
그렇기 때문에 반드시 Reference
Queue와 함께
사용해야 합니다.
!
-‐
Weak
Reference와 유사하며,
finalize 시점에서 메모리를 바로 정리하지 않고 Reference
Queue에 참조를 등
록하여 코드에 접근 할 수 있도록 합니다. 객체의 자원 정리를 구현하기 위해 사용할 수 있습니다.
!
예제 코드
ReferenceQueue
q
=
new
ReferenceQueue();
PhantomReference
pr
=
new
PhantomReference(object,
referenceQueue);
!
//
Later
on
another
point
Reference
r
=
q.remove();
!
//
Now,
clear
up
any
thing
you
want
79.
Strong Soft
Weak
Phantom
Mark Reference
Queue
-‐
Strong
:
연결된 객체들을 체크 합니다.
-‐
Soft
:
메모리 상태에 따라 Mark하거나,
Reference
Queue에
넣습니다.
-‐
Weak
:
Reference
Queue에 넣습니다.
-‐
Phantom
: 코드상에서 바로 Reference
Queue에 넣습니다.
Reference에 따른 Mark과정 차이
80.
GC 전 GC후GC 중
Strong
Reference 동작 방식
기본 컨셉
-‐ Mark
Sweep
:
GC-‐Roots로부터 연결된 인스턴스들을 마크합니다. 그리고 마크되지 않은 객체들을 제거
(Sweep)합니다.
-‐ Reachability
:
Roots로 부터 도달(참조) 가능한 객체(rechable)와 도달 할 수 없는 객체(un
reachable)로 나눕
니다.
-‐ 프로그래머가 GC에 관여하지 않고 Mark되는 방식에 따라 Mark하고 Mark하지 않은 것들을 Sweep합니다.
81.
마크되는 과정은 아래와같습니다.
Mark
Bit
1
1
1
GC
Roots
A
B
C
D
E
F
G
H
A
B
C D
G F
H
E
1
D1
82.
Mark를 모두 마친후 제거(Sweep)를 하게 됩니다.
UnmarkedSweep
:
Mark
되지 않은 메모리를 회수합니다.
1
Mark-‐Bit
1 1 제거 대상
83.
GC 전 GC후GC 중
Soft,
Weak,
Phantom 동작 방식
기본 컨셉
-‐ Strong과 마찬가지로 Mark
Sweep 방식으로 이루어집니다.
-‐ 다른 부분은 Mark되지 않는다는 것입니다.
Soft
:
메모리 상태에 따라 Mark하거나 Reference
Queue에 넣습니다.
Weak
:
Mark하지 않고
Reference
Queue에 넣습니다.
Phantom
:
코드상에서 바로 Reference
Queue에 넣습니다.
-‐ Sweep
Reference
Queue에 넣어 두었던 객체들을 제거 합니다.
Reference
Queue에 넣은뒤 제거(Sweep)를 하게 됩니다.
heapSweepSystemWeak
:
Mark하는 과정에서 reference
queue에 넣어두었던 Soft,
Weak,
Phantom
Object의 메모리를 회수합니다.
!
!
!
! Reference
Queue
a b
87.
Strong Soft
Weak
Phantom
Mark Reference
Queue
-‐
Strong
:
연결된 객체들을 체크 합니다.
-‐
Soft
:
메모리 상태에 따라 Mark하거나,
Reference
Queue에
넣습니다.
-‐
Weak
:
Reference
Queue에 넣습니다.
-‐
Phantom
: 코드상에서 바로 Reference
Queue에 넣습니다.
GC를 다시 한번 정리하면
Mark가 먼저 동작합니다.
1) heapSweepSystemWeak
:
Mark하는 과정에서 reference
queue에 넣어두었던 Soft,
Weak,
Phantom
Object의 메모리를 회수합니다.
!
!
!
!
!
!
2) BitmapSweep
: 이미지의 메모리를 회수 합니다.
!
3) UnmarkedSweep
:
Mark
되지 않은 메모리를 회수합니다.
Reference
Queue
a b
1
Mark-‐Bit
1 1 제거 대상
Mark 후에는 Sweep이 이루어집니다.
90.
이미지 객체 회수에대해서 더 알아보겠습니다.
-‐ Bitmap은 GC에서 매우 중요한 부분입니다.
-‐ 메모리 누수의 원인은 대부분 이미지와 관련되어 있습니다.
-‐ 그래서 안드로이드에서는 Honey
Comb이전과 이후로 Bitmap을 다르게 관리하고 있습니다.
Honey
Comb 이전 Honey
Comb 이후
저장 위치 Dalvik외부 native
Heap Dalvik 내부
GC 동작 전체 App이 멈춤 부분적으로 진행(partially)
Bitmap의 GC GC의 대상이 아님 GC의 대상
다른 App의 영향 메모리 누수가 발생하면 다른
App도 함께 죽음
다른 앱에 영향이 없음
91.
HoneyComb 이전에는 왜그랬을까요?
-‐ 왜 저장 위치를 밖에 두었을까요?
Honeycomb이전에는 그래픽 라이브러리를 c++의 skia 라이브러리를 사용했습니다. 그래서 비트맵도
native메모리에 로딩될 수 밖에 없었고, 이를 많이 잡아먹으면 다른 앱에서 사용할 수 없었기 때문에 한계
를 정해 두었습니다.
92.
HoneyComb 이후 이점은무엇일까요?
-‐ 저장 위치를 dalvik
heap으로 bitmap을 옮겼고,
GC를 할때 bitmap도 함께 관리를 할 수 있게 됩니다.
-‐ 이전에는 App의 GC가 이루어진다고 해도 bitmap은
native영역에 존재하기 때문에 GC의 대상이 되지 않
았습니다.
bitmap이 native영역을 차지하게 되면 다른 앱을 사용하는데 제약을 받게 됩니다. 이를 해결하
기 위해서는 수동으로 Finalize()와 Recycle()을 통해 직접 native영역에서 메모리를 회수해야 했습니다.
93.
이제 메모리를
어떻게 확인하는지 알아봅시다.
94.
2. 메모리상태 확인하기
STEP1.
Plug-‐in설치
STEP2.
Dump
HPROF
file
STEP3.
분석
:MAT를 통해 heap의 정보를 얻어서 메모리 상태를 확인
[참고영상]
Google
I/O
2011:
Memory
management
for
Android
Apps
https://www.youtube.com/watch?v=_CruQY55HOk