antest1/GotoBrowser

OOM Issue

antest1 opened this issue · 7 comments

Application unexpectedly closed while running on foreground:

  • Device: Galaxy Note 4
  • Android: 6.0.0
08-18 20:08:18.289 25272-10743/? E/GOTO: 304 Not Modified http://125.6.189.215/kcs2/resources/ship/full/1571_4948_gnnicfxddgut.png
08-18 20:08:18.289 25272-10743/? E/GOTO: load cached resource: /kcs2/resources/ship/full/1571_4948_gnnicfxddgut.png Tue, 25 Jun 2019 04:28:39 GMT
08-18 20:08:18.289 25272-10743/? E/GOTO: /data/user/0/com.antest1.gotobrowser/files/cache/kcs2/resources/ship/full/1571_4948_gnnicfxddgut.png 258671
08-18 20:08:18.639 25272-26553/? E/chromium: [ERROR:validation_errors.cc(76)] Invalid message: VALIDATION_ERROR_UNEXPECTED_NULL_POINTER (null field 1)
08-18 20:08:18.644 25272-26551/? A/chromium: [FATAL:memory.cc(22)] Out of memory. size=23142400
08-18 20:08:18.644 25272-26551/? A/libc: Fatal signal 7 (SIGBUS), code 0, fault addr 0x0 in tid 26551 (Chrome_InProcRe)
08-18 20:08:18.719 2971-2971/? A/DEBUG: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
08-18 20:08:18.719 2971-2971/? A/DEBUG: Build fingerprint: 'samsung/trelteskt/trelteskt:6.0.1/MMB29K/N910SKSU2DSA1:user/release-keys'
08-18 20:08:18.719 2971-2971/? A/DEBUG: Revision: '14'
08-18 20:08:18.719 2971-2971/? A/DEBUG: ABI: 'arm'
08-18 20:08:18.724 2971-2971/? A/DEBUG: pid: 25272, tid: 26551, name: Chrome_InProcRe  >>> com.antest1.gotobrowser <<<
08-18 20:08:18.724 2971-2971/? A/DEBUG: signal 7 (SIGBUS), code 0 (SI_USER), fault addr 0x0
08-18 20:08:18.854 2971-2971/? A/DEBUG: Abort message: '[FATAL:memory.cc(22)] Out of memory. size=23142400
    '
08-18 20:08:18.854 2971-2971/? A/DEBUG:     r0 00000000  r1 7d23dd80  r2 00000400  r3 00000000
08-18 20:08:18.854 2971-2971/? A/DEBUG:     r4 9b33a150  r5 a45b4d00  r6 b6d2d4cc  r7 9b33a134
08-18 20:08:18.854 2971-2971/? A/DEBUG:     r8 b6d2eec0  r9 9b33a588  sl 9b33a584  fp 9b33a580
08-18 20:08:18.854 2971-2971/? A/DEBUG:     ip 9b33a154  sp 9b33a120  lr a2f7ae45  pc a2f7af2e  cpsr 680f0030
08-18 20:08:18.859 2971-2971/? A/DEBUG: backtrace:
08-18 20:08:18.859 2971-2971/? A/DEBUG:     #00 pc 014eef2e  /data/app/com.google.android.webview-1/lib/arm/libwebviewchromium.so
08-18 20:08:20.114 15011-15011/? E/Zygote: v2
08-18 20:08:20.114 15011-15011/? W/SELinux: Function: selinux_compare_spd_ram, index[1], priority [2], priority version is VE=SEPF_SECMOBILE_6.0.1_0035
08-18 20:08:20.119 15011-15011/? E/Zygote: accessInfo : 0
08-18 20:08:20.119 15011-15011/? W/SELinux: SELinux: seapp_context_lookup: seinfo=untrusted, level=s0:c512,c768, pkgname=com.google.android.setupwizard 
08-18 20:08:20.189 15011-15011/? W/System: ClassLoader referenced unknown path: /system/priv-app/SetupWizard/lib/arm
08-18 20:08:20.374 15011-15011/? E/SetupWizard: tickleCheckinService called after completing user setup
08-18 20:08:20.664 15026-15026/? E/Zygote: v2
08-18 20:08:20.669 15026-15026/? W/SELinux: Function: selinux_compare_spd_ram, index[1], priority [2], priority version is VE=SEPF_SECMOBILE_6.0.1_0035
08-18 20:08:20.669 15026-15026/? E/Zygote: accessInfo : 0

I have OOM issues with an old phone (Galaxy A7 2016 w/ SD615) too.

KC memory usage is not that high (a kcanotify H5 fork is using <400MB) and it doesn't seems to leak over time.

With Chrome OOM is rare. However, with a crosswalk view it is almost guaranteed to get OOM within 2 sorties. I guess it is because an embedded WebView has a more static memory space/pool together with the app.

Although it might not be the exact same case, one explanation about fragmentation seems legit to me.
https://bugs.chromium.org/p/chromium/issues/detail?id=525938
Since KC constantly prepares and clears texture cache from scene to scene, fragmentation is quite understandable. Eventually the system can no longer find a continuous memory address that is big enough to handle caching / PNG decoding / webGL texture of a huge image.

One example of huge images in KC is kcs2/img/map/map_common.png which is 3129*3047. It is 36MB when decoded. Decoding process requires even more. This particular map often fails to load into openGL(GPU mem) and results in black sprites.

I don't have any workaround yet to the problem. I guess splitting into smaller texture tiles is not possible. Scaling down huge images directly in the cache system maybe an nice option.

Update:

According to https://stackoverflow.com/a/50624536, Android 8+ seems to have a mitigation. My A7 is 7.1 FYI.

about image compression, this library seems to be help.
https://github.com/ndahlquist/pngquant-android

The memory usage goes down by 20MB ~ 50MB.
But the resource loading time is too long. (waited a few minutes for compressing some huge PNGs).
Not worth it IMO. At least it should not be done in real-time during the gameplay.

I think compress the image only once when download image (or existing image) and load it in the next play would be workaround for long compressing time issue.

The problem is that shouldInterceptRequest() is single threaded and UI blocking.
So it is impossible to finish compression during the first-time download.

The steps should be:

  1. Right after processWebRequest(), creates a thread to compress in background. (from map_common.png to map_common.png.tmp)
  2. After compression, do an atomic rename(replace) to map_common.png

About step 2, I save compressed file separately from the original file (to make compress function as optional).

Check the processImageDataResource and KcPngCompress.java for current implementation.

Update:

I was wrong about shouldInterceptRequest()
It is async on new version WebView and it doesn't block UI anymore. (as at 2019, dont know the exact Chromium version)
So it should be okay to compress some small PNGs during first-download.

Related chromium thread: https://bugs.chromium.org/p/chromium/issues/detail?id=586331