General APP only need to pay attention to the foreground memory is too high system kill FOOM, goude map has a lot of users use background navigation, so also need to pay attention to the background memory is too high caused by system kill BOOM, and the background kill is more serious than the foreground kill. In order to improve the user experience, memory governance is urgent.

background

According to Apple’s official WWDC, reducing memory can help users experience a faster startup speed, avoid crashes due to excessive memory, and keep the APP alive for a longer time.

For Automap, according to the analysis of online data, too high memory will lead to the navigation process system kill OOM. In particular, what is different from other APPs is that the general APP only needs to pay attention to the system killing FOOM with too high memory in the foreground. Many users of Goude map use background navigation, so they also need to pay attention to the system killing BOOM caused by too high memory in the background, and the background killing is more serious than the foreground killing. In order to improve the user experience, memory governance is urgent.

The principle of analyzing

OOM

OOM is short for Out of Memory. In iOS APP, if the memory exceeds, the system will kill the APP directly, a different kind of Crash, and can not catch. When you find the OOM, you can find a log starting with JetSamEvent from the device -> Privacy -> Analysis and Improvement -> Analysis data. The log records a lot of information: device information, system version, memory size, CPU time, etc.

Jetsam

Jetsam is a resource management mechanism for iOS. Unlike MacOS, Linux, Windows, etc., there is no memory swap space in iOS, so when the overall memory of the device is tight, the system will Kill some low priority or excessive memory consumption directly.

Through the IOS open source XNU kernel source code can be analyzed:

  • Each process has a priority list in the kernel, and JetSam, under memory stress, tries to kill the process at the bottom of the priority list until the memory water level returns to normal.
  • Jetsam uses get_task_phys_footprint to get the value of the phys_footprint to decide whether to kill the application.

The Jetsam mechanism cleanup strategy can be summarized as follows:

  • When a single APP’s physical memory footprint exceeds the upper limit, it will be cleaned. Different devices have different memory water levels.
  • When the overall physical memory footprint of the device is under pressure, clean the background applications first, then clean the foreground applications.
  • Clean up high footprint applications first, then low footprint applications.
  • User applications are cleaned before system applications.

Low Memory Killer on Android:

  • Depending on the priority of the APP and how much total memory is used, the system will kill the APP if the device runs out of memory.
  • The determination of memory tightness depends on the size of the system RSS(actual physical memory used, including the total memory occupied by the shared libraries).
  • There are three key parameters:

1) Oom_adj: In Framework layer, it represents the priority of the process. The higher the value, the lower the priority, and the easier it is to be killed.

2) OOM_ADJ threshold: Used in Framework layer, which represents the memory threshold of OOM_ADJ. The Android Kernel will periodically detect whether the current remaining memory is below this threshold. If it is below this threshold, the process with the highest value in the OOM_ADJ corresponding to the threshold value will be killed until the remaining memory is restored to a state above this threshold value.

3) OOM_SCORE_ADJ: It is used in Kernel layer. It is converted from OOM_ADJ and is the actual parameter used when killing the process.

The data analysis

Phys_Footprint captures the total physical Memory of the iOS app. Please refer to the official description of iOS Memory Deep Dive for details.

std::optional<size_t> memoryFootprint() { task_vm_info_data_t vmInfo; mach_msg_type_number_t count = TASK_VM_INFO_COUNT; kern_return_t result = task_info(mach_task_self(), TASK_VM_INFO, (task_info_t) &vmInfo, &count); if (result ! = KERN_SUCCESS) return std::nullopt; return static_cast<size_t>(vmInfo.phys_footprint); }

Instruments-VM Tracker can be used to analyze specific memory categories, such as the Malloc part of heap memory, WebKit Malloc part of JavaScriptCore memory, and so on. Note that the memory value of each class = Dirty Size + Swapped.

The memory distribution in the crawled navigation of the Instruments VM Tracker was compared and analyzed. When the navigation foreground is standing, the total memory value of AutoNavi map is very high, among which IOKIT, WebKit Malloc and Malloc heap memory occupy the most memory.

There are many tools available in the analysis process, each with its own advantages and disadvantages, which need to be used together to make up for each other. We used Intruments VM Tracker, Allocations, Capture GPU Frame, MemGraph, Dumpsys Meminfo, Graphics API Debugger, ARM in our analysis Mobile Studio, AJX memory analysis tools, self-research Malloc analysis tools, etc.

  • Iokit memory renders the video memory portion of the map.
  • WebKit Malloc memory is AJX JS business memory.
  • Malloc heap memory, we allocate memory through Hook Malloc API, by fetching stack analysis of specific memory consumers.

Management optimization

Based on the above data analysis, it is easy to make the idea of starting from the head. Our general idea in the process of governance:

  • Analyze data: Starting from the big head of memory, analyze each memory belonging business for further analysis and optimization of business.
  • Memory governance: Optimized technical solutions to reduce memory overhead, high and low end machine function classification and intelligent disaster recovery (i.e. memory alarm through function degradation and other strategies to release memory).

Divide and conquer

According to the data analysis, the three main memory consumption of AutoNavi map are map rendering (Graphic memory), function service (JavaScriptCore) and general service (Malloc). We also mainly start from these three aspects of optimization.

Graphic memory optimization

Xcode comes with the Debug tool Capture GPU Frame, which can analyze the specific video memory occupation. The video memory is mainly divided into the Texture part and the Buffer part, and the specific consumption is analyzed by the detailed address information. Similar analysis tools on Android can be used with the Google Graphics API Debugger.

According to the analysis, we reduced the video memory consumption of Texture by adjusting the FBO drawing method, optimizing the background of the vector intersection image, releasing the icon across the page, optimizing the text Texture, and reducing the full-screen anti-aliasing of the low-end closing mechanism. In Buffer, low memory mode is enabled, quadtree preloading is turned off, and background is cut to release cache resources.

Its Malloc optimization

AutoNavi uses a self-developed dynamic solution, which relies on the framework JavaScriptCore provided by the iOS system. Most of the business memory consumption is classified into WebKit Malloc by the system, as can be seen from the VM Tracker in the system tool Instruments. There are two ideas here, one is to optimize memory consumption by the business itself, and the second is to optimize memory consumption by dynamic engines and frameworks.

Business itself optimization, dynamic solution IDE memory analysis tools can be clearly output where the specific business memory consumption, easy to analyze the business students is reasonable.

Dynamic engine and framework optimization, we have optimized the use of the system library JavaScriptCore in such a way that multiple JSContextRef contexts share the same JSContextGroupRef. Multiple pages can share a single piece of framework code, thus reducing memory overhead.

Malloc heap memory optimization

IOS side heap memory allocation basically uses the libmalloc library, which contains the following memory operation interface:

Void *malloc(size_t __size) __result_use_check __alloc_size(1); void *malloc(size_t __size) __result_use_check __alloc_size(1); Void *calloc(size_t __count, size_t __size) __result_use_check __alloc_size(1,2); void free(void *); void *realloc(void *__ptr, size_t __size) __result_use_check __alloc_size(2); void *valloc(size_t) __alloc_size(1); // Create a heap based copy of a block or simply add a reference to an existing one. // This must be paired  with Block_release to recover memory, even when running // under Objective-C Garbage Collection. BLOCK_EXPORT void *_Block_copy(const void *aBlock) __OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_3_2);

The memory usage can be analyzed by recording the stack and size of memory allocation through Hook memory operation API.

There is also a global hook function, malloc_logger, which can output the log during Malloc process. It is defined as follows:

// We set malloc_logger to NULL to disable logging, if we encounter errors
// during file writing
typedef void(malloc_logger_t)(uint32_t type,
        uintptr_t arg1,
        uintptr_t arg2,
        uintptr_t arg3,
        uintptr_t result,
        uint32_t num_hot_frames_to_skip);
extern malloc_logger_t *malloc_logger;

The IOS heap memory analysis scheme can be realized through the Hook Malloc series API or by setting the function of malloc_logger, which can record the heap memory usage.

This scheme has several difficulties, such as the magnitude of memory allocation per second, allocation and release of memory requiring efficient queries and stack de-aggregation. For this reason, we designed a complete set of Malloc heap memory analysis scheme to quickly locate heap memory ownership so that it can be distributed to the respective business Owner for analysis and optimization.

Unified management

With the growth of business, the super APP of AutoNavi has brought great resource pressure. Therefore, we have developed a set of adaptive resource management framework to meet the extreme balance of function and experience in different business scenarios under limited resources. The main design idea is to use scheduling algorithm to calculate in real time by monitoring the user’s device level, system state, current business scene and user behavior, to uniformly manage and coordinate the allocation of APP’s current resource state, and to recycle the memory and other resources that are currently invisible to the user.

Adaptive Resource Management Framework – Memory section

Resources can be managed according to different device levels, business scenarios, user behavior, and system state. All businesses can easily access this framework, and it has been applied to many business scenarios with good benefits.

Data inspection and acceptance

Through successive governance of the three versions, the fore-and-background navigation scenarios have a 50% gain and the ABORT rate has a 10% to 20% gain. Overall earnings are positive, but the challenge is how we can maintain our gains.

Long term control

If there is no long-term control scheme, with the iteration of business versions, the previous optimization will be consumed in less than three or five versions. To this end, we built a set of APM performance monitoring platform to find and solve problems in the development and testing phase without bringing them online.

APM performance monitoring platform

In order to monitor APP performance daily, we have built an offline “APM Performance Monitoring Platform”, which can support performance monitoring of conventional business scenarios, including memory, CPU, traffic, etc., and can timely detect problems and give an alarm. Then cooperate with the performance follow-up process, to ensure the performance of the client to finish the last hurdle.

Memory analysis tool

Xcode Memory Gauge: In Xcode’s Debug Navigator, you can take a rough look at the memory footprint.

Instruments -allocations: You can view virtual memory footprint, heap information, object information, call stack information, VM Regions information, and more. You can use this tool to analyze memory and optimize for the location.

Instruments -Leaks: Used to detect memory Leaks.

Instruments – VM Tracker: This tool provides an overview of the memory footprint of various types, such as the size of the dirty memory. It can be used to analyze the causes of excessive memory, memory leaks, etc.

WWDC 2016 – Syetem Trace in Depth – Virtual Memory Trace – Virtual Memory Trace in Depth

Memory Resource Exceptions: Starting with Xcode 10, the debugger can catch Exc_Resource Resource_Type_Memory Exceptions when the Memory footprint becomes too large and the breakpoint is at the point where the exception was raised.

Xcode Memory Debugger: In Xcode, you can directly view the interdependencies between all objects. It is very convenient to find circular references. You can also export this information as a MemGraph file.

MemGraph + Command Line Instructions: In combination with the memgraph output from the previous step, you can use some instructions to analyze the memory situation. Vmmap can print out process information, information of VMRegions, etc., combined with grep can view the information of the specified VMRegion. Leaks can trace objects in the heap to see memory leaks, stack information, and more. The heap prints out all the information in the heap to keep track of objects with large memory footprint. MALLOC_HISTORY allows you to easily find problems by looking at the stack information for the objects that are generated by the HEAP directive.

MALLOC_HISTORY ===> Creation; Leaks = = = > the Reference; Heap & vmmap ===> Size.

Metrickit: A new monitoring framework for iOS 13 that collects and processes battery and performance metrics. When the user uses the APP, IOS will record the indicators, and then send them to the Apple server, and automatically generate related visual reports. Use window-> Organizer -> Metrics to check, including battery, startup time, lag situation, memory situation, disk read and write. MetrickIt can also be integrated into the project, uploading data to its own service for analysis.

MLeaksFinder: Detects memory leaks without breaking code by determining whether the UIViewController’s children are also destroyed after it has been destroyed.

Graphics API Debugger: Google’s open source set of Graphics debugging tools that examine, fine-tune, and replay applications’ graphics-driven API calls.

ARM Mobile Studio: Professional grade GPU analysis tool.

This article is the original content of Aliyun, shall not be reproduced without permission