【Linux】BCC 工具使用

BPF 同时被 2 个专栏收录
11 篇文章 3 订阅
11 篇文章 0 订阅

【Linux】BCC 工具使用

本实验参照该实验手册:linux-tracing-workshop

1. 缓慢的文件I/O

尝试跟踪由于I/O操作缓慢而表现出延迟的应用程序

编译并运行应用程序: 首先运行以下命令来编译logger应用程序,让其在后台执行

[root@rumia linux-tracing-workshop-master]$ gcc -g -fno-omit-frame-pointer -O0 -pthread logger.c -o logger
[root@rumia linux-tracing-workshop-master]$./logger

收集I/O延迟信息:/bcc/tools目录下执行.能够快速看到logger应用程序执行的一些较大的I/O 比其他较小的I/O花费的时间更长

[root@rumia tools]$ ./biosnoop.py
TIME(s)     COMM           PID    DISK    T SECTOR     BYTES  LAT(ms)
0.000000    logger         28988  sda     W 16668104   262144    2.75
0.000024    logger         28988  sda     W 16668616   262144    2.75
0.000047    logger         28988  sda     W 16669128   262144    2.77
0.000282    logger         28988  sda     W 16669640   262144    2.99
0.001292    logger         28988  sda     W 10504856   4096      0.75
0.011483    logger         28988  sda     W 17394904   4096      0.94
0.012350    logger         28988  sda     W 10504864   4096      0.73

观察文件I/O操作缓慢: 查看它正在写哪些文件,哪些操作所需的时间比其他时间长

[root@rumia tools]$ ./fileslower.py 1
Tracing sync read/writes slower than 1 ms
TIME(s)  COMM           TID    D BYTES   LAT(ms) FILENAME
0.023    logger         28988  W 1024       1.94 log.data
0.041    logger         28989  W 1048576    6.15 flush.data
0.044    logger         28988  W 1024       1.61 log.data
0.066    logger         28988  W 1024       1.95 log.data
0.088    logger         28988  W 1024       1.82 log.data

2. 追踪泄漏

请确保内核版本高于4.6

编译并运行应用程序: 使用javac编译完成后, 运行java XXX.class

// 内存泄漏场景
static Map map = new HashMap();

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    for (int i = 0; i < 100000000; i++) {
        byte[] b = new byte[10*10];
        map.put(i,b);
    }
    System.out.println(map);
}

寻找泄漏源: memleak附加到内存分配和释放功能,并收集所有未释放的分配的数据。具体来说,对于用户模式C ++应用程序,memleak可以将其附加到libc 的mallocfree函数。对于内核内存泄漏,memleak可以附加到kmallockfree函数

$ ./memleak.py -p 18052

默认情况下,memleak将打印按剩余分配排序的前10个堆栈-也就是说,由于该工具已附加到您的进程中,已执行但未释放的分配。尝试自己分析这些调用堆栈

[00:49:23] Top 10 stacks with outstanding allocations:
	16 bytes in 1 allocations from stack
		os::malloc(unsigned long, MemoryType, NativeCallStack const&)+0xad [libjvm.so]
		CHeapObj<(MemoryType)6>::operator new(unsigned long, NativeCallStack const&)+0x19 [libjvm.so]
		CHeapObj<(MemoryType)6>::operator new(unsigned long)+0x75 [libjvm.so]
		add_derived_oop(oopDesc**, oopDesc**)+0x33 [libjvm.so]
		OopMapSet::oops_do(frame const*, RegisterMap const*, OopClosure*)+0x187 [libjvm.so]
		frame::oops_do_internal(OopClosure*, CLDClosure*, CodeBlobClosure*, RegisterMap*, bool)+0x99 [libjvm.so]
		JavaThread::oops_do(OopClosure*, CLDClosure*, CodeBlobClosure*)+0x185 [libjvm.so]
		ThreadRootsMarkingTask::do_it(GCTaskManager*, unsigned int)+0x10a [libjvm.so]
		GCTaskThread::run()+0x172 [libjvm.so]
		java_start(Thread*)+0xf2 [libjvm.so]
		start_thread+0xc5 [libpthread-2.17.so]

3. 启用和跟踪JVM USDT探针

OpenJDK还配备了许多USDT探针。它们中的大多数都是开箱即用的,有些必须启用特殊-XX:+ExtendedDTraceProbes标志,因为它们会导致性能下降。要探索其中的一些探针,请导航至$JAVA_HOME并查看tapset目录

这些.stp文件包含一堆探针的描述和声明,包括其参数。例如,尝试查找gc_collect_tenured_begingc_collect_tenured_end探针描述。

$ cd /etc/alternatives/java_sdk
$ ls tapset/
hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp     hotspot_jni-1.8.0.242.b08-0.el7_7.x86_64.stp
hotspot_gc-1.8.0.242.b08-0.el7_7.x86_64.stp  jstack-1.8.0.242.b08-0.el7_7.x86_64.stp

现在,让我们来看一个更实际的例子。现在,您将通过使用class_loaded探针来跟踪正在运行的Java应用程序,并查看正在加载哪些类。首先,通过运行以下命令: 看起来有四个参数,并且正在加载的类名作为第一个参数给出

$ grep -A 10 'probe.*class_loaded' tapset/*.stp
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp:probe hotspot.class_loaded =
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  process("/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/amd64/server/libjvm.so").mark("class__loaded")
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-{
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  name = "class_loaded";
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  class = user_string_n($arg1, $arg2);
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  classloader_id = $arg3;
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  is_shared = $arg4;
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-  probestr = sprintf("%s(class='%s',classloader_id=0x%x,is_shared=%d)",
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-                     name, class, classloader_id, is_shared);
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-}
tapset/hotspot-1.8.0.242.b08-0.el7_7.x86_64.stp-

此时,我们可以运行一个Java应用程序

$ java slowy/App

现在,使用tplist以下命令发现可用的跟踪点:

$ jps
19322 App
19391 Jps
$ ./tplist.py -p 19322 '*class*loaded'
/proc/19322/root/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/amd64/server/libjvm.so hotspot:class__unloaded
/proc/19322/root/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.242.b08-0.el7_7.x86_64/jre/lib/amd64/server/libjvm.so hotspot:class__loaded

最后,我们可以使用跟踪有趣的跟踪点trace,此时,每当Java应用程序加载类时,您都应该获得一条跟踪消息

cd /bcc/tools
$./trace.py 'u:/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.77-1.b03.fc22.x86_64/jre/lib/amd64/server/libjvm.so:class__loaded "%s", arg1'

PID     TID     COMM            FUNC             -
28625   28626   java            class__loaded    java/util/Formatter
28625   28626   java            class__loaded    java/util/regex/Pattern
28625   28626   java            class__loaded    java/util/regex/Pattern$Node
[...]
28625   28626   java            class__loaded    java/util/regex/Pattern$Start
28625   28626   java            class__loaded    java/util/regex/Pattern$TreeInfo
28625   28626   java            class__loaded    java/util/Locale$Category
28625   28626   java            class__loaded    java/util/Locale$1
[...]
28625   28626   java            class__loaded    java/util/Formatter$Conversion
28625   28626   java            class__loaded    java/lang/Shutdown
28625   28626   java            class__loaded    java/lang/Shutdown$Lock
  • 0
    点赞
  • 0
    评论
  • 1
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
用于windows下面的vim编辑器。 给喜欢vim的人使用。详细如下: 好吧,详细点,这里写出一些基本的命令: 【什么是vi】 vi就是linux命令行下的最著名的编辑器之一,(编辑器就是类似windows记事本的功能,不过vi功能比记事本强大无限倍!^_^),现在实际使用的都是vim,它是vi的改进版本,所以现在的vi基本上就是vim了。 【vi能做什么】 第一个功能不用多说,vi可以编辑文本文件。至于其他的功能,多得无法列举,我只说我所知的一些典型的功能应用: (1)编辑文本文件 (2)方便地阅读程序源代码 (3)当文件目录浏览器来用 (4)提供编程、调试环境 (5)利用vi执行一些脚本文件(vi有自己的脚本文件语法) (x)等等等等...... 【vi的操作模式】   vi具有两种基本模式,为输入模式(或插入模式、编辑模式)和指令模式(或命令模式)。输入模式下输入字符,文本就会显示在屏幕上;而指令模式下输入字符就解释为一个输入命令并执行,而不会显示相应的字符。理解指令模式最简单方式就是想象平时剪切、复制以及粘贴数据时所发生的情况。 使用[Esc]键可以停止当前操作(插入或者命令)重新回到指令模式,准备接受新的指令。如果本来就在指令模式下面,将会响铃一下。 【最基本的使用】 这里提供了使用vi得最基本的操作,能够实现大多数的编辑目的。如果你肯花几分钟把“最基本的使用”的内容都实践一下,那么你至少可以独立地在vim中朝你想要得方向“前进”了。如果你不想学习,那么就把它当作一个“字典”吧。 *用vi打开一个文件: 输入“vi filename”. 这里,filename就是你要打开的文件的名字,默认打开文件后vi处于指令模式。 *进入编辑模式编辑打开的文件: 输入“i”. 或输入“a”. 进入编辑模式后,你可以直接敲入想要输入的字符到文件,两者的区别是i在当前字符前面开始插入,a在当前字符后面开始插入。 *退出编辑模式: 输入“[Esc]”. 这样,将返回指令模式,准备接收你要传达给vi的指令并执行,如果之前已经在指令模式下,那么系统将响铃提醒一下。 **以下命令都是在命令模式下进行: *撤销修改: 输入“u”. 这里,相比以前的vi来说,vim支持多步撤销。 *恢复修改: 输入“[Ctrl]r”. 这里,和撤销命令相反,是撤销的撤销,也可多步。 *复制行到剪切板: 输入“yy”. *复制选定内容到剪切板: (1)输入“v”。 (2)按方向键将高亮选择的内容。 (3)输入“y”。 这里,开始输入v使vi临时进入了一个"选择模式",输入方向键可以选择,输入y将选择的内容复制剪切板。 *删除行: 输入“dd”. 注意,vi的删除等价于剪切,删除的内容会保存到剪切板中。 *删除选定内容: (1)输入“v”。 (2)按方向键将高亮选择的内容。 (3)输入“d”。 这里,开始输入v使vi临时进入了一个“选择模式”,输入方向键可以选择,输入d将选择的内容删除。 *粘贴: 输入“p”. 这样会将剪切板的内容粘贴到光标位置或者光标下一行。 *查找字符并定位到第一个匹配处: 输入“/character”. 这里character是待查找的字符,只要先输入/,再输入待查字符,最后回车即可定位到第一个匹配的字符处。 *定位到匹配查找的下一个字符处: 输入“n”. *定位到匹配查找的上一个字符处: 输入“N”. *保存文件: 输入“:w”. 注意w前面的':',输入':'之后,vim会将':'之后的输入解释为待执行的指令。 *退出: 输入“:q”. 这里,如果文件没有保存,将提示无法退出,除非你强制退出,不保存文件,或者保存退出。 *强制退出: 输入“:q!”. *保存退出: 输入“:wq”. 或输入“ZZ”. *察看帮助 输入":help". ** 另外还有一个简易的教程: 输入命令:vimtutor.
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值