JavaScript setTimeout performance measurement
Intro
In HTML browser applications timer events are used all over. And it could impact
usability of HTML application in various ways. From slowness of UI interaction to
memory leaks and eventually death of application.
The application profiling methods are used for code efficiency measurement.
Profilers are available in most popular browsers to some extent, but the
high level analysis stays in developer's hands and quite subjective. Especially
when it comes to comparison of alternative code implementations.
Scope
- expose available measurements of performance and HTML/JS engine load
- enumerate some methods of efficiency improvement
- compare the methods in numbers
Measurements
The timer-related activities in HTML application mostly exposed as timer event
handling. Most popular low-level API is setTimer
, setInterval
, postMessage
and
special use of XHR. Platform also could provide own specific methods.
Difficult part is how to count application performance impact on those timer
event handlers
changes in attempt to tune them up.
I see the few criterias could be measured:
- Event handler timing. It will be most efficient and adequate method if not
facing few crucial "buts"
- discrete step for timer by JS
new Date().getTime()
stays is in the range of 15-30
ms. Which suppose to be longer of length for most timer event handlers.
But it will work for long (longer of double detectable time) timing
events.
- due to lack of reasonable functionality in native timer API event handlers are
usually wrapped by framework API. Which on its own has big impact on short
event handlers. For those in addition to individual handler timing, the
framework wrapper need to be tracked as well.
- System CPU load. Obviously it is indirect and not
precise. Will work only in
conditions where CPU utilization is high enough and
impact of say removal of
timer event handler will be
noticeable. The
artificial
bursting of timer event
handler calls to the level of good detection is needed. Also there is no CPU
utilization JS API exist. It could be simulated by count per second of dummy
events.
postMessage
or setTimeout
w/ zero interval. Just need to be sure that
platform does that asynchronously.
Another option is to have constant timeout but incrementally increase the load.
Say just loop on heavy math computations. Operations counter per second until
the timer interval is reached will give the CPU availability.
CPU load timing is not intrusive and do not chance characteristics of recearched
event handler. Also it allows check system load overall. I.e. no special
treatment for specific timer event handler. Also could be used for system
performance tracking on other recurrent event handlers like drag, mouse
movement, progress animations, etc.
Tips
My todo list during timer handlers optimization.
- Check the timing for event handler. If the execution time for event handler is
sizeable (>30ms) than we have easiest case and all needed is the timing stats.
Better to have average computation capabilities and good sampling set. Average
calculation could be oursourced instead of embedded in JS.
Obvoiusly accounting in proper/no exceptions execution: try/finally impacting
the performace themselves
- Collection of timing stats.
console.time
console.timeEnd
will be sufficient
If those are not available (like in IE)
- get time @ start
- print delta time @ end in format available for further average processing.
- OR keep global counter and total execution time, printing out average every time
@ end
- If event handler execution time is short or you do not want to alter the event
handlers themselves, than CPU load will be the criteria.
- Create the "CPU filler" routine. It shall act as low-priority thread, letting
remaining app to run.
- setTimeout with counter increment and comparing of the current time with
last detected. Once new time value changed, update the stats: counter per second
overall and for last second.
- Other statistics could be handy. Like max time delay between filler calls -
matching longest routine. Since there are few routines need to be tracked
separately, routine could set it's key and reset last timer value. That key will
be used for stats collection.
- Special treatement need to be done for 0 interval: it shall be ignored in MIN
stat computation due to minimum detectable interval (~30 ms)
- Trigger on/off collection of stats. Reset stats. The timing functionality could
be expensive. Especially in CPU load timing. The application load for
development comfort need to be as fast as possible.
Also the load timing is a separate problem and shall not be mixed with timer
events profiling. From another side it has a reason to trigger profiling
programmatically to see the impact in exact conditions and avoid mix with
inrelated statistics. Like start on begin drag and stop on release.
- Have a global flag(s) or hash map of "profiling enabled" flags. Check the flag
before collecting/printing timing
- Have the triggering code on start/stop or after application load. In Web 2.0
application the onLoad for body is not a proper place to start time-based
functionality (and obviously the timer events profiling): it is still the heavy
initialization phase.
-
Finally on app level
- collect stats for current app.
- validate by simulation of ideal performance tuning: timer event handler have
only
return
in body.
- do the real stuff and see how it goes!
Links
©2010 Sasha Firsov