JS::PerfMeasurement
is only functional on Linux, but it is planned to add support for Windows (bug 583322) and OSX (bug 583323) as well, and we welcome patches for other operating systems.The JS::PerfMeasurement
class, found in jsperf.h
, lets you take detailed performance measurements of your code. It is a stopwatch profiler -- that is, it counts events that occur while code of interest is running; it does not do call traces or sampling. The current implementation can measure eleven different types of low-level hardware and software events:
Bitmask passed to constructor | Counter variable | What it measures |
---|---|---|
PerfMeasurement::CPU_CYCLES | .cpu_cycles | Raw CPU clock cycles |
::INSTRUCTIONS | .instructions | Total instructions executed |
::CACHE_REFERENCES | .cache_references | Total number of memory accesses |
::CACHE_MISSES | .cache_misses | Memory accesses that missed the cache |
::BRANCH_INSTRUCTIONS | .branch_instructions | Branch instructions executed |
::BRANCH_MISSES | .branch_misses | Branch instructions that were not predicted correctly |
::BUS_CYCLES | .bus_cycles | Total memory bus cycles |
::PAGE_FAULTS | .page_faults | Total page-fault exceptions fielded by the OS |
::MAJOR_PAGE_FAULTS | .major_page_faults | Page faults that required disk access |
::CONTEXT_SWITCHES | .context_switches | Context switches involving the profiled thread |
::CPU_MIGRATIONS | .cpu_migrations | Migrations of the profiled thread from one CPU core to another |
These events map directly to "generic events" in the Linux 2.6.31+ <linux/perf_event.h>
interface, and so unfortunately are a little vague in their specification; for instance, we can't tell you exactly which level of cache you get misses for if you measure CACHE_MISSES
. We also can't guarantee that all platforms will support all event types, once we have more than one back end for this interface.
Here is the complete C++-level API:
- PerfMeasurement::EventMask
- This is an enumeration defining all of the bit mask values in the above table. You bitwise-OR the ones you want together and pass them to the constructor.
- PerfMeasurement::ALL
- In a constructor call, this special value means "measure everything that can possibly be measured."
- PerfMeasurement::NUM_MEASURABLE_EVENTS
- This constant equals the total number of events defined by the API - not necessarily the total number of events that a particular OS allows you to measure. (At time of writing, Linux allows all the above events to be measured, and we don't have back ends for any other operating system.
- static bool PerfMeasurement::canMeasureSomething()
- This class method returns true if and only if some -- not necessarily all -- events can be measured by the current build of SpiderMonkey, running on the current OS. At present, it returns true on Linux when the
<linux/perf_event.h>
API is available (kernel 2.6.31 or later), and false everywhere else. - PerfMeasurement::PerfMeasurement(EventMask toMeasure)
- The constructor creates a new profiling object, which measures some subset of the requested events.
- PerfMeasurement::~PerfMeasurement()
- Take care not to leak profiling objects, as they may be holding down expensive OS-level state.
- EventMask eventsMeasured
- Instances of PerfMeasurement expose this constant. It will not have any more bits set than were set in the mask passed to the constructor, but if the OS cannot or will not measure all of the requested events, then only those events that will actually be measured have their bits set. All the counter variables for events that are not being measured will have the fixed value
(uint64)-1
. - void start()
- Call this on a PerfMeasurement instance to start timing.
- void stop()
- And call this to stop timing again. The counter variables do not update in real time; they only change when
stop
is called. Counter values are accumulated across many start/stop cycles, and you can modify their values if you want;stop
simply adds counts read back from the OS to whatever is already in each counter. - void reset()
- Resets all enabled counters to zero.
- uint64 cpu_cycles, uint64 instructions, etc.
- Each potentially-measurable event corresponds to a regular old instance variable, which you can read and even modify. All presently-measurable events are measured with counters, not timers; that is, there is no defined relation between the numbers you get from this interface, and wall-clock time.
- PerfMeasurement* JS::ExtractPerfMeasurement(jsval wrapper)
- If you are the C++ side of an XPCOM interface, and you want to benchmark only part of your execution time but make the results available to JavaScript, you can declare a bare
jsval
argument in your .idl file and have JavaScript pass a PerfMeasurement object that it created in that argument slot. Thejsval
you receive points to a JavaScript wrapper object. To extract the C++-level PerfMeasurement object, call this function. It will returnNULL
if JavaScript passed in something with the wrong dynamic type. - JSObject* JS::RegisterPerfMeasurement(JSContext* cx, JSObject* global)
- You shouldn't need to use this function, but we mention it for completeness. It initializes the JavaScript wrapper interface for this API and pokes the constructor function into the global object you provide.