Mobile/Powersaving/Wakeups/Debugging

From MozillaWiki
Jump to: navigation, search

Finding Wakeups

Finding Wakeups Using the Automatic Tool

  • First you apply this patch. It modifies some critical files, in particular in the condition variable handling code and in the timer thread code. It adds a parameter to both, so that when you call them, you must identify (by a string) who you are.
  • Then, you run python timeout_rewriter.py (that script is included in the patch). This goes through the entire codebase, rewriting all the calls to condition variables (PR_WaitCondVar etc.) and timer creation (->initWithCallback etc.) to add that parameter. It modifies both C++ and JS code. Over 100 files are modified. How it does the rewriting is sort of hackish: It doesn't use anything fancy, just some heuristics derived from trial and error ;)
  • Then build Firefox normally, and run it. All timeouts will then be printed with explanations. For details on how to interpret the output, see the original blog post.

Status of the tool:

  • Slightly underreports when compared to powertop. The reason is that each call to a wakeup-related function (like NotifyCondVar) can potentially lead to more than 1 wakeup. In other words, powertop measures absolute wakeups, the tool measures 'logical' wakeups. The two are proportional, so lowering one will lower the other. The ratio is something like 1:1.5.

Old Approaches to Finding Wakeups

Another approach to finding wakeups is to add some debug prints to the relevant NSPR functions, which are PR_WaitCondVar (in nsprpub/pr/src/pthreads) and so forth, e.g.

PR_IMPLEMENT(PRStatus) PR_WaitCondVar(PRCondVar *cvar, PRIntervalTime timeout)
{
   printf("PR_WaitCondVar %x ; %d\n", cvar, timeout);

This can give you some useful information when running. To further detect what code is calling the function, consider running the debugger and placing breakpoints there, then looking at a stack trace.

Debugger tips:

  • Placing a breakpoint in nsTimerImpl.cpp::Fire(), where it decides what callback to call ("switch (callbackType) {", currently line 425), can be very useful - simply step forward a little until you see what is being called.
  • Note that working in the debugger, with freezing/continuing etc., will mess up the normal wakeup timing. So after discovering the relevant suspects using the debugger, consider adding debug printouts and running outside of the debugger to see which are actually more important in practice.