Giter VIP home page Giter VIP logo

bsbacktracelogger's Introduction

BSBacktraceLogger —— 轻量级调用栈分析器

这是一个强大且轻量的线程调用栈分析器,只有一个类,四百行代码。它支持现有所有模拟器、真机的 CPU 架构,可以获取任意线程的调用栈,因此可以在检测到 runloop 检测到卡顿时获取卡顿处的代码执行情况。

用法

#import "BSBacktraceLogger.h"

- (void)viewDidLoad {
    [super viewDidLoad];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
        BSLOG  // 打印当前线程的调用栈
        BSLOG_ALL  // 打印所有线程的调用栈
        BSLOG_MAIN  // 打印主线程调用栈
    });
    [self foo];
}

- (void)foo {
    [self bar];
}

- (void)bar {
    while (true) {
        ;
    }
}

定义了三个宏用于快速输出,或者调用 [BSBacktraceLogger bs_backtraceOfCurrentThread] 等函数获取字符串格式的调用栈。

样例

上述代码中,BSLOG_MAIN 这个宏的输出结果如下:

2016-08-27 18:33:20.017 BSBacktraceLogger[25215:862569] Backtrace of Thread 1803:
KtBacktraceLogger               0x10b831f4c -[ViewController bar] + 12
KtBacktraceLogger               0x10b831f2b -[ViewController foo] + 43
KtBacktraceLogger               0x10b831fe0 -[ViewController viewDidLoad] + 128
UIKit                           0x10c813984 -[UIViewController loadViewIfRequired] + 1198
UIKit                           0x10c813cd3 -[UIViewController view] + 27
UIKit                           0x10c6e9fb4 -[UIWindow addRootViewControllerViewIfPossible] + 61
UIKit                           0x10c6ea69d -[UIWindow _setHidden:forced:] + 282
UIKit                           0x10c6fc180 -[UIWindow makeKeyAndVisible] + 42
UIKit                           0x10c670ed9 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 4131
UIKit                           0x10c677568 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1769
UIKit                           0x10c674714 -[UIApplication workspaceDidEndTransaction:] + 188
FrontBoardServices              0x10f0e18c8 __FBSSERIALQUEUE_IS_CALLING_OUT_TO_A_BLOCK__ + 24
FrontBoardServices              0x10f0e1741 -[FBSSerialQueue _performNext] + 178
FrontBoardServices              0x10f0e1aca -[FBSSerialQueue _performNextFromRunLoopSource] + 45
CoreFoundation                  0x10c1e8301 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
CoreFoundation                  0x10c1de22c __CFRunLoopDoSources0 + 556
CoreFoundation                  0x10c1dd6e3 __CFRunLoopRun + 867
CoreFoundation                  0x10c1dd0f8 CFRunLoopRunSpecific + 488
UIKit                           0x10c673f21 -[UIApplication _run] + 402
UIKit                           0x10c678f09 UIApplicationMain + 171
KtBacktraceLogger               0x10b8338ff main + 111
libdyld.dylib                   0x10ea9c92d start + 1

说明

Xcode 的调试输出不稳定,有时候存在调用 NSLog() 但没有输出结果的情况,建议前往 控制台 中根据设备的 UUID 查看完整输出。

真机调试和使用 Release 模式时,为了优化,某些符号表并不在内存中,而是存储在磁盘上的 dSYM 文件中,无法在运行时解析,因此符号名称显示为 <redacted>

bsbacktracelogger's People

Contributors

bestswifter avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

bsbacktracelogger's Issues

获取到Thread堆栈信息后,还能做什么?

您好,假如下面是我在卡顿时,记录的Thread的堆栈信息:
Backtrace of Thread 10243:

libsystem_kernel.dylib 0x10d86834a mach_msg_trap + 10
CoreFoundation 0x108fd7e85 __CFRunLoopServiceMachPort + 213
CoreFoundation 0x108fd73c2 __CFRunLoopRun + 1730
CoreFoundation 0x108fd6a89 CFRunLoopRunSpecific + 409
Foundation 0x108950e5e -[NSRunLoop(NSRunLoop) runMode:beforeDate:] + 274
Foundation 0x1089ce9b7 -[NSRunLoop(NSRunLoop) runUntilDate:] + 87
UIKit 0x10ad9ec95 -[UIEventFetcher threadMain] + 118
Foundation 0x10895e8ac NSThread__start + 1197
libsystem_pthread.dylib 0x10d8a493b _pthread_body + 180
libsystem_pthread.dylib 0x10d8a4887 _pthread_start + 286
libsystem_pthread.dylib 0x10d8a408d thread_start + 13

问题是,我用上面这段信息,根本分析不出什么有价值的信息;
您有何建议?
或者说,用BSBacktraceLogger打出来的log, 还需要结合dsym和atos来符号化吗?

一个貌似重复判断的小问题

大神你好.拜读代码和博客,写的都非常详细,对我帮助很大.十分感谢~
现在有个小问题:代码173行和179行有两次主线程判断,能否解释一下为什么这样做?是有什么特殊的处理吗?
个人理解第一个主线程判断 return 掉以后,第二个判断应该是走不到的.
望解答~

if ([nsthread isMainThread]) {
    return (thread_t)main_thread_id;
}

for (int i = 0; i < count; ++i) {
    pthread_t pt = pthread_from_mach_thread_np(list[i]);
    if ([nsthread isMainThread]) {
        if (list[i] == main_thread_id) {
            return list[i];
        }
    }
    if (pt) {
        name[0] = '\0';
        pthread_getname_np(pt, name, sizeof name);
        if (!strcmp(name, [nsthread name].UTF8String)) {
            [nsthread setName:originName];
            return list[i];
        }
    }
}

请问为什么不用系统提供的dladdr方法,而需要自己写一个fl_dladdr呢?

系统提供的dladdr方法是线程安全的,而代码中的fl_dladdr其实底层调用的也是系统提供的_dyld_get_image_header和_dyld_get_image_name等方法,而这些方法是线程不安全的,经过我本人的实验对比,fl_dladdr返回的symbolbuffer和dladdr返回的结果是一样的,不清楚作者是出于什么样的考虑自己重写了一个fl_dladdr方法。

很多调用栈模块名没有识别出来

我的手机型号是iPhoneXR, iOS14.5版本,调用栈如下:
libobjc.A.dylib 0x1bd80f1e0 objc_msgSend + 32
libdispatch.dylib 0x1008fdd90 _dispatch_client_callout + 20
0x0000000000000000 0x8e66190100900e80 0x0 + 10260916293105356416
0x0000000000000000 0xc450230100916ca0 0x0 + 14145844916782197920
0x0000000000000000 0xe21599010090dea0 0x0 + 16291095456666148512
0x0000000000000000 0x75177501a8d301f8 0x0 + 8437341076889731576
0x0000000000000000 0x4e09cb81a8d2a0d0 0x0 + 5623249367492370640
0x0000000000000000 0x800f7b81a8d291c0 0x0 + 9227729958318805440
0x0000000000000000 0xd00cf701c0311734 0x0 + 14991628846501009204
0x0000000000000000 0x1608ce81ab7977e4 0x0 + 1587745924971067364
0x0000000000000000 0x112c2481ab79d054 0x0 + 1237404136966312020
0x0000000000000000 0x106b6981005399d4 0x0 + 1183155329892063700
libdyld.dylib 0x1a89e5cf8 + 4

循环一个子线程,第一次打印的堆栈有时候只有一条

dispatch_async(dispatch_get_global_queue(0, 0), ^{ // something for (NSInteger i = 0; i < 5000 ; i ++) { NSLog(@"index----- %@",@(i)); NSString * ddd = [KGPrintThreadSnapshoot bs_backtraceOfCurrentThread]; NSLog(@"bs_backtraceOfCurrentThread----- %@",ddd); } });

打印结果:
index==1
bs_backtraceOfCurrentThread----- Backtrace of Thread 3587:
libsystem_kernel.dylib 0x111127f72 mach_msg_trap + 10
index==2的时候 就准确了

unsigned integer overflow

https://github.com/bestswifter/BSBacktraceLogger/blob/master/BSBacktraceLogger/BSBacktraceLogger.m#L318

untime error: unsigned integer overflow: 20274 - 21786 cannot be represented in type 'unsigned long'

for(uint32_t iSym = 0; iSym < symtabCmd->nsyms; iSym++) {
// If n_value is 0, the symbol refers to an external object.
if(symbolTable[iSym].n_value != 0) {
uintptr_t symbolBase = symbolTable[iSym].n_value;
uintptr_t currentDistance = addressWithSlide - symbolBase;
if((addressWithSlide >= symbolBase) &&
(currentDistance <= bestDistance)) {
bestMatch = symbolTable + iSym;
bestDistance = currentDistance;
}
}
}

bs_machThreadFromNSThread will cause mach port leak?

thread_t bs_machThreadFromNSThread(NSThread *nsthread) {
    char name[256];
    mach_msg_type_number_t count;
    thread_act_array_t list;
    task_threads(mach_task_self(), &list, &count);
    
    NSTimeInterval currentTimestamp = [[NSDate date] timeIntervalSince1970];
    NSString *originName = [nsthread name];
    [nsthread setName:[NSString stringWithFormat:@"%f", currentTimestamp]];
    
    if ([nsthread isMainThread]) {
        return (thread_t)main_thread_id;
    }
    
    for (int i = 0; i < count; ++i) {
        pthread_t pt = pthread_from_mach_thread_np(list[i]);
        if ([nsthread isMainThread]) {
            if (list[i] == main_thread_id) {
                return list[i];
            }
        }
        if (pt) {
            name[0] = '\0';
            pthread_getname_np(pt, name, sizeof name);
            if (!strcmp(name, [nsthread name].UTF8String)) {
                [nsthread setName:originName];
                return list[i];
            }
        }
    }
    
    [nsthread setName:originName];
    return pthread_mach_thread_np(pthread_self());
}

this method will cause mach port leak

can host carthage?

Skipped building BSBacktraceLogger due to the error:
Dependency "BSBacktraceLogger" has no shared framework schemes for any of the platforms: iOS

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.