jprof-log
and jprof-map
files. By collecting a large
number of these call stacks, it is possible to deduce where mozilla is spending
its time.
cvs co mozilla/tools/jprof
Next, configure your mozilla with jprof support by adding
--enable-jprof
to your configure options (eg adding
ac_add_options --enable-jprof
to your .mozconfig
) and
making sure that you do not have the
--enable-strip
configure option set -- jprof needs symbols to
operate.
Finally, build mozilla with your new configuration. Now you can run jprof.
kill -PROF
, or with kill -ALRM
if
JP_REALTIME is used, or with kill -POLL
(also known as kill -IO
) if JP_RTC_HZ is used).
freq
is the frequency
at which the timer should fire, measured in Hz. It must be a power of 2.
The maximal frequency allowed by the kernel can be changed by writing to
/proc/sys/dev/rtc/max-user-freq
; the maximum value it can be
set to is 8192. Note that /dev/rtc
will need to be readable
by the Firefox process; making that file world-readable is a simple way to
accomplish that.
A build with jprof enabled adds two functions to the Window object:
JProfStartProfiling()
and JProfStopProfiling()
. When used with JP_DEFER, these
allow one to start and stop the timer just around whatever critical section is
being profiled
setenv JPROF_FLAGS "JP_START JP_FIRST=3 JP_PERIOD=0.025"
setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.0015"
setenv JPROF_FLAGS "JP_DEFER JP_PERIOD=0.010 JP_REALTIME"
setenv JPROF_FLAGS "JP_DEFER JP_RTC_HZ=8192"
jprof can be paused at any time by sending a SIGUSR1 to mozilla (kill
-USR1
). This will cause the timer signals to stop and jprof-map to be
written, but it will not close jprof-log. Combining SIGUSR1 with the JP_DEFER
option allows profiling of one sequence of actions by starting the timer right
before starting the actions and stopping the timer right afterward.
After a SIGUSR1, sending another timer signal (SIGPROF, SIGALRM, or SIGPOLL (aka SIGIO), depending on the mode) can be used to continue writing data to the same output.
jprof-log
and jprof-map
files, we
can use the jprof executable is used to turn them into readable output. To do
this jprof needs the name of the mozilla binary and the log file. It deduces
the name of the map file:
./jprof /home/user/mozilla/debug/dist/bin/mozilla-bin ./jprof-log > tmp.htmlThis will generate the file
tmp.html
which you should view in a
web browser.
This shows that of the 151603 times the timer fired, 1777 (1.2% of the total) were inside nsStyleContext::GetStyleData() and 1552 (1.0% of the total) were in the nsCOMPtr_base destructor.Total hit count: 151603 Count %Total Function Name 8806 5.8 __libc_poll 2254 1.5 __i686.get_pc_thunk.bx 2053 1.4 _int_malloc 1777 1.2 nsStyleContext::GetStyleData(nsStyleStructID) 1600 1.1 __libc_malloc 1552 1.0 nsCOMPtr_base::~nsCOMPtr_base()
In general, the functions with the highest count are the functions which are taking the most time.
The function names are linked to the entry for that function in the hierarchical profile, which is described in the next section.
The information this block tells us is:141300 PL_ProcessPendingEvents 927 PL_ProcessEventsBeforeID 29358 0 142227 PL_HandleEvent 92394 nsInputStreamReadyEvent::EventHandler(PLEvent*) 49181 HandlePLEvent(ReflowEvent*) 481 handleTimerEvent(TimerEventType*) 158 nsTransportStatusEvent::HandleEvent(PLEvent*) 9 PL_DestroyEvent 4 __restore_rt
PL_HandleEvent
PL_HandleEvent
. Of these:
nsInputStreamReadyEvent::EventHandler
HandlePLEvent(ReflowEvent*)
handleTimerEvent
nsTransportStatusEvent::HandleEvent
PL_DestroyEvent
__restore_rt
PL_HandleEvent
:
PL_ProcessPendingEvents
PL_ProcessEventsBeforeID
This block corresponds to the function PL_HandleEvent
, which is
therefore bolded and not a link. The name of this function is preceded by
three numbers which have the following meaning. The number on the left (29358)
is the index number, and is not important. The center number (0) is the number
of times this function was interrupted by the timer. The last number (142227)
is the number of times this function was in the call stack when the timer went
off. That is, the timer went off while we were in code that was ultimately
called from PL_HandleEvent
.
For our example we can see that our function was in the call stack for 142227 interrupt ticks, but we were never the function that was running when the interrupt arrived.
The functions listed above the line for PL_HandleEvent
are its
callers. The numbers to the left of these function names are the numbers of
times these functions were in the call stack as callers of
PL_HandleEvent
. In our example, we were called 927 times by
PL_ProcessEventsBeforeID
and 141300 times by
PL_ProcessPendingEvents
.
The functions listed below the line for PL_HandleEvent
are its
callees. The numbers to the left of the function names are the numbers of
times these functions were in the callstack as callees of PL_HandleEvent
. In our example, of the 142227 profiler hits under PL_HandleEvent
92394 were under nsInputStreamReadyEvent::EventHandler
, 49181 were under HandlePLEvent(ReflowEvent*)
, and so forth.
#define JPROF_PTHREAD_HACK
near the beginning of
libmalloc.cpp
.