Android L Memory Foot Print Analysis

Low end devices with limited amounts of RAM running Android L can have poor system performance. We want to understand why, gather information about the amount of memory in use and identify potential solutions or further research into potential solutions.

How to Measure Memory Usage

The whole system

cat /proc/meminfo

Individual process

  • raw data (also reference man proc):
    $ cat /proc/<PID>/stat

  • For human readable:
    cat /proc/<PID>/status

  • memory map (smaps provide very details, thanks to yanbin-fang)
    $ cat /proc/<PID>/maps
    $ cat /proc/<PID>/smaps

  • Android (http://elinux.org/Android_Memory_Usage)
    $ procrank
    $ procmem <PID>

Result

Device Info

Nexus 10

Juno

Android

nexus10-linaro
L:build-228

armv8-android-juno-lsk
L:build-226
L-MR1:LCR-15.04

CPU

Samsung Exynos 5250
2 cores @1.7GHz

ARM Cortex A57*2+A53*4

RAM

2G

8G

GPU

Mali T604

Mali T624

display

2560 * 1600

1920 * 1080

Memory usage after reboot

(KB)

Nexus 10

Juno (32-bit L)

Juno (64-bit L)

Juno (32-bit L-MR1)

Juno (64b L-MR1)

MemTotal

1125576

8230960

8230960

8228116

8231940

MemFree

641276

7708148

7560248

7733800

7590652

Used

484300

522812

670712

494316

641288

Buffers

4076

5588

3964

4072

5444

Cached

176008

209400

327052

207392

333192

Active

189184

169824

209452

126280

169804

Inactive

149696

186872

292684

190068

299712

Memory usage (APPs) (L)

Nexus 10

Juno (32-bit)

Juno (64-bit)

32b -> 64b increase

(ps)

VSIZE (GB)

RSS (MB)

VSIZE (GB)

RSS (MB)

USS (MB)

VSIZE (GB)

RSS (MB)

USS (MB)

VSS

RSS

USS

Stock APPs

"Browser default page"

1.57

122

1.65

142

97

3.51

191

186

112.73%

34.51%

91.75%

Calculator

1.46

68

1

50

11

1.5

55

26

50.00%

10.00%

136.36%

Calendar

1.46

76

1.01

60

15

1.51

67

47

49.50%

11.67%

213.33%

Clock

1.47

84

1.01

64

19

1.64

71

37

62.38%

10.94%

94.74%

Contacts

1.47

78

1.02

60

15

1.52

66

50

49.02%

10.00%

233.33%

Email

1.47

87

1.03

69

22

1.66

77

56

61.17%

11.59%

154.55%

Gallery

1.46

69

1.03

52

20

1.02

52

26

-0.97%

0.00%

30.00%

Music

1.49

40

0.98

35

6

1.29

40

6

31.63%

14.29%

0.00%

3rd party APPs (fresh startup without any actions)

Angry Bird

1.53

130

1.05

144

93

1.16

196

95

10.48%

36.11%

2.15%

Antutu 5.3

1.48

97

1.03

79

72

1.03

80

83

0.00%

1.27%

15.28%

Facebook

1.54

143

1.15

145

97

1.15

146

91

0.00%

0.69%

-6.19%

Firefox 33.1

1.7

168

1.29

154

64

1.28

155

88

-0.78%

0.65%

37.50%

Gears ES2

1.47

64

0.99

47

9

0.99

47

9

0.00%

0.00%

0.00%

HelloJni

1.44

35

0.95

29

3

1.26

33

3

32.63%

13.79%

0.00%

Twitter

1.49

106

1.05

84

31

1.05

83

31

0.00%

-1.19%

0.00%

Use cases

Browsing linaro.org

1.68

177

127

3.82

233

268

127.38%

31.64%

111.02%

add one more tab: phoronix

1.73

240

157

4

272

367

131.21%

13.33%

133.76%

Browsing youtube and play video

1.8

260

218

4.12

331

480

128.89%

27.31%

120.18%

View photos

1.05

92

62

1.07

108

68

1.90%

17.39%

9.68%

facebook timeline

1.21

208

125

1.23

230

154

1.65%

10.58%

23.20%

Improvements L -> L MR1

Juno (64b L)

Juno (64b L MR1)

L -> L MR1 reduce

(ps)

VSIZE (GB)

RSS (MB)

USS (MB)

VSIZE (GB)

RSS (MB)

USS (MB)

VSS

RSS

USS

Stock APPs

Browser

3.51

191

186

3.51

181

145

0.00%

5.24%

22.04%

Calculator

1.5

55

26

1.5

42

9.4

0.00%

23.64%

63.85%

Calendar

1.51

67

47

1.51

55

16.7

0.00%

17.91%

64.47%

Clock

1.64

71

37

1.6

60

19

2.44%

15.49%

48.65%

Contacts

1.52

66

50

1.5

53

16

1.32%

19.70%

68.00%

Email

1.66

77

56

1.45

50

12

12.65%

35.06%

78.57%

Gallery

1.02

52

26

1.02

45

20

0.00%

13.46%

23.08%

Music

1.29

40

6

1.3

40

6

-0.78%

0.00%

0.00%

3rd party APPs (fresh startup without any actions)

Angry Bird

1.16

196

95

1.2

128

98

-3.45%

34.69%

-3.16%

Antutu 5.3

1.03

80

83

1.02

60

28

0.97%

25.00%

66.27%

Chrome 41

1.14

84

43

1.12

80

40

1.75%

4.76%

6.98%

Facebook

1.15

146

91

1.1

100

63

4.35%

31.51%

30.77%

Firefox 33.1

1.28

155

88

1.26

145

82

1.56%

6.45%

6.82%

Gears ES2

0.99

47

9

0.98

31

4.6

1.01%

34.04%

48.89%

HelloJni

1.26

33

3

1.27

32

2.4

-0.79%

3.03%

20.00%

Twitter 5.35

1.05

83

31

1.03

63

33

1.90%

24.10%

-6.45%

Temple Run 2 1.11.2

1.17

173

142

1.16

162

128

0.85%

6.36%

9.86%

Vellamo 3.1

1.66

103

66

1.65

73

36

0.60%

29.13%

45.45%

Use cases

Browsing linaro.org

3.82

233

268

4.2

345

300

-9.95%

-48.07%

-11.94%

add one more tab: phoronix

4

272

367

5.8

599

553

-45.00%

-120.22%

-50.68%

"Browsing youtube and play video"

4.12

331

480

5.9

818

771

-43.20%

-147.13%

-60.63%

View photos

1.07

108

68

1.06

93

68

0.93%

13.89%

0.00%

facebook timeline

1.23

230

154

1.19

196

130

3.25%

14.78%

15.58%

Viewing twitter

1.1

101

66

1.08

92

59

1.82%

8.91%

10.61%

after Vellamo completed browser test

1.8

128

83

1.81

109

63.4

-0.56%

14.84%

23.61%

Firefox: browsing linaro.org

1.33

202

130

1.32

192

123

0.75%

4.95%

5.38%

Firefox: one more tab

1.42

257

181

1.39

242

170

2.11%

5.84%

6.08%

Firefox: youtube playing

1.44

277

198

1.42

273

198

1.39%

1.44%

0.00%

Improvements L -> L MR1 (32b)

Juno (32b L)

Juno (32b L MR1)

L -> L MR1 reduce

(ps)

VSIZE (GB)

RSS (MB)

USS (MB)

VSIZE (GB)

RSS (MB)

USS (MB)

VSS

RSS

USS

Stock APPs

Browser

1.65

142

97

1.63

134

56

1.21%

5.63%

42.27%

Calculator

1

50

11

0.99

34

6

1.00%

32.00%

45.45%

Calendar

1.01

60

15

1

41

9

0.99%

31.67%

40.00%

Clock

1.01

64

19

1

45

12

0.99%

29.69%

36.84%

Contacts

1.02

60

15

1.01

41

9

0.98%

31.67%

40.00%

Email

1.03

69

22

1.01

46

13

1.94%

33.33%

40.91%

Gallery

1.03

52

20

1.03

45

14

0.00%

13.46%

30.00%

Music

0.98

35

6

0.98

33

4

0.00%

5.71%

33.33%

3rd party APPs (fresh startup without any actions)

Angry Bird

1.05

144

93

1.17

108

73

-11.43%

25.00%

21.51%

Antutu 5.3

1.03

79

72

1.02

59

63

0.97%

25.32%

12.50%

Chrome 41

NA

NA

NA

1.11

73

30

NA

NA

NA

Facebook

1.15

145

97

1.13

125

83

1.74%

13.79%

14.43%

Firefox 33.1

1.29

154

64

1.27

129

63

1.55%

16.23%

1.56%

Gears ES2

0.99

47

9

0.98

30

4

1.01%

36.17%

55.56%

HelloJni

0.95

29

3

0.95

27

2

0.00%

6.90%

33.33%

Twitter 5.35

1.05

84

31

1.03

62

27

1.90%

26.19%

12.90%

Temple Run 2 1.11.2

NA

NA

NA

1.16

150

115

NA

NA

NA

Vellamo 3.1

NA

NA

NA

1.01

50

19

NA

NA

NA

Use cases

Browsing linaro.org

1.68

177

127

1.67

124

87

0.60%

29.94%

31.50%

add one more tab: phoronix

1.73

240

157

1.69

154

116

2.31%

35.83%

26.11%

"Browsing youtube and play video"

1.8

260

218

1.77

187

150

1.67%

28.08%

31.19%

View photos

1.05

92

62

1.06

80

49

-0.95%

13.04%

20.97%

facebook timeline

1.21

208

125

1.18

183

113

2.48%

12.02%

9.60%

Viewing twitter

NA

NA

NA

1.08

88

49

NA

NA

NA

after Vellamo completed browser test

NA

NA

NA

1.02

58

23

NA

NA

NA

Firefox: browsing linaro.org

NA

NA

NA

1.33

182

111

NA

NA

NA

Firefox: one more tab

NA

NA

NA

1.38

228

152

NA

NA

NA

Firefox: youtube playing

NA

NA

NA

1.41

231

154

NA

NA

NA

Some data are marked as NA, because those items are newly added when I was doing L-MR1. And it would take much time to have them because 32-bit Android L need to be manually rebuilt.

Memory Restriction

Android 64b runs on Juno, but the memory size is restricted by passing mem=X to kernel boot args.

Android L

(KB)

32b with 768M

768M

1G

2G

4G

8G

MemTotal

757264

757264

1019408

2037620

4103020

8230960

MemFree

186652

92048

357084

1369580

3436412

7565216

Used

570612

665216

662324

668040

666608

665744

Buffers

4752

2336

2300

2316

2276

2276

Cached

247192

326436

326696

326656

326864

327016

Active

154280

205760

205048

208084

205904

206004

Inactive

209896

291940

292272

292244

292324

292568

  • No matter how much available RAM, used memory after boot occupied around 660~670 MB.
  • Starting web browser to play youtube video in 768M Android triggered lowmemorykiller many times and even had kernel dump_backtrace. Therefore, 768M is apparently not sufficient for Juno to run Android-64 with full HD display.
  • For Android-32b with 768M memory, the lowmemorykiller does not active when opening web browser until I the 2nd tab is opened.
  • Enable ro.config.low_mem=true does not help reduce memory usage.

  • I also tried very low memory size: 512M. Linux can boot to console, and Android only shows status bar and three buttons but not home screen. The lowmemorykiller starts to kill APPs continually since Linux console prompt shows. The launcher cannot be started and Android keeps showing "Unfortunately, Launcher has stopped."

arm64 L MR1

(KB)

768M

1G

2G

4G

8G

MemTotal:

751348

1016564

2034776

4100176

8228116

MemFree:

121640

382680

1391732

3473420

7596048

Used

629708

633884

643044

626756

632068

Buffers:

4152

4292

4192

3992

4056

Cached:

333452

333308

333196

333412

333476

Active:

165700

166560

176820

166440

166500

Inactive:

299492

299292

299292

299264

299488

The free memory increases around 30MB, and that looks like not enough for low memory Android. The lowmemorykiller is still often triggered in 768M Android.

I did some experiments in 768M and 1G to see when does lowmemorykiller start. For each stock APPs, I started it and press 'home' to return to home screen, then start next APP. In 768M Android, the lowmemorykiller starts to kill after I start 3rd APP. While for 1G Android, the lowmemorykiller does not kill any APP after I traverse all stock APPs.

Observations

  • The memory usage of an APP which is forked by Zygote64 will dramatically increase especially in USS.
  • The USS of an 64-bit APP increase more than 90% comparing to its 32-bit version. (except for Music and HelloJNI)
  • The VSS (VSIZE) is almost the same across 32-bit and 64-bit Android if the APP is forked by Zygote32.
  • Some APPs may not have changeless VSize but have significantly increase in USS (such as antutu, firefox, facebook timeline)

Raw data at Google Doc link https://docs.google.com/a/linaro.org/spreadsheets/d/1riR1t3j9W4maESOoWo_2UDR8d8gsIiV6BlK9QRQIPmU/edit?usp=sharing

Based on the above experiments, we found that 2GB is definitely enough for great user experience even on very high-res screens. While 1GB is fair enough for most of use cases, because we did not see any visible problems with typical use at full HD display. Although 768MB Android-64b boots successfully, it would encounter certain lowmemorykiller actions, which will significantly hurt user experience, hence we think 768MB is NOT recommended for end-user products.

We also applied various well-known memory optimizations suggested by https://source.android.com/devices/tech/low-ram.html. We tried swap, zRAM, KSM, and Enable Low Ram Device, however neither of them made visible improvement. Details are described below:

swap

  • The lowmemorykiller still killed the processes rather moving memory pages to swap. According to free command, the lowmemorykiller kills processes even the swap usage is very low (less than 10 MB).

  • A 300MB swap space was created for 768MB Android-64b, but the lowmemorykiller still tried to kill APPs even the swap is available.
  • Much less swap area is used (<10MB).

  • Adjusting /proc/sys/vm/swapiness is useless.

zRAM

* For 768MB Android-64b, the free memory is rare, we don’t think moving those precious resource for zRAM is a good idea. Instead, we tried zRAM in 1GB Android-64b but encountered the same swap problem as swap case.

KSM

  • KSM only saves hundreds of pages (< 2MB). Probably the number of identical pages is very little in Android environment.

ro.config.low_ram=true

  • It did not improve the low memory situation, the usage memory is not reduced.

Future work

Although neither of the above mentioned technical solutions provided improvement in our experiments so far, we would like to look into Cache and SWAP as areas that show potential to improve situation in low-memory configurations.

We are interested in feedback and additional suggestions.

Cache

We found that a large portion of used memory is allocated for cache (more than 300MB out of used memory 600MB). Around 200MB cache could be released by echo 1 > /proc/sys/vm/drop_caches. However, Android (or Linux) prefer keeping cache rather than keeping running applications and this policy makes Android trigger the lowmemorykiller under low memory situation rather than cleaning cache. With our follow-up work we would like to see if those policies can be tuned and if those trade-offs can be made and whether that results in working system under low memory conditions.

Investigate how to leverage swap area

Since there are shipping products that use swap to file on SD Card we would like to see if such technical solution could be made to work with Android as well. Known reservations about impact of this on performance and lifetime of flash need to be taken into account, but solving this problem could be helpful for zRAM and low memory conditions in general.

Platform/Android/MemoryFootprintAnalysis (last modified 2015-06-18 07:43:32)