Javascript Profiling: Difference between revisions

Jump to navigation Jump to search
no edit summary
No edit summary
No edit summary
Line 15: Line 15:
<dd>The constructor takes no arguments
<dd>The constructor takes no arguments


<dt>startProfiling()
<dt>startProfiling(obj, [sample_rate, [max_samples]])
<dd>Ensures that profiling has started. If some other Profiler has started profiling, this is a no-op. If startProfiling() is invoked, an eventual stopProfiling() must be paired to cease profiling data collection.
<dd>Ensures that profiling has started on the specified object's runtime. The sample rate and max samples are optional parameters which can tune how the profile is collected.
<dt>isProfiling()
 
<dd>Returns whether profiling is turned on by any Profiler objects
The sample rate is the time between samples of the call stack specified in microseconds (defaults to 1000 = 1ms). The sample rate is mostly a guideline as the platform being run might not guarantee the granularity of timing. Samples will not happen more frequently than the specified rate, but may occur more infrequently.
 
A maximum number of samples can be specified as well, but the default is unlimited (0). If the maximum number of samples is reached, then the sample storage is treated as a ring buffer, discarding the oldest samples.
 
If some other Profiler object is profiling the specified runtime, then an error is thrown if the sample rate or maximum sample count is different. Eventually a call to stopProfiling() must be paired with this call to cease data collection.
<dt>isProfiling(obj)
<dd>Returns whether profiling is turned on for the specified runtime
<dt>frame()
<dt>frame()
<dd>Fetch the current object instance representing the current stack trace of invocation for the invoking context's global. 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's global is not being profiled by the <tt>Profiler</tt> instance, then an error is thrown
<dd>Fetch the current object instance representing the current stack trace of invocation for the invoking context's global. 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's global is not being profiled by the <tt>Profiler</tt> instance, then an error is thrown
<dt>info()
<dt>info(obj)
<dd>Returns all profile information for the past XXX seconds. Data is stored in a circular fashion, so only the most recent data will be available.
<dd>Returns all profile information for the specified object's runtime. The data returned is all that is collected between the last invocation of clearInfo() and all the profile data.
<dt>clearInfo()
<dt>clearInfo(obj)
<dd>Removes all information stored in profiling.
<dd>Removes all custom frame() information stored for the specified object's runtime. Also clears all profiling samples collected so far.
<dt>stopProfiling()
<dt>stopProfiling(obj)
<dd>Ceases profiling. This must only be called if a pairing call to startProfiling() has been made.
<dd>Ceases profiling on the specified runtime. This must only be called if a pairing call to startProfiling(obj) has been made.


</dl>
</dl>
Line 34: Line 40:
The return value is an object which is a hash containing all the information. The hash can loosely be viewed as a trie. Here's some example code:
The return value is an object which is a hash containing all the information. The hash can loosely be viewed as a trie. Here's some example code:
   
   
  profiler = new Profiler();
  // input.js
  profiler.startProfiling(this);
var p = new Profiler();              
function b() { profiler.frame().b = true; }
  function foo(n) {                     
  function a() { b(); profiler.frame().a = 4; }
    var sum = 0;                      
  a();
    for (var i = 0; i < n; i++) {    
  profiler.info() // => { 'input.js:3 (a)': {a: 4, 'input.js:2 (b)': {b: true}}}
        sum += i;                     
    }                                 
    var fac = 1;                     
    for (var i = 1; i < 2 * n; i++)
        fac *= i;                    
    }                                
    return sum + fac;                 
}                                     
                                       
  function bar(n) {                    
    p.frame().one = 1;                
    var info = p.frame();             
    info.two = 2;                     
    info.= n;                    
}                                    
                                       
p.startProfiling(p);                 
foo(4000000);                         
bar(200);                             
  p.stopProfiling(p);                  
                                       
  print(JSON.stringify(p.info(p)))     
 
And the following hash would be printed:
 
{                                                                 
  ticks: 624,                                                     
  children: [                                                     
    {                                                             
      function: { file: 'input.js', line: 1 },                     
      site: { file: 'input.js', line: 25 },                       
      ticks: 624,                                                 
      children: [                                                 
        {                                                         
          function: { file: 'input.js', line: 1, name: 'foo' },   
          site: { file: 'input.js', line: 7 },                     
          ticks: 195,                                             
          self: 195                                               
        }, {                                                       
          function: { file: 'input.js', line: 1, name: 'foo' },   
          site: { file: 'input.js', line: 11 },                   
          ticks: 429,                                             
          self: 429                                               
        }                                                         
      ]                                                           
    }, {                                                           
      function: { file: 'input.js', line: 1},                     
      site: { file: 'input.js', line: 26},                         
      children: [                                                 
        {                                                         
          function: { file: 'input.js', line: 18, name: 'bar' },   
          site: { file: 'input.js', line: 18 },                   
          data: { one: 1 }                                         
        }, {                                                       
          function: { file: 'input.js', line: 18, name: 'bar' },   
          site: { file: 'input.js', line: 19 },                   
          data: { two: 2, n: 200 }                                 
        }                                                          
      ]                                                           
    }                                                              
  ]                                                               
}                                                                  


With this structure, each "stack trace" has its own object which is persisted across invocations. Each object also has information about whatever children were invoked from it.
With this structure, each "stack trace" has its own object which is persisted across invocations. Each object also has information about whatever children were invoked from it.
Line 48: Line 115:


<dl>
<dl>
<dt>runtime
<dt>ticks
<dd>This is an integer value of the amount of milliseconds that the corresponding stack trace was seen running for
<dd>This is an integer value of the number of ticks while this function's frame was on the stack. This is useful when counting total time spent in a function. It should be true that: <tt>ticks = self + children.sum('ticks')</tt>
<dt>allocs
<dt>self
<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
<dd>This is an integer value like "ticks," but instead only counts the time spent in the function itself. When a sample is taken and a function is currently running (it's the top of the stack), it's self count is increased.
<dt>gc
<dd>This integer represents the number of times that garbage collection was invoked at the site
<dt>compile
<dd>This integer represents the number of times a function was compiled when invoked from this site.
</dl>
</dl>


22

edits

Navigation menu