Android performance optimization game OutOfMemoryError: pthread_create explores the truth

Recently, I began to analyze the OOM problem of the game. The magnitude of the problem in the bugly, the terrifying million level, is in the top 1 of the java exception, as shown below: the devices that occur
insert image description here
are basically 32-bit CPU architecture
insert image description here

Analysis process

Let’s first look at the stack of error reports, which basically happen during the creation of threads:
insert image description here
simply looking at the call stack of java error reports, it is often simply considered that too many app threads cause OOM. However, is this really the case?

First, through the adb shell, check the number of threads in the game
insert image description here
. After going through the main process of the game, it is found that the number of threads has not increased particularly much, generally around 200, and has not reached the maximum number of threads limited by the manufacturer (the limit of 500+ threads on Huawei devices number).

It can be deduced that it is not the problem of OOM caused by too many threads.

Then continue to explore, OOM is an exception thrown when the memory is insufficient and the application for memory allocation fails again.

Go to check if it is the culprit caused by insufficient system memory?
insert image description here
Judging from the statistical data on bugly, when OOM occurs in the game, the available memory of the system is still sufficient, so this reason is also ruled out.

Then continue, analyze and see if Dalivk Heap has insufficient memory?

The java heap OOM exception will bring, , which is completely inconsistent with the Failed to allocate a 294920 byte allocation with 147040 free bytes and 143KB until OOMone on the error stack , so it is not caused by insufficient memory in the dalvik heap.pthread_create (1040KB stack) failed: Try again

After excluding three possibilities, combined with 32-bit devices, it is inferred that the only thing left is that the virtual memory of the app is insufficient.

For more information about memory, please read Android memory analysis (java/native heap memory, virtual memory, processor memory) and Android adb shell View App memory (java heap memory/vss virtual memory/detailed memory status/memory snapshot hprof ) and system available memory

The maximum virtual memory of a 32-bit process is 4G, of which the kernel space occupies 1G + the user space occupies 3G, and there is a limit .

Guess verification

Compile a game channel package, find a 32-bit device, and install it.

Log in to the game, enter the game lobby, and check the virtual memory:
insert image description here
found that the virtual memory Vmsize: 2.9G, which is in the normal value.

Then play a few relatively large game maps:
insert image description here
Check the virtual memory again:
insert image description here
the virtual memory has soared to 3.4G

Try to continue to play different maps, and also record the virtual memory of the app.
insert image description here
insert image description here
When the virtual memory is close to 4G, the number of threads is still in the normal range of 192, the game appears black screen, and then suddenly crashes.

The logcat output at this time, the log of the thread oom:

2023-06-12 18:29:23.950 23936-24275/? E/Adreno-GSL: <gsl_memory_alloc_pure:2615>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
2023-06-12 18:29:23.951 23936-24275/? E/Adreno-GSL: <gsl_memory_alloc_pure:2615>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
2023-06-12 18:29:23.953 23936-24275/? E/Adreno-GSL: <gsl_memory_alloc_pure:2615>: GSL MEM ERROR: kgsl_sharedmem_alloc ioctl failed.
2023-06-12 18:29:23.953 23936-24016/? E/AndroidRuntime: FATAL EXCEPTION: miniCrashTask
    Process: com.minitech.miniworld.meta, PID: 23936
    java.lang.OutOfMemoryError: pthread_create (1040KB stack) failed: Try again
        at java.lang.Thread.nativeCreate(Native Method)
        at java.lang.Thread.start(Thread.java:884)
        at okio.AsyncTimeout.scheduleTimeout(AsyncTimeout.java:88)
        at okio.AsyncTimeout.enter(AsyncTimeout.java:80)
        at okio.AsyncTimeout$2.read(AsyncTimeout.java:235)
        at okio.RealBufferedSource.indexOf(RealBufferedSource.java:354)
        at okio.RealBufferedSource.readUtf8LineStrict(RealBufferedSource.java:226)
        at okhttp3.internal.http1.Http1Codec.readHeaderLine(Http1Codec.java:215)
        at okhttp3.internal.http1.Http1Codec.readResponseHeaders(Http1Codec.java:189)
        at okhttp3.internal.http.CallServerInterceptor.intercept(CallServerInterceptor.java:88)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:45)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
        at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)

In the end, the conjecture was verified. The 32-bit app process has a virtual memory limit of 4G, which is the culprit causing OOM.

Summary :

On devices with 32-bit CPU architecture (armeabi-v7a and armeabi) or in a sandbox environment (64-bit CPU is not supported), the game will most likely encounter the 4G virtual memory limit, which will cause OOM.

Guess you like

Origin blog.csdn.net/hexingen/article/details/131956266