Skip to content

Instantly share code, notes, and snippets.

@siddontang
Last active December 24, 2020 01:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save siddontang/af37155035a5d5641e6a601fef661f4c to your computer and use it in GitHub Desktop.
Save siddontang/af37155035a5d5641e6a601fef661f4c to your computer and use it in GitHub Desktop.

Using dtrace to profile your program on Mac OSX.

Prepare

wget https://github.com/brendangregg/FlameGraph/archive/master.zip
unzip master.zip 
mv FlameGraph-master FlameGraph

wget https://raw.githubusercontent.com/siddontang/gprof2dot/master/gprof2dot.py
chmod +x gprof2dot.py

CPU

Trace the running program

Refer to https://github.com/brendangregg/FlameGraph#dtrace

# cat dtrace_cpu.sh
dtrace -x ustackframes=100 -n 'profile-97 /pid == $target/ { @[ustack()] = count(); } tick-60s { exit(0); }' -p $1 -o 
out.user_stacks
dtrace_cpu.sh 12345

Generate flamegraph

./stackcollapse.pl < out.user_stacks | ./FlameGraph/flamegraph.pl > user.svg

Generate Graph

gprof2dot.py -f dtrace out.user_stacks | dot -Tpng -o output.png

# Notice: sometimes, the dtrace outputs format may be latin-1, and gprof2dot will fail to parse it.
# To solve this problem, you should use iconv to convert to UTF-8 explicitly.
# TODO: add an encoding flag to tell gprof2dot how to decode the profile file.
iconv -f ISO-8859-1 -t UTF-8 out.user_stacks | gprof2dot.py -f dtrace

Memory

scripts

# cat mem_trace.d
#!/usr/sbin/dtrace -s

#pragma D option quiet
#pragma D option aggrate=100us
#pragma D option bufpolicy=fill
#pragma D option bufsize=100m

// rjem is only for jemalloc. 
/*
pid$1::_rjem_mallocx:entry
{
	self->trace = 1;
	self->size = arg0;
}

pid$1::_rjem_mallocx:return
/self->trace == 1/
{
	@stacks[ustack(10)] = count();
	
	self->trace = 0;
	self->size = 0;
}

pid$1::_rjem_rallocx:entry
{
	self->trace = 1;
	self->size = arg0;
}

pid$1::_rjem_rallocx:return
/self->trace == 1/
{
	@stacks[ustack(10)] = count();
	
	self->trace = 0;
	self->size = 0;
}
*/

pid$1::malloc:entry
{
	self->trace = 1;
	self->size = arg0;
}

pid$1::malloc:return
/self->trace == 1/
{
	@stacks[ustack(10)] = count();
	
	self->trace = 0;
	self->size = 0;
}

profile:::tick-10s 
{
	exit(0);
}

END 
{
	printa(@stacks);
}

Tracing

sudo ./mem_trace.d $1 > out.mem_stacks
iconv -f ISO-8859-1 -t UTF-8 out.mem_stacks| ./gprof2dot.py -f dtrace | dot -Tsvg -o mem_graph.svg
./FlameGraph/stackcollapse.pl < out.mem_stacks | ./FlameGraph/flamegraph.pl --color=mem  > mem.svg
@siddontang
Copy link
Author

image

@siddontang
Copy link
Author

image

@siddontang
Copy link
Author

image

@siddontang
Copy link
Author

image

@interma
Copy link

interma commented Oct 30, 2019

thanks! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment