• tracer ftrace笔记(6)—— SQL查询 Hello


    一、简介

    1. 以.perfetto后缀的trace文件解析窗口中,搜索栏中输入":"后进入SQL查询窗口,查询的结果会显示在trace解析界面下面,点击会跳转到trace上对应位置。若是想单独窗口显示查询结果,可以点击左侧边栏上的"Query(SQL)",输入SQL预计后按Ctrl+Enter触发查询,但是这种查询的结果点击不会跳转。

    2. 几个常用的Table/View的格式及关键字段信息:

    slice表,横向track上的一条条小片段
    ts:片段起始时间戳(单位ns)
    dur:片段持续时长(ns)
    track_id:属于哪个track(水平timeline)
    name:片段标注的名称,对应Trace中打印的方法名、标记等信息

    二、Table和关键字段信息

    1. slice表,也即片段表,描述横向track上的一条条小片段,也是最重要的一个表

    ts:片段起始时间戳(单位ns)
    dur: 片段持续时长(ns)
    track_id: 属于哪个track(哪个水平timeline)
    name: 片段标注的名称,对应trace中打印的方法名、标记等信息

    2. thread_track 表,描述线程track

    id: track id,就是一个横向的timeline,每个track都有一个唯一id.
    utid:标识线程id,并不是调度上的线程tid。只是表里面的一个标志,多个表进程join互联的时候用作一个关键字进行查询的

    3. thread表,对应各线程信息

    utid:标识线程id,并不是调度上的线程tid。utid 和 thread_track表的 utid 关联,方便两个表之间join连接。
    name: 线程名
    tid: 调度上的真实的tid


    4. process表,对应各进程信息

    upid: 进程的标志,并非调度上的进程的pid。其作用是和thread表中的upid关联,表示thread所属的进程。
    pid: 表示进程真实的pid.
    uid: 进程身份uid


    5. sched_slice表,CPU信息区中描述线程调度片段

    cpu:当前调用片段运行在哪个cpu上。
    end_state: 当前片段结束后的线程的状态。
    priority: 线程优先级(0-139)


    6. thread_state表,描述各track上边的线程调度片段,标识线程运行状态

    utid: 标识线程id,对应thread表同名字段。
    cpu: 当前slice所在的线程运行在哪个CPU上。
    state: 线程状态

    对这些表结构了解后,就可以写SQL进行查询了。


    三、常用查询脚本

    1. 列出所有doFrame片段,按耗时倒序排列,取前100条

    select
        slice_id, track_id, ts,dur, dur/1e6, name
    from
        slice
    WHERE
        name like '%doFrame%'
    order by dur desc limit 100

    2. 上面1中查询的基础上,指定process name为systemui,即systemui自身的绘帧信息

    select
        slice_id, track_id, ts, dur, dur/1e6, slice.name
    from
        slice
    JOIN
        thread_track
    ON
        slice.track_id = thread_track.id
    JOIN
        thread USING(utid)
    JOIN
        process USING(upid)
    WHERE
        process.name = 'com.android.systemui' and slice.name like '%doFrame%'
    order by dur desc limit 100

    3. system_server 中各"OPF:"关键字片段(也可以缓冲其它片段)的耗时信息,包含各片段的真实running_time(每个slice可能有一段时间running,一段时间sleep,一段时间runnable,需要借助thread_state表来查询slice中各调度时间片的状态)

    select slice_id,track_id,thread.utid,slice.ts,slice.dur,(slice.dur/1e6) as dur_ms, (select total(case when thread_state.ts < slice.ts then MIN(slice.ts+slice.dur,thread_state.ts+thread_state.dur)-slice.ts when (thread_state.ts+thread_state.dur) > (slice.ts+slice.dur) then (slice.ts+slice.dur-MAX(thread_state.ts,slice.ts)) else thread_state.dur end) from thread_state where thread_state.utid=thread.utid and thread_state.state='Running' and thread_state.ts < (slice.ts+slice.dur) and (thread_state.ts+thread_state.dur) > slice.ts)/1e6 as total_running,slice.name from slice JOIN thread_track ON slice.track_id = thread_track.id JOIN thread USING(utid) JOIN process USING(upid) WHERE process.name='system_server' and slice.name like 'OPF:%' order by slice.dur desc limit 400

    前面一大堆操作是为了从墙上时间duration中提取真实的running时间。可将 like 'OPF:%' 换成 '%doFrame%',即可查看system_server中各 doFrame 时机运行时间。查询结果显示如下,表示doFrame持续时间是2.373769ms,这之间实际运行时间是1.988307ms:

    slice_id    track_id    utid    ts    dur    dur_ms    total_running    name
    6963    155    205    13304838190408    2373769    2.373769    1.988307    Choreographer#doFrame 15051
    ...

    4. system_server中的锁竞争情况(lockcontention),lock_depth表示当时参与此对象锁竞争的线程个数

    select count(1) as lock_depth, s.slice_id,s.track_id,s.ts,s.dur,s.dur/1e6 as dur_ms,ctn.otid,s.name
    from slice s, (select slice_id,track_id,ts,dur,name,substr(name, 46, instr(name,')')-46) as otid 
    from slice t
    WHERE name like 'Lock contention on a monitor lock %'
    order by dur) ctn
    JOIN thread_track ON s.track_id=thread_track.id JOIN thread USING(utid) JOIN process USING(upid)
    WHERE
        process.name = 'system_server'
    and s.name like 'Lock contention on a monitor lock %'
        and substr(s.name, 46, instr(s.name,')')-46) = ctn.otid
        and ctn.slice_id <> s.slice_id
        and ctn.ts >= s.ts and (ctn.ts+ctn.dur) <= (s.ts+s.dur)
    group by s.slice_id
    order by s.dur desc

    5. 查看trace的metadata

    select * from metadata

    6. 使用SQL定位一个片段

    (1) 查看trace的起始时间和结束时间

    select * from trace_bounds
    
    -- 显示内容如下,单位ns
    -- start_ts        end_ts
    -- 19768418232311    19787715757089

    (2) 因为trace上显示条目是相对时间,比如一个条目开始时间为"18s 938ms 179us 983ns",持续时间为"20ms 117us 447ns",想通过SQL脚本选中它需要换算成绝对时间,19768418232311 + 18938179983 = 19787356412294,写SQL为:

    --失败
    select * from slice where ts=19787356412294 and dur=20117447
    --成功
    select * from slice where ts > 19787356402294 and ts < 19787356422294 and dur > 20107447 and dur < 20127447

    但是由于数值近似值,不一定能选中,改为一个区间会好一些。

    四、补充

    1. Perfetto trace UI界面的左侧边栏的"Sample queries"下每个查询条目的SQL脚本都会显示出来,且"Debug SQL"条目下有很多现成的SQL模板脚本可以拷贝修改使用。

    参考:https://blog.csdn.net/feelabclihu/article/details/126672666

  • 相关阅读:
    Scrapy-02-item管道、shell、选择器
    django类视图的装饰器验证
    django禁用csrf
    django admin
    关系型数据库与非关系型数据库
    LINQ.CS
    测试
    测试
    一个测试
    WPF中的Style
  • 原文地址:https://www.cnblogs.com/hellokitty2/p/16700883.html
Copyright © 2020-2023  润新知