MTHawkeye
Profiling / Debugging assist tools for iOS. (Memory Leak, OOM, ANR, Hard Stalling, Network, OpenGL, Time Profile ...)
Install / Use
/learn @meitu/MTHawkeyeREADME
MTHawkeye
MTHawkeye is profiling, debugging tools for iOS used in Meitu. It's designed to help iOS developers improve development productivity and assist in optimizing the App performance.
During the App product development cycle, we introduced MTHawkeye to help us discover, find, analyze, locate, and solve problems faster.
- Development phase, focusing on development and debugging assistance, detect problems in a timely manner, and prompt developers to deal with them.
- Test phase, focusing on collecting performance data as much as possible from the test case, for generating automated test analysis reports.
- Online phase, focusing on performance data that needs by our own business but missing from third party APM components.
MTHawkeye has built-in some common performance detection plug-ins. It also introduces and improves FLEX as a plug-in for debugging assistance. When you use MTHawkeye, you can customize and add the plug-ins you need.
The following are demo diagrams of some built-in plugins for View time-consuming methods on main Thread, View App memory allocations details, View network transaction records. See the post for more plugin instructions.
<img src="./doc/images/ui-time-profiler-demo-flow.gif" width=285> <img src="./doc/images/memory-allocations-demo-flow.gif" width=285> <img src="./doc/images/network-monitor-demo-flow.gif" width=285>
0x00 Features
MTHawkeye can be divided into upper, middle and lower layers. In addition to the bottom Base layer, the middle is the UI Skeleton and Desktop Adaptor, the uppermost plug-ins are internally split according to different scenarios. You can optionally add these plugins to your own scenario. The overall structure is as follows:

Base Feature
The Base layer mainly provides plugin management capabilities, storage API and util classes.
UI Skeleton provides an interface interaction framework for the development and testing phase. It includes a floating window, the main panels frame, and a setting panel, all of which can be modified, and the plug-in can integrate the interface interaction.
Optional plugins
The built-in plugins are divided into Memory, TimeConsuming, Energy, Network, Graphics, Storage, Utility according to the focus points.
Memory
# LivingObjectSniffer
LivingObjectSniffer is mainly used to track and observe objects directly or indirectly held by ViewController, as well as custom View objects. Detects whether these objects are unexpected alive, which may cause by leaks, not released in time, or unnecessary memory buffers.
In the development and testing phase, the detected unexpected alive objects can be prompted to the developer in the form of floating windows flash warning or toast.
In the automated test, the recorded unexpected alive objects can also be extracted for the further memory usage analysis.
# Allocations
Allocations is similar to the Instrument's Allocations module, It tracks the memory details actually allocated by the application. When the application memory usage is abnormal (abnormal rise, OOM exit), the recorded memory allocation details can be used to analyze specific memory usage issues.
TimeConsuming
# UITimeProfiler
UITimeProfiler is used to assist in optimizing the time-consuming tasks of the main thread.
The data collection part mainly includes two components, VC Life Trace and ObjC CallTrace. VC Life Trace tracking the time of each key node when opening ViewController, and when ObjC CallTrace is turned on, it can track Objective-C methods that are executed on the main thread and take longer than the specified threshold.
The interface layer part combines the two parts of data to make it easier for developers to find out the time-consuming details of the operations they are focusing on. The example diagram is as shown in the previous section, for a more detailed description, see the UITimeProfiler plugin documentation.
After enabling the plug-in on the automated test or online phase, without other code, you can continuously automate tracking the startup, page open, and other critical processes time-consuming.
# ANRTrace
ANRTrace is used to capture the stuck event, and will sample the main thread stack frame when the jam occurs.
# FPSTrace
FPSTrace is used to track the interface FPS and OpenGL flush FPS, and display the current value on the floating window.
Energy
# CPUTrace
CPUTrace is used to track the CPU's continuous high-load usage, and will recording which methods are mainly called during the high-load CPU usage.
# BackgroundTask Trace
BackgoundTask trace plugin will tracing the begin/end of UIBackgroundTaskIdentifier, it would be useful when try to find out the cause of crash 0xbada5e47. (see the code for usage directly)
Network
# NetworkMonitor
NetworkMonitor observes and records HTTP(S) network transactions with metrics info in the App. Providing built-in records viewing interface for a developer to troubleshoot network problems.
- Inherit FLEX's network recording logic, and optimize the initialization logic, greatly reducing the impact by hooking on startup time.
- For NSURLSession after iOS 9, add the URLSessionTaskMetrics record to view the time of each stage of the transaction.
- Add a waterfall view similar to Chrome network debugging based on transaction metrics, to view the queue and concurrency of network transactions, and do further optimization.
- Add the ability to detect duplicate unnecessary network transactions.
- Enhanced search bar to support multi-condition search (host filter, status filter)
- Record the network transaction with request header, request body, response body.
# NetworkInspect
NetworkInspect is based on NetworkMonitor. Depending on the actual of the network transaction, checking whether the network request can be improved according to the inspection rules, and you can add your own inspection rules by yourself.
Graphics
# OpenGLTrace
OpengGLTrace is used to track the memory usage of OpenGL resources, and to help find OpenGL API error calls and exception parameter passing.
Storage
# DirectoryWatcher
DirectoryWatcher is used to track the size of the specified sandbox folders, it also integrates FLEX's sandbox file browser.
Utility
# FLEX
FLEX is commonly used in daily development, MTHawkeye adds it as a plugin and extends the use of AirDrop for sandboxed files.
Desktop Extension
If you need to extend the plugin to the desktop, such as viewing and processing the data on the desktop collected by the plugins, you can get the data based on the interface provided by each plugin, and then bridge to the protocol provided by the third-party desktop client. Such as
0x01 Usage
Use during development
First, add an MTHawkeye reference to the project podfile:
#< Only used during Debug
#< Since the podfile dependency doesn't support environment configuration,
#< the dependent pods also need to be explicitly configured as Debug.
def hawkeye
pod 'MTHawkeye', :configurations => 'Debug'
pod 'FLEX', :configurations => ['Debug']
pod 'FBRetainCycleDetector', :configurations => ['Debug']
pod 'fishhook', :configurations => ['Debug']
pod 'CocoaLumberjack',
'3.6.0', :configurations => ['Debug'] # CocoaLumberjack is optional, change to `MTHawkeye/DefaultPluginsWithoutLog` if don't need.
# pod 'MTGLDebug', :configurations => ['Debug'] # MTGLDebug is exclude by default, change `MTHawkeye` to `MTHawkeye/DefaultPlugins` to include.
pod 'MTAppenderFile', :configurations => ['Debug']
end
target "YourProject" do
hawkeye
# ...
end
Attention:CocoaLumberjack must <~3.6.0
Then, turn on the MTHawkeye service when the App starts, You can use all the plugins as default, or choose the plugins you need to start.
A: Quickly integrate all default plugins and start:
#ifdef DEBUG
#import <MTHawkeye/MTRunHawkeyeInOneLine.h>
#endif
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
#ifdef DEBUG
[MTRunHawkeyeInOneLine start];
#endif
// ...
}
<details>
<summary> B: Select the required plugins, insert new plugins externally: </summary>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self startCustomHawkeye];
// ...
}
- (void)startCustomHawkeye {
#ifdef DEBUG
[[MTHawkeyeClient shared]
setPluginsSetupHandler:^(NSMutableArray<id<MTHawkeyePlugin>> *_Nonnull plugins) {
[MTHawkeyeDe
Related Skills
node-connect
330.7kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
81.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
330.7kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
81.4kCommit, push, and open a PR
