MySQL, dtrace, C++, Makefile.am, Now taking patches...

« previous entry | next entry »
Sep. 6th, 2007 | 10:01 am

One of those projects I have been meaning to do is add dtrace support
to MySQL. Since I have been working with the Sun this has been on my
list to do.

What is DTrace? It is a way to dynamically trace/measure an
application for systems supporting DTrace.
http://en.wikipedia.org/wiki/Dtrace

The project of adding these really was more about research then about
actual code. While there are a number of resources on the web for
adding dtrace probes to C, there are few that exist for C++. Also, C+
+ requires a later version of Solaris then what comes installed on
machines that Sun ships, so you will need to have a fairly recent
install of Solaris Express to make use of this.

First I am going to define a couple of probes in probes.d:

provider mysql {

probe external_lock(int);
probe insert_start();
probe insert_end();

};


Inside of handler.cc I modify the insert function as an example
dtrace extension (and probes.h was added as an include file):

int handler::ha_write_row(uchar *buf)
{
int error;
MYSQL_INSERT_START();
if (unlikely(error= write_row(buf)))
return error;
if (unlikely(error= binlog_log_row(table, 0,
buf)))
return error;
MYSQL_INSERT_END();
return 0;
}



Makefile.am was a pain, just because I never found the "best way" to
do it. I played around with a number of methods for adding probes.d
and finally came up with a suffix rule that worked. I suspect this
part of the patch I will rework to something which is a bit more
elegant over time. One thing to note for people writing C++ application. The -h flag for dtrace is the key to making these work with C++. It generates an include file with all of the proper information for accessing external C functions from C++. I've looked at how other projects have implemented their dtrace, most wrote their own include files. I suspect they did this because the -h flag was not in existence when they wrote their initial implementations.

30,32d29
< DTRACE = @DTRACE@
< DTRACEFLAGS = @DTRACEFLAGS@
< DTRACEFILES = handler.o
126,131d122
<
< if HAVE_DTRACE
< mysqld_SOURCES += probes.d
< endif
<
<
184d174
< SUFFIXES : .d
186,188d175
< .d.o :
< $(DTRACE) $(DTRACEFLAGS) -h -s $<
< $(DTRACE) $(DTRACEFLAGS) -G -s $< $(DTRACEFILES)



Finally I wrote up a new rule for configure.in. I've added an
sinclude for it so that I could keep it in a separate file (the MySQL
configure.in is way too long, so even removing small pieces from it
makes sense).

AC_ARG_ENABLE(dtrace,
[ --enable-dtrace Build with support for the DTRACE.],
[
AC_DEFINE([HAVE_DTRACE], [1], [Enables DTRACE Support])
AC_CHECK_PROGS(DTRACE, dtrace)
if test -z "$DTRACE"; then
AC_MSG_ERROR([dtrace not found])
fi
ENABLE_DTRACE="yes"
AC_SUBST(DTRACEFLAGS)
AC_SUBST(HAVE_DTRACE)
AM_CONDITIONAL([HAVE_DTRACE], [ test "$ENABLE_DTRACE" = "yes" ])
],
[ ENABLE_ASSEMBLER=no ]
)



What is now left?

We should write a little script to see what one looks like:

#!/usr/sbin/dtrace -qs
mysql$1:::insert_start
{
@start["Start"] = count();
self->ts = timestamp;
}

mysql$1:::insert_end
/self->ts/
{
@commit["Commit"] = count();
@time["Total time (ns)"] = sum(timestamp - self->ts);
self->ts=0;
}


And our output looks like:

# ./mysqld.d `pgrep -n mysqld`
Start 4
Commit 4
Total time (ns) 75417



The above is the cost of doing a single insert into a MyISAM table!
There are a lot more probes that can be added to the server

Want to help? Patches are always welcome!

Link | Leave a comment | Add to Memories | Share

Comments {0}