Skip to content

Commit

Permalink
feat: add image monitor func.
Browse files Browse the repository at this point in the history
  • Loading branch information
Xcoder1011 committed Dec 14, 2022
1 parent 1b87fd9 commit d23bdc3
Show file tree
Hide file tree
Showing 12 changed files with 351 additions and 274 deletions.
11 changes: 9 additions & 2 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
PODS:
- Kingfisher (6.3.1)
- SKApmTools (0.1.0):
- SKApmTools (0.1.1):
- SKApmTools/ANR (= 0.1.1)
- SKApmTools/BackTrace (= 0.1.1)
- SKApmTools/ImageTool (= 0.1.1)
- SKApmTools/ANR (0.1.1):
- SKApmTools/BackTrace
- SKApmTools/BackTrace (0.1.1)
- SKApmTools/ImageTool (0.1.1):
- Kingfisher

DEPENDENCIES:
Expand All @@ -16,7 +23,7 @@ EXTERNAL SOURCES:

SPEC CHECKSUMS:
Kingfisher: 016c8b653a35add51dd34a3aba36b580041acc74
SKApmTools: 1cdc19b3bbda3615500e79450155c4eca5d4594f
SKApmTools: 72d09797ece888421c8930658e3c67c500dc2d72

PODFILE CHECKSUM: ef423484222a246d65153af8f35943a888efe5a3

Expand Down
36 changes: 27 additions & 9 deletions Example/Pods/Local Podspecs/SKApmTools.podspec.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 9 additions & 2 deletions Example/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

399 changes: 200 additions & 199 deletions Example/Pods/Pods.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions Example/SKApmTools/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {

UIImageView.initializeOnceSwift()
// UIImage.initializeOnceSwift()

let root = UINavigationController(rootViewController: ViewController())
root.view.backgroundColor = .white
window?.rootViewController = root
Expand Down
5 changes: 3 additions & 2 deletions Example/SKApmTools/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class ViewController: UIViewController {
btn.addTarget(self, action: #selector(btnClicked(_:)) , for: .touchUpInside)
view.addSubview(btn)
}

// 1.开启卡顿监测
SKANRMonitor.start()
let datas = SKANRMonitor.getPendingEntities()
print("待处理的卡顿数据数目: \(datas.count)")
Expand All @@ -40,7 +40,8 @@ class ViewController: UIViewController {
@objc func btnClicked(_ sender: UIButton) {
if let title = sender.title(for: .normal) {
if (title.elementsEqual("图片检测")) {
print("图片检测")
// 2.开启图片尺寸检查
SKImageMonitor.start()
let ctl = TestLoadImageController()
self.navigationController?.pushViewController(ctl, animated: true)
} else {
Expand Down
64 changes: 59 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,67 @@
# SKApmTools

APM性能优化相关(swift版本 ):ANR卡顿监测、网络优化、内存监控、启动优化、常见crash防护、crash监控上报

[![CI Status](https://img.shields.io/travis/Xcoder1011/SKApmTools.svg?style=flat)](https://travis-ci.org/Xcoder1011/SKApmTools)
[![Version](https://img.shields.io/cocoapods/v/SKApmTools.svg?style=flat)](https://cocoapods.org/pods/SKApmTools)
[![License](https://img.shields.io/cocoapods/l/SKApmTools.svg?style=flat)](https://cocoapods.org/pods/SKApmTools)
[![Platform](https://img.shields.io/cocoapods/p/SKApmTools.svg?style=flat)](https://cocoapods.org/pods/SKApmTools)
## Usage

APM性能优化相关(swift版本 ):ANR卡顿监测、网络优化、内存监控、启动优化、常见crash防护、crash监控上报
### 1.卡顿监测

开启卡顿监测

```swift
// 1.开启卡顿监测
SKANRMonitor.start()
SKANRMonitor.monitorCallback { curEntity, allEntities in
print("监测到卡顿: \(curEntity.validFunction)")
print(curEntity.threadId)
print(curEntity.occurenceTime)
print(curEntity.validAddress)
print(curEntity.traceContent)
}
```

控制台打印卡顿信息

```swift

监测到卡顿: SKApmTools_Example.ViewController.btnClicked(__C.UIButton) -> ()
259
692678740.80218
0x000000010621ccce
0 Foundation 0x00007ff800c7db5d +[NSThread sleepForTimeInterval:] + 163
1 SKApmTools_Example 0x000000010621ccce SKApmTools_Example.ViewController.btnClicked(__C.UIButton) -> () + 654
2 SKApmTools_Example 0x000000010621cd55 @objc SKApmTools_Example.ViewController.btnClicked(__C.UIButton) -> () + 53
3 UIKitCore 0x0000000107b9cd05 -[UIApplication sendAction:to:from:forEvent:] + 95
4 UIKitCore 0x00000001072fec74 -[UIControl sendAction:to:forEvent:] + 110
5 UIKitCore 0x00000001072ff078 -[UIControl _sendActionsForEvents:withEvent:] + 345
6 UIKitCore 0x00000001072fb203 -[UIButton _sendActionsForEvents:withEvent:] + 148
7 UIKitCore 0x00000001072fd8cf -[UIControl touchesEnded:withEvent:] + 485
8 UIKitCore 0x0000000107be1e95 -[UIWindow _sendTouchesForEvent:] + 1292
9 UIKitCore 0x0000000107be3ef1 -[UIWindow sendEvent:] + 5304
10 UIKitCore 0x0000000107bb77f2 -[UIApplication sendEvent:] + 898
11 UIKitCore 0x0000000107c5ee61 __dispatchPreprocessedEventFromEventQueue + 9381
12 UIKitCore 0x0000000107c61569 __processEventQueue + 8334
13 UIKitCore 0x0000000107c578a1 __eventFetcherSourceCallback + 272
14 CoreFoundation 0x00007ff800387035 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
15 CoreFoundation 0x00007ff800386f74 __CFRunLoopDoSource0 + 157
16 CoreFoundation 0x00007ff800386771 __CFRunLoopDoSources0 + 212
17 CoreFoundation 0x00007ff800380e73 __CFRunLoopRun + 927
18 CoreFoundation 0x00007ff8003806f7 CFRunLoopRunSpecific + 560
19 GraphicsServices 0x00007ff809c5c28a GSEventRunModal + 139
20 UIKitCore 0x0000000107b9662b -[UIApplication _run] + 994
21 UIKitCore 0x0000000107b9b547 UIApplicationMain + 123
22 SKApmTools_Example 0x000000010621e2df main + 63
23 dyld 0x00000001063e32bf start_sim + 10
24 ??? 0x0000000112c83310 0x0 + 4610077456
```

### 2.图片尺寸检测

开启图片尺寸检测

```swift
SKImageMonitor.start()
```

## Example

Expand Down
37 changes: 16 additions & 21 deletions SKApmTools.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,34 @@

Pod::Spec.new do |s|
s.name = 'SKApmTools'
s.version = '0.1.0'
s.summary = 'A short description of SKApmTools.'

# This description is used to generate tags and improve search results.
# * Think: What does it do? Why did you write it? What is the focus?
# * Try to keep it short, snappy and to the point.
# * Write the description between the DESC delimiters below.
# * Finally, don't worry about the indent, CocoaPods strips it!

s.version = '0.1.1'
s.summary = 'APM性能优化相关(swift版本 ):ANR卡顿监测、网络优化、内存监控、启动优化、常见crash防护、crash监控上报'
s.description = <<-DESC
TODO: Add long description of the pod here.
APM性能优化相关(swift版本 ):ANR卡顿监测、网络优化、内存监控、启动优化、常见crash防护、crash监控上报
DESC

s.homepage = 'https://github.com/Xcoder1011/SKApmTools'
# s.screenshots = 'www.example.com/screenshots_1', 'www.example.com/screenshots_2'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Xcoder1011' => 'shangkunwu@msn.com' }
s.source = { :git => 'https://github.com/Xcoder1011/SKApmTools.git', :tag => s.version.to_s }
# s.social_media_url = 'https://twitter.com/<TWITTER_USERNAME>'

s.ios.deployment_target = '10.0'

s.source_files = 'SKApmTools/Classes/**/*.{swift,h,c}'

s.pod_target_xcconfig = {
"DEFINES_MODULE" => "YES"
}

# s.resource_bundles = {
# 'SKApmTools' => ['SKApmTools/Assets/*.png']
# }

# s.public_header_files = 'Pod/Classes/**/*.h'
# s.frameworks = 'UIKit', 'MapKit'
s.dependency 'Kingfisher'
s.subspec 'BackTrace' do |ss|
ss.source_files = 'SKApmTools/Classes/BackTrace/*'
end

s.subspec 'ANR' do |ss|
ss.source_files = 'SKApmTools/Classes/ANR/*'
ss.dependency 'SKApmTools/BackTrace'
end

s.subspec 'ImageTool' do |ss|
ss.source_files = 'SKApmTools/Classes/ImageTool/*'
ss.dependency 'Kingfisher'
end
end
2 changes: 1 addition & 1 deletion SKApmTools/Classes/ANR/SKANRMonitor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import Foundation

@objc open class SKANRMonitor: NSObject{
@objc open class SKANRMonitor: NSObject {

@objc public static let sharedInstance = SKANRMonitor()
/// 单次耗时较长的卡顿阈值: 默认值为300ms,单位:毫秒
Expand Down
24 changes: 24 additions & 0 deletions SKApmTools/Classes/ImageTool/SKImageMonitor.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// SKImageMonitor.swift
// SKApmTools
//
// Created by WDMac on 2022/12/13.
//

import Foundation

@objc open class SKImageMonitor: NSObject {

@objc public static let sharedInstance = SKImageMonitor()

@objc public private(set) var enable: Bool = false

@objc public class func start() {
SKImageMonitor.sharedInstance.enable = true
UIImageView.initializeOnceSwift()
}

@objc public class func stop() {
SKImageMonitor.sharedInstance.enable = false
}
}
31 changes: 2 additions & 29 deletions SKApmTools/Classes/ImageTool/UIImageView+HookLoad.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ private var sk_urlKey: Void?

extension UIImageView {

/// runtime 记录url信息
private var sk_url: NSURL? {
get { return sk_getAssociatedObject(self, &sk_urlKey) }
set { sk_setRetainedAssociatedObject(self, &sk_urlKey, newValue)}
Expand All @@ -33,16 +32,12 @@ extension UIImageView {
}
}

/// 这里写一个公共的加载图片的方法,用于获取图片url相关信息,只是为了演示...
/// 真正不同的项目,可以通过hook每个项目中封装好的加载图片的方法,获取图片url相关信息
///
@objc public func loadImage(with url: NSURL?) {
if let url = url {
sk_url = url
if url.isFileURL {
self.image = UIImage(data: try! Data(contentsOf: url as URL))
} else {
// 这里用了Kingfisher也是为了演示网络图片
KF.url(url as URL).set(to: self)
}
}
Expand All @@ -59,8 +54,9 @@ extension UIImageView {
}

private func checkSize() {
guard SKImageMonitor.sharedInstance.enable else { return }
guard self.frame.size.height > 0 else { return }
guard let image = self.image , let cgimage = image.cgImage else { return }
guard let image = self.image else { return }

/// 1. 检查宽高比差异
let viewRatio = self.frame.size.width / self.frame.size.height
Expand All @@ -74,29 +70,6 @@ extension UIImageView {
if image.size.height / self.frame.size.height >= 2 && image.size.width / self.frame.size.width >= 2 {
print("-----⚠️⚠️⚠️ warnin: ----- 图片的大小是实际显示UI大小的2倍或以上,\(debugUrlInfo)")
}

/// 3. 检查图片size
/// 这里判断图片在内存中的大小阈值 还是 判断 图片原始 尺寸大小,都能通过url信息拿到原始尺寸大小
/// 比如本地图片可以通过FileManager.default.attributesOfItem(atPath:)获取size信息
///
let size = cgimage.bytesPerRow * cgimage.height / 1000
if size > 1024 * 2 {
print("-----⚠️⚠️⚠️ warnin: ----- >>>> image memory size = \(size)kb, \(debugUrlInfo)")
}

if let data = UIImagePNGRepresentation(image) {
let kBytes = data.count / 1000
if kBytes > 512 {
print("-----⚠️⚠️⚠️ warnin: ----- 尺寸大于512kb,\(debugUrlInfo)")
}
}

if let data = UIImageJPEGRepresentation(image, 0.5) {
let kBytes = data.count / 1000
if kBytes > 512 {
print("-----⚠️⚠️⚠️ warnin: ----- 尺寸大于512kb,\(debugUrlInfo)")
}
}
}

var debugUrlInfo: String {
Expand Down

0 comments on commit d23bdc3

Please sign in to comment.