Skip to content

Commit

Permalink
Merge pull request ming1016#30 from erduoniba/master
Browse files Browse the repository at this point in the history
bugfix: 修复方法调用链路重复的问题
  • Loading branch information
ming1016 authored Dec 20, 2023
2 parents 9ec6fc7 + d56addd commit 33e1eca
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 14 deletions.
27 changes: 19 additions & 8 deletions GCDFetchFeed/GCDFetchFeed.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
3EE311701C4E212700103FA3 /* SMRootViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE3116F1C4E212700103FA3 /* SMRootViewController.m */; };
3EE311751C4E303600103FA3 /* SMFeedModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 3EE311741C4E303600103FA3 /* SMFeedModel.m */; };
8F3DCFAC671E00110311BDBE /* Pods_GCDFetchFeed.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3796ACD85E2DA28F1711CF41 /* Pods_GCDFetchFeed.framework */; };
D9DCCA782B329A1D00465F0F /* SMCallTraceDemo.m in Sources */ = {isa = PBXBuildFile; fileRef = D9DCCA772B329A1D00465F0F /* SMCallTraceDemo.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand All @@ -86,7 +87,6 @@
/* End PBXContainerItemProxy section */

/* Begin PBXFileReference section */
055B62180119DC2D35BCADD9 /* Pods-GCDFetchFeed.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GCDFetchFeed.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GCDFetchFeed/Pods-GCDFetchFeed.debug.xcconfig"; sourceTree = "<group>"; };
0866301727293784009D4501 /* fishhook.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fishhook.c; sourceTree = "<group>"; };
0866301827293784009D4501 /* fishhook.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fishhook.h; sourceTree = "<group>"; };
0A12F2661DE96864002ED910 /* STMURLCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = STMURLCache.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -147,6 +147,7 @@
0AEE64951D881563009E21C7 /* SMMapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMMapViewController.m; sourceTree = "<group>"; };
0AEE64981D883058009E21C7 /* ArtWork.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ArtWork.h; sourceTree = "<group>"; };
0AEE64991D883058009E21C7 /* ArtWork.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ArtWork.m; sourceTree = "<group>"; };
0E1C8B15B6322EA774EE06D2 /* Pods-GCDFetchFeed.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GCDFetchFeed.release.xcconfig"; path = "Pods/Target Support Files/Pods-GCDFetchFeed/Pods-GCDFetchFeed.release.xcconfig"; sourceTree = "<group>"; };
3796ACD85E2DA28F1711CF41 /* Pods_GCDFetchFeed.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_GCDFetchFeed.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3E58A8511C507BFD0026A610 /* SMRootCellViewModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMRootCellViewModel.h; sourceTree = "<group>"; };
3E58A8521C507BFD0026A610 /* SMRootCellViewModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMRootCellViewModel.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -210,7 +211,9 @@
3EE3116F1C4E212700103FA3 /* SMRootViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMRootViewController.m; sourceTree = "<group>"; };
3EE311731C4E303600103FA3 /* SMFeedModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SMFeedModel.h; sourceTree = "<group>"; };
3EE311741C4E303600103FA3 /* SMFeedModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SMFeedModel.m; sourceTree = "<group>"; };
BB29081F4A19D8EFBD4887AF /* Pods-GCDFetchFeed.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GCDFetchFeed.release.xcconfig"; path = "Pods/Target Support Files/Pods-GCDFetchFeed/Pods-GCDFetchFeed.release.xcconfig"; sourceTree = "<group>"; };
8123E856919C2C01C5BED146 /* Pods-GCDFetchFeed.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-GCDFetchFeed.debug.xcconfig"; path = "Pods/Target Support Files/Pods-GCDFetchFeed/Pods-GCDFetchFeed.debug.xcconfig"; sourceTree = "<group>"; };
D9DCCA762B329A1D00465F0F /* SMCallTraceDemo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SMCallTraceDemo.h; sourceTree = "<group>"; };
D9DCCA772B329A1D00465F0F /* SMCallTraceDemo.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SMCallTraceDemo.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -266,6 +269,8 @@
isa = PBXGroup;
children = (
0A35AD421F45B2D000780172 /* SMLagMonitor */,
D9DCCA762B329A1D00465F0F /* SMCallTraceDemo.h */,
D9DCCA772B329A1D00465F0F /* SMCallTraceDemo.m */,
);
path = Lib;
sourceTree = "<group>";
Expand Down Expand Up @@ -604,8 +609,8 @@
A386EE4060ADD261E13CC63F /* Pods */ = {
isa = PBXGroup;
children = (
055B62180119DC2D35BCADD9 /* Pods-GCDFetchFeed.debug.xcconfig */,
BB29081F4A19D8EFBD4887AF /* Pods-GCDFetchFeed.release.xcconfig */,
8123E856919C2C01C5BED146 /* Pods-GCDFetchFeed.debug.xcconfig */,
0E1C8B15B6322EA774EE06D2 /* Pods-GCDFetchFeed.release.xcconfig */,
);
name = Pods;
sourceTree = "<group>";
Expand Down Expand Up @@ -687,7 +692,8 @@
TargetAttributes = {
3EE311371C4E1F0800103FA3 = {
CreatedOnToolsVersion = 7.2;
DevelopmentTeam = 962Z8PV35L;
DevelopmentTeam = TKRM4J3XJV;
ProvisioningStyle = Manual;
};
3EE311501C4E1F0800103FA3 = {
CreatedOnToolsVersion = 7.2;
Expand Down Expand Up @@ -863,6 +869,7 @@
3E8341EF1C5257F4002C3EAA /* SMFeedListViewController.m in Sources */,
0AEE649A1D883058009E21C7 /* ArtWork.m in Sources */,
0A35AD4B1F45B32600780172 /* SMStackCell.m in Sources */,
D9DCCA782B329A1D00465F0F /* SMCallTraceDemo.m in Sources */,
3E58A8601C50B7270026A610 /* SMTitleLabel.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -992,23 +999,27 @@
};
3EE311661C4E1F0800103FA3 /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 055B62180119DC2D35BCADD9 /* Pods-GCDFetchFeed.debug.xcconfig */;
baseConfigurationReference = 8123E856919C2C01C5BED146 /* Pods-GCDFetchFeed.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
DEVELOPMENT_TEAM = 962Z8PV35L;
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = TKRM4J3XJV;
INFOPLIST_FILE = GCDFetchFeed/Info.plist;
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
OTHER_CFLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = com.starming.GCDFetchFeed;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = JingxiDev_18;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
3EE311671C4E1F0800103FA3 /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = BB29081F4A19D8EFBD4887AF /* Pods-GCDFetchFeed.release.xcconfig */;
baseConfigurationReference = 0E1C8B15B6322EA774EE06D2 /* Pods-GCDFetchFeed.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
4 changes: 4 additions & 0 deletions GCDFetchFeed/GCDFetchFeed/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#import "SMStyle.h"
#import "SMFeedModel.h"
#import "SMLagMonitor.h"
#import "SMCallTraceDemo.h"

#import <dlfcn.h>

Expand All @@ -25,6 +26,9 @@ @implementation AppDelegate


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

[SMCallTraceDemo test];

//这里是做卡顿监测
// [[SMLagMonitor shareInstance] beginMonitor];
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
Expand Down
19 changes: 19 additions & 0 deletions GCDFetchFeed/GCDFetchFeed/Lib/SMCallTraceDemo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// SMCallTraceDemo.h
// GCDFetchFeed
//
// Created by denglibing on 2023/12/20.
// Copyright © 2023 Starming. All rights reserved.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface SMCallTraceDemo : NSObject

+ (void)test;

@end

NS_ASSUME_NONNULL_END
100 changes: 100 additions & 0 deletions GCDFetchFeed/GCDFetchFeed/Lib/SMCallTraceDemo.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
//
// SMCallTraceDemo.m
// GCDFetchFeed
//
// Created by denglibing on 2023/12/20.
// Copyright © 2023 Starming. All rights reserved.
//

#import "SMCallTraceDemo.h"

#import "SMCallTrace.h"

@implementation SMCallTraceDemo

+ (void)test {
[SMCallTrace start];

[self test1_1];
[self test2_1];
[self test3_1];

[self test1_1];
[self test2_1];
[self test3_1];

[SMCallTrace stop];
[SMCallTrace save];

// 打印的日志如下:
/*
0| 39.11|+[SMCallTraceDemo test1_1]
1| 13.03| +[SMCallTraceDemo test1_2]
1| 14.02| +[SMCallTraceDemo test1_3]
0| 69.08|+[SMCallTraceDemo test2_1]
1| 23.02| +[SMCallTraceDemo test2_2]
1| 24.03| +[SMCallTraceDemo test2_3]
0| 99.32|+[SMCallTraceDemo test3_1]
1| 33.13| +[SMCallTraceDemo test3_2]
1| 34.14| +[SMCallTraceDemo test3_3]
0| 39.29|+[SMCallTraceDemo test1_1]
1| 13.09| +[SMCallTraceDemo test1_2]
1| 14.06| +[SMCallTraceDemo test1_3]
0| 68.76|+[SMCallTraceDemo test2_1]
1| 23.06| +[SMCallTraceDemo test2_2]
1| 24.13| +[SMCallTraceDemo test2_3]
0| 99.24|+[SMCallTraceDemo test3_1]
1| 33.09| +[SMCallTraceDemo test3_2]
1| 34.07| +[SMCallTraceDemo test3_3]
*/
}

+ (void)test1_1 {
usleep(11 * 1000);
[self test1_2];
[self test1_3];
}

+ (void)test1_2 {
usleep(12 * 1000);
}

+ (void)test1_3 {
usleep(13 * 1000);
}

+ (void)test2_1 {
usleep(21 * 1000);
[self test2_2];
[self test2_3];
}

+ (void)test2_2 {
usleep(22 * 1000);
}

+ (void)test2_3 {
usleep(23 * 1000);
}


+ (void)test3_1 {
usleep(31 * 1000);
[self test3_2];
[self test3_3];
}

+ (void)test3_2 {
usleep(32 * 1000);
}

+ (void)test3_3 {
usleep(33 * 1000);
}

@end
22 changes: 18 additions & 4 deletions GCDFetchFeed/GCDFetchFeed/Lib/SMLagMonitor/SMCallTrace.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,14 +43,18 @@ + (void)save {
model.path = [NSString stringWithFormat:@"[%@ %@]",model.className,model.methodName];
[self appendRecord:model to:mStr];
}
// NSLog(@"%@",mStr);
NSLog(@"\n%@",mStr);
}
+ (void)stopSaveAndClean {
[SMCallTrace stop];
[SMCallTrace save];
smClearCallRecords();
}
+ (void)appendRecord:(SMCallTraceTimeCostModel *)cost to:(NSMutableString *)mStr {
if (cost.callDepth == 0) {
[mStr appendFormat:@"\n"];
}
[mStr appendFormat:@"%@\n", [cost des]];
// [mStr appendFormat:@"%@\n path%@\n",[cost des],cost.path];
if (cost.subCosts.count < 1) {
cost.lastCall = YES;
Expand Down Expand Up @@ -80,6 +84,12 @@ + (void)appendRecord:(SMCallTraceTimeCostModel *)cost to:(NSMutableString *)mStr
model.isClassMethod = class_isMetaClass(rd->cls);
model.timeCost = (double)rd->time / 1000000.0;
model.callDepth = rd->depth;
model.lr = rd->lr;

if (rd->caller_record != NULL) {
model.callerLr = rd->caller_record->lr;
}

[arr addObject:model];
}
NSUInteger count = arr.count;
Expand All @@ -89,14 +99,18 @@ + (void)appendRecord:(SMCallTraceTimeCostModel *)cost to:(NSMutableString *)mStr
[arr removeObjectAtIndex:i];
//Todo:不需要循环,直接设置下一个,然后判断好边界就行
for (NSUInteger j = i; j < count - 1; j++) {
//下一个深度小的话就开始将后面的递归的往 sub array 里添加
if (arr[j].callDepth + 1 == model.callDepth) {
// 下一个深度小的话就开始将后面的递归的往 sub array 里添加
// ⚠️⚠️ 这里的bug:不能根据 callDepth 来判断,不然所有层级相等的深度,都在一个调用链路中了
// 需要根据调用链路来关联
if (arr[j].lr == model.callerLr) {
NSMutableArray *sub = (NSMutableArray *)arr[j].subCosts;
if (!sub) {
sub = [NSMutableArray new];
arr[j].subCosts = sub;
}
[sub insertObject:model atIndex:0];
if (![sub containsObject:model]) {
[sub addObject:model];
}
}
}
i--;
Expand Down
14 changes: 13 additions & 1 deletion GCDFetchFeed/GCDFetchFeed/Lib/SMLagMonitor/SMCallTraceCore.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,13 @@ static smCallRecord *_smCallRecords;
static int _smRecordNum;
static int _smRecordAlloc;

typedef struct {
typedef struct thread_call_record {
id self; //通过 object_getClass 能够得到 Class 再通过 NSStringFromClass 能够得到类名
Class cls;
SEL cmd; //通过 NSStringFromSelector 方法能够得到方法名
uint64_t time; //us
uintptr_t lr; // link register
struct thread_call_record *caller_record; //调用该方法的信息
} thread_call_record;

typedef struct {
Expand Down Expand Up @@ -87,6 +88,9 @@ static inline void push_call_record(id _self, Class _cls, SEL _cmd, uintptr_t lr
newRecord->cls = _cls;
newRecord->cmd = _cmd;
newRecord->lr = lr;
if (nextIndex > 0) {
newRecord->caller_record = cs->stack;
}
if (cs->is_main_thread && _call_record_enabled) {
struct timeval now;
gettimeofday(&now, NULL);
Expand Down Expand Up @@ -124,6 +128,14 @@ static inline uintptr_t pop_call_record() {
log->depth = curIndex;
log->sel = pRecord->cmd;
log->time = cost;
log->lr = pRecord->lr;
if (pRecord->caller_record != NULL) {
smCallRecord *caller_record = (smCallRecord *)malloc(sizeof(smCallRecord));
caller_record->cls = pRecord->caller_record->cls;
caller_record->sel = pRecord->caller_record->cmd;
caller_record->lr = pRecord->caller_record->lr;
log->caller_record = caller_record;
}
}
}
return pRecord->lr;
Expand Down
4 changes: 3 additions & 1 deletion GCDFetchFeed/GCDFetchFeed/Lib/SMLagMonitor/SMCallTraceCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
#include <stdio.h>
#include <objc/objc.h>

typedef struct {
typedef struct smCallRecord {
__unsafe_unretained Class cls;
SEL sel;
uint64_t time; // us (1/1000 ms)
int depth;
uintptr_t lr; // link register
struct smCallRecord *caller_record;
} smCallRecord;

extern void smCallTraceStart();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
@property (nonatomic, assign) NSUInteger frequency; //访问频次
@property (nonatomic, strong) NSArray <SMCallTraceTimeCostModel *> *subCosts;

@property (nonatomic, assign) uintptr_t lr; // 自身的 Link Register
@property (nonatomic, assign) uintptr_t callerLr; // 调用者的 Link Register

- (NSString *)des;

@end

0 comments on commit 33e1eca

Please sign in to comment.