Friday Mar 09, 2007

Adding Javascript Dtrace probes to Mozilla

Hi, as a follow on from my earlier post on adding dynamic instrumentation to mozilla, just wanted to let you all know that we have now put up a patch for Brendan Gregg's Javascript probes that will apply on top of the infrastructure patch we posted earlier :)

All of the probes listed in Brendan's Blog on JavaScript and DTrace will work:

Brendan's Javascript blog

Demo of the Javascript probes in action

But we have changed the namespace to be in sync with the other mozilla probes, so you will need to change the probe names in the script appropriately, for example:

Change: javascript\*:::function-entry to trace_mozilla\*:::js_function-entry

Applying the Javascript patch

Follow the instructions below to apply the Mozilla Infrastructure and layout patch:

Adding Dtrace probes to Mozilla

Then apply the Mozilla Javascript probe patch:

  • Apply mozilla-js.diff downloaded from bug 370906

$ cd mozilla
$ gpatch -p0  -i mozilla-js.diff

Rebuild mozilla as described above, not forgetting to run ./configure –enable-dtrace before hand. Test the probes have been applied by running the newly patched firefox-bin and listing the probes as described below.

Available Javascript Probes

To list the available javascript probes once the patch is applied and mozilla rebuilt with --enable-dtrace, just type:

$ cd mozilla/dist/bin
$ ./firefox-bin &
$ dtrace -n
'trace_mozilla\*:::js\*' -l
ID  PROVIDER             MODULE                  FUNCTION              NAME
35 trace_mozilla1815 jsdtrace_execute_done js_execute-done 35 trace_mozilla1815 jsdtrace_execute_done jsdtrace_execute_start 35 trace_mozilla1815 jsdtrace_execute_done js_execute-done



This script counts all of the javascript function calls that are being executed by firefox and lists the originating file for the javascript code, listed under FUNC and FILE respectively. You could use a predicate to exclude javascript being used by the browser's chrome UI if you wished, but this simple script just counts all of the function calls. See Brendan's blog for lots more examples :)

D option quiet
printf("Tracing...Hit Ctrl-C to end.\\n";);
@funcs[basename(copyinstr(arg0)), copyinstr(arg2)] = count();
printf("%-32s %-36s %8s\\n", "FILE", "FUNC","CALLS";);
printa("%-32s %-36s %@8d\\n", @funcs);
dtrace -s js_funcalls.d


FILE           FUNC                             CALLS
autocomplete.xml createEvent 1
autocomplete.xml dispatchEvent 1
: browser.xml QueryInterface 130
nsSessionStore.js QueryInterface 987
nsSessionStore.js getNext 988
nsSessionStore.js hasMoreElements 990

Wednesday Mar 07, 2007

Adding Dtrace Probes to Mozilla

Hi - we've been looking at adding a general framework for dynamic instrumentation to mozilla. On OpenSolaris this means dtrace probes :) The blurb from the submitted  bugzilla RFE gives you the general idea:


The main goal for this Dynamic Tracing Framework for Mozilla is to provide a common interface for adding instrumentation points or probes to Mozilla so its behavior can be easily observed by developers and administrators even in production systems. This framework will allow Mozilla to use the appropriate monitoring/tracing facility provided by each OS. OpenSolaris, FreeBSD and MacOS will use DTrace and other OSes can use their own respective tool.

All the gory details are up with the bug including the full proposal:

Bug 370906: [RFE] Dynamic Tracing Framework for Mozilla

Example 1 

A little sample output from Firefox built with --enable-dtrace and using the layout probes. The layout probes fire when a page is being loaded by Firefox. The phases that are triggered during the auto layout are frame construction, reflow [elements on the page need to be changed] and paint. All of these phases can be tracked by the probes, the times taken for each phase and whether one phase has triggered other phases, such as reflow causing new frame construction.

This script just counts the number and type of each phase that is triggered for a specific Presentation context. 

$ dtrace -qs layout_count.d -p `pgrep firefox-bin` -o out.txt

Snip from layout_count.d [see bug for full details]:
@[arg0, phaseStr[arg1], probefunc] = count();

Sample Output

$ cat out.txt | c++filt 
Pres Ctx Phase Count Function
153556424 [ paint ] 2 unsigned PresShell::Paint(nsIView\*,
nsIRenderingContext\*,const nsRegion)
169258584 [ frameCon ] 2 unsigned nsCSSFrameConstructor::CharacterDataChanged
140305640 [ frameCon ] 4 unsigned nsCSSFrameConstructor::ContentRemoved

This information is very important when tracking down hard to debug reflow bugs or when trying to understand performance timing data for specific pages. As we work with the probes we will start to look at how Firefox is interacting with the system as these phases are being triggered, such as what XServer traffic is being generated. This will be possible by combining the Firefox layout probes and the Xserver probes.


We are hacking away to improve the patch given feedback from the mozilla folks. But thought others might enjoy having a go now, so I've put down some general instructions if you are keen to try this on OpenSolaris :) We are putting in some layout probes which allow you to see the progress of frame construction, reflow and paint as a new page is loaded as a proof of concept. We will also provide a patch to add Brendan Gregg's Javascript probes in the next few days which should be an interesting adjunct to Mozilla's Javascript debugger. The hope is that others who have a lot more knowledge of the mozilla code base will start adding their own probes, once the infrastructure is in place to support them. The patch is still in review so a ways to go yet, but hopefully as others use them, the benefits will become clear. We have tried to make sure we minimize the probe impact and by default dtrace is not enabled in the build, you must build mozilla with ./configure --enable-dtrace to add any of the dtrace infrastructure.


All of the patches discussed below can be obtained from: Bug 370906


Getting Sources

  • Mozilla sources
    • Grab the mozilla sources from head: Mozilla CVS
    • If you need to do this from behind a firewall, you can use runsocks and set your CVS_RSH=ssh and your SOCKS5_SERVER=<socks server>
$ export CVSROOT=""
$ cvs login -> just hit return for password
$ cvs co mozilla

Applying Patches

  • Mozilla infrastructure + layout probe patch:
    • To get the diff patch, just go to the bug  370906 and look for "Mozilla Dynamic Tracing Framework + layout probes patch" in the Attachment table, click on it and do a save as mozilla-layout.diff
    • Apply mozilla-layout.diff downloaded from bug 370906 
$ cd mozilla
$ gpatch -p0 -i mozilla-layout.diff

Building Mozilla

  • Build mozilla
    • Setup mozilla for building:
$ export LD_LIBRARY_PATH=/usr/sfw/lib
$ export CC="/usr/bin/cc"
$ export CXX="/usr/bin/CC"
$ export CFLAGS="-xlibmil"
$ export CXXFLAGS="-xlibmil -xlibmopt -features=tmplife -norunpath"
$ export LDFLAGS="-R'\\$\\$ORIGIN:\\$\\$ORIGIN/..' -R/usr/sfw/lib"
  • Create a .mozconfig file under mozilla/.mozconfig containing the following:
ac_add_options --enable-xft
ac_add_options --disable-freetype2
ac_add_options --disable-tests
ac_add_options --disable-debug
ac_add_options --enable-svg
ac_add_options --enable-canvas
ac_add_options --enable-optimize
ac_add_options --enable-xinerama
ac_add_options --disable-auto-deps
ac_add_options --enable-application=browser
. $topsrcdir/browser/config/mozconfig
  • You must run autoconf to regenerate configure with the appropriate dtrace options; it needs to be version 2.13.
$ autoconf
$ ./configure --enable-dtrace
Note: this will generate a mozilla-trace.h from the mozilla-trace.d if one is not
present in the mozilla root directory.
$ gmake

Testing the Probes

  • The probes should now be present
    • Check Layout Probes are there.
$ cd mozilla/dist/bin
$ ./firefox-bin &
$ dtrace -n 'trace_mozilla\*:::layout\*' -l

Example 2

This sample script is using the layout start and end probes to time the various layout phases as they occur when a page is loaded by Firefox. The script will print out the Presentation context for each phase [identifies which context each phase is being triggered for], which allows them to be grouped together, along with the time taken for each phase and the function which is triggering that phase.

#!/usr/sbin/dtrace -s
#pragma D option quiet

enum eLayoutPhases { EPaint, EReflow, EFrameC};
phaseStr[EPaint] = "paint";
phaseStr[EReflow] = "reflow";
phaseStr[EFrameC] = "frameCon";

self->ts[probefunc, arg0, arg1] = timestamp;

/self->ts[probefunc, arg0, arg1]/
@phase_time[arg0, phaseStr[arg1], probefunc ] =
sum((timestamp - self->ts[probefunc, arg0, arg1])/1000);
self->ts[probefunc, arg0, arg1] = 0;

printf("%10s %10s %8s %-30s \\n", "Pres Ctx", "Phase", "Time(usec)", "Function" );
printa("%10d [ %8s ] %5@d %-30s \\n", @phase_time);

/x++ == $1/
{ exit(0);}

Sample Output

$ dtrace -qs layout_time.d -p `pgrep firefox-bin` -o out.txt
$ cat out.txt | c++filt
Pres Ctx Phase Time(usec) Function
156084568 [ frameCon ] 34 unsigned nsCSSFrameConstructor::CharacterDataChanged
141161216 [ frameCon ] 91 unsigned nsCSSFrameConstructor::ContentRemoved
141161216 [ frameCon ] 331 unsigned nsCSSFrameConstructor::ContentInserted
141161216 [ reflow ] 3458 unsigned PresShell::ProcessReflowCommands(int)
152558200 [ paint ] 6216 unsigned PresShell::Paint(nsIView\*,
nsIRenderingContext\*,const nsRegion )
141161216 [ paint ] 90459 unsigned PresShell::Paint(nsIView\*,
nsIRenderingContext\*,const nsRegion )





Top Tags
« April 2014