我的站点

一个系统软件工程师的随手涂鸦

Tag: DTrace

Profiling CPU使用

本文内容取自于《Systems Performance: Enterprise and the Cloud》

Profiling CPU的方法是通过对CPU状态进行周期性地采样,然后进行分析。包含5个步骤:

1. Select the type of profile data to capture, and the rate.
2. Begin sampling at a timed interval.
3. Wait while the activity of interest occurs.
4. End sampling and collect sample data.
5. Process the data.

CPU采样数据基于下面两个因素:

a. User level, kernel level, or both
b. Function and offset (program-counter-based), function only, partial stack trace, or full stack trace

抓取user levelkernel level所有的函数调用栈固然可以完整地得到CPUprofile,但这样会产生太多的数据。因此通常只采样user levelkernel level部分函数调用栈就可以了,有时可能仅需要保留函数的名字。

下面是一个使用DTraceCPU采样的例子:

 # dtrace -qn 'profile-997 /arg1/ {@[execname, ufunc(arg1)] = count();} tick-10s{exit(0)}'

 top                                                 libc.so.7`0x801154fec                                             1
 top                                                 libc.so.7`0x8011e5f28                                             1
 top                                                 libc.so.7`0x8011f18a9                                             1

 

*NIX & Hacking —— 第9期

做一本我感兴趣的杂志,就这么简单!

Assembler

Assembler relaxation

GDB

GDB dashboard

Go

Best practices for a new Go developer
On Go, Portability, and System Interfaces

Kernel

A Toure of Bootloading
GRUB 2 bootloader – Full tutorial
How I ended up writing new real-time kernel
Kernel bypass
Linux Kernel Crash Book

Network

TCP in 30 instructions

RMS

Interviews: RMS Answers Your Questions

Rust

Why Rust?

Tracing

Dynamic Tracing with DTrace & SystemTap

*NIX & Hacking —— 第6期

做一本我感兴趣的杂志,就这么简单!

CPU

Is there a way to dump a CPU’s CPUID information?

DTrace

Reducing RAM usage in pkgin

Git

365GIT
Deal with git am failures
Ry’s Git Tutorial

Golang

cgasm
Embedding Lua in Go
GopherCon 2015
GoWork
go-torch

Kernel

Getting into Linux Kernel Development
KernelDebuggingTricks
vmlinuz Definition

Python

Functional Programming in Python
Fun with BPF, or, shutting down a TCP listening socket the hard way

Unix

On Hurd, Linux and the (mis)adventures of cross-compiling a GNU Hurd toolchain
Unix as IDE: Introduction

Easter egg

What are some good computer tricks that are not commonly known?
Why aren’t there a lot of old programmers at software companies?
x86 Exploitation 101: “House of Lore” – People and traditions

使用Dtrace检查recv()的返回值

这周在新的产品版本上线后,发现监控日志总是会报recv()返回error,并且errno是131(ECONNRESET)。查了一下man手册,发现并没有说recv()会返回ECONNRESET,于是自己便打算一探究竟。想到最近正在学习Dtrace,于是便写了下面这个简单脚本(check_recv.d):

#!/usr/sbin/dtrace -qs

syscall::recv:return
/(int)arg0 <=0 && pid == $1/
{
    printf("recv return: tid=%d, arg0=%d, errno=%d\n", tid, arg0, errno);
}

第四行是触发探针条件:当recv返回0或者-1并且进程号等于输入监控的进程号。
第六行是输出:线程ID,recv()返回值,errno。
使用方法 :check_recv.d 19771(监控进程号)
通过运行脚本,我发现其实recv()返回的是0,而errno也是0,那么为什么监控日志会输出errno是131呢?我又查了一下这个版本新加的代码,发现了下面的逻辑:

if (recv() <= 0)
{
    log(errno)
}

原来在recv()返回0时,也会输出errno。而在recv()返回0时,是不会更新errno的值,只有在recv()返回-1时,才会更新errno的值。所以现在监控日志里的errno其实是以前某个系统调用错误时设置的errno。所以代码应该改为:

if (recv() < 0)
{
    log(errno)
}

问题解决!

Powered by WordPress & Theme by Anders Norén