Javascript Profiling: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
No edit summary
Line 5: Line 5:
As an idea of what should be possible to build on top of this API, see [http://unity3d.com/support/documentation/Manual/Profiler.html Unity's profiler],
As an idea of what should be possible to build on top of this API, see [http://unity3d.com/support/documentation/Manual/Profiler.html Unity's profiler],


== The Profiler ==
== The Profiler object ==


There will be a global <tt>Profiler</tt> object available to instantiate to begin profiling other objects. The <tt>Profiler</tt> object has the following methods:
There will be a global <tt>Profiler</tt> object available to instantiate to begin profiling other objects. The <tt>Profiler</tt> object has the following methods:


* <tt>new Profiler()</tt> - constructor takes no arguments, creates an instance for the invoking context.
<dl>
* <tt>startProfiling : context &rarr; unit</tt> - Starts profiling the specified context. If the context is currently being profiled by another <tt>Profiler</tt> instance (including this one), then an error is thrown.
<dt>new Profiler()
* <tt>isProfiling : context &rarr; bool</tt> - Returns whether the specified context is being profiled or not by this instance.
<dd>The constructor takes no arguments
* <tt>event : object &rarr; unit</tt> - Records a profiling event for the current context. The event is an object which will eventually be returned in a <tt>Profiler.Stack</tt> object queued up in the <tt>events</tt> field. If the current context is not being profiled by this instance, then an error is thrown.
 
* <tt>info : context &rarr; Profiler.Stack list</tt> - Fetches information about a context which is being profiled. Throws an error if the context provided isn't being profiled by this <tt>Profiler</tt> instance.
<dt>startProfiling(context)
* <tt>stopProfiling : context &rarr; Profiler.Stack list</tt> - Ceases profiling the specified context. Returns the same information that <tt>info</tt> returns. Throws an error if the context is not being profiled by this instance.
<dd>Starts profiling the specified context. If the context is currently being profiled this instance, then an error is thrown.
<dt>isProfiling(context)
<dd>Returns whether the specified context is being profiled or not by this instance.
<dt>frame()
<dd>Fetch the current <tt>Profiler.Frame</tt> instance representing the current stack trace of invocation for the invoking context. Properties can be added to this object and will be persisted across invocations of this method so long as each invocation has the same backtrace. If the invoking context is not being profiled by the <tt>Profiler</tt> instance, then an error is thrown
<dt>info(context)
<dd>Returns an array of <tt>Profiler.Frame</tt> instances. Each instance is present for some internal event having been traced at that stack location, or the <tt>frame()</tt> method was called at that location
<dt>clearInfo(context)
<dd>Removes all known frame instances for the given context. Throws an error if the context is not being profiled
<dt>stopProfiling(context)
<dd>Ceases profiling the specified context. Throws an error if the context is not being profiled.
 
</dl>


Possibly have attributes or methods to enable/disable profiling specific attributes? (custom/memory/time/etc.)
Possibly have attributes or methods to enable/disable profiling specific attributes? (custom/memory/time/etc.)


== The <tt>Profiler.Stack</tt> object ==
== The Profiler.Frame object ==
 
A <tt>Profiler.Frame</tt> object represents an event at a particular stack trace. An instance cannot be directly instantiated, but rather it is created through the profiler's <tt>frame()</tt> method.
 
<dl>
<dt>stack
<dd>This attribute is a list of hashes with two keys: <tt>file</tt> and <tt>line</tt>. Each element in the array is the caller of the previous element. All <tt>Profiler.Frame</tt> instances are equivalent based on their stack traces. Some frames may be filtered out based on the permissions of the viewing context.
</dl>


A <tt>Profiler.Stack</tt> object represents an event at a particular stack trace. A stack trace is defined by an ordered list of <tt>&lt;url, line&gt;</tt> pairs where the <tt>url</tt> is the source file of the function and <tt>line</tt> is the line number within the source file. The object would look similarly as follows:
=== Profiled Statistics ===


{                                                     
Some internal events are profiled when profiling is turned on, and they are kept track of in the following fields of the corresponding <tt>Profiler.Frame</tt> instance.
  // Filtered out based on permission of script
  // reading this information
  stack: [                                           
    ['http://example.com/foo.js', 10],               
    ['http://example.com/foo.js', 23],               
    ...                                               
    ['http://example.com/bar.js', 4]                 
  ],
  events: [                                           
    {type: 'runtime', total: 124, pct: 0.1582},       
    {type: 'malloc', times: 4, average: 9, total: 35},
    {type: 'recompile', times: 4},                   
    {type: 'custom-foo', ...},                       
    ...                                              
  ]                                                   
}


The <tt>stack</tt> field is the actual stack trace this represents, and the first element is the function which triggered the events, and the subsequent elements are the callers of the previous element. The <tt>events</tt> field is a list of all events related to this stack trace. Events are added internally, but custom events can also be added via <tt>event</tt>.
<dl>
<dt>runtime
<dd>This is an integer value of the amount of milliseconds that the corresponding stack trace was seen running for
<dt>allocs
<dd>This is a two-element hash. The <tt>total</tt> key represents the total amount of allocations that occurred at this trace, and the <tt>amt</tt> key is the number of times that allocation was triggered at this location
</dl>


Possibly events would also be filtered out? This is more relevant to instrumented C++ functions, I would imagine that all JS events would be public to all <tt>Profiler</tt>s
Other statistics can be easily added from either JS or C++.


== Use Cases ==
== Use Cases ==
Line 50: Line 58:
=== Test Cases ===
=== Test Cases ===


The test suite would initially create a <tt>Profiler</tt> object and then start/stop profiling the current page on each call to <tt>startProfiling</tt>/<tt>stopProfiling</tt> and the information returned from <tt>stopProfiling</tt> would be what is displayed.
The test suite would initially create a <tt>Profiler</tt> object and then start/stop profiling the current page on each call to <tt>startProfiling</tt>/<tt>stopProfiling</tt> and the information returned from <tt>info</tt> would be what is displayed. Between each test, the <tt>clearInfo</tt> method would be used to prevent pollution between runs.


=== Extension ===
=== Extension ===


Opened on a page and creates its own <tt>Profiler</tt> object. It then profiles the current page via <tt>startProfiling</tt> (probably a button to be hit). Some time later <tt>stopProfiling</tt> is used to get information about the run of profiling (again probably a button being hit) and then all of the information is sorted through and displayed in some fancy fashion.
Opened on a page and creates its own <tt>Profiler</tt> object. It then profiles the current page via <tt>startProfiling</tt> (probably a button to be hit). Some time later <tt>info</tt> is used to get information about the run of profiling (again probably a button being hit) and then all of the information is sorted through and displayed in some fancy fashion.


The page being profiled is unaware that it's being profiled, and there's nothing that it needs to do to help it along. If it so desires, it could conditionally call <tt>profilee.event()</tt> to learn some interesting information.
The page being profiled is unaware that it's being profiled, and there's nothing that it needs to do to help it along.


= Implementation =
= Implementation =
Line 114: Line 122:


There will be a way to instrument events from C++ as well to track things like GC triggers, GC allocations, type inference failures, etc.
There will be a way to instrument events from C++ as well to track things like GC triggers, GC allocations, type inference failures, etc.
= Extensions =
* Create a generic <tt>Profiler.Statistics</tt> which is an aggregator for stats, kinda like http://sourceware.org/systemtap/langref/Statistics_aggregates.html where you call <tt>stats.insert(4)</tt> and it would automatically track min, max, average, count, etc.
* Throw away all data more than N seconds old because it's probably not interesting and wasting memory now
22

edits

Navigation menu