<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array"/>
  <modified type="array">
    <modified>
      <diff></diff>
      <filename>src/native_service/BrowserProfiler/libBrowserProfiler.so</filename>
    </modified>
    <modified>
      <diff>@@ -826,6 +826,22 @@ bp::List::operator= (const List &amp; other)
     return *this;
 }
 
+void bp::List::clear()
+{
+    for (unsigned int i = 0; i &lt; values.size(); i++)
+    {
+        delete values[i];
+    }
+    values.clear();
+    
+    if (e.value.listVal.elements != NULL) 
+    {
+        free(e.value.listVal.elements);
+    }
+    e.value.listVal.size = 0;
+    e.value.listVal.elements = NULL;
+}
+
 bp::List::~List()
 {
     for (unsigned int i = 0; i &lt; values.size(); i++)</diff>
      <filename>src/native_service/bptypeutil.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -227,6 +227,9 @@ namespace bp {
         operator std::vector&lt;const Object *&gt;() const; // throw(ConversionException);
         
         virtual const Object &amp; operator[](unsigned int index) const; // throw();
+
+        // empty out a list
+        void clear();
     private:
         std::vector&lt;Object *&gt; values;
     };</diff>
      <filename>src/native_service/bptypeutil.h</filename>
    </modified>
    <modified>
      <diff>@@ -65,11 +65,15 @@ sampleThread(void * arg)
 {
     ServiceContext * myCtx = (ServiceContext *) arg;
     
+    std::cout &lt;&lt; &quot;sampling thread running&quot; &lt;&lt; std::endl;
+
     while (myCtx-&gt;samples.size() &lt; MAX_SAMPLES &amp;&amp; myCtx-&gt;running)
     {
         float cpu;
         long long mem;
-
+        bp::time::Stopwatch sampleTime;
+        sampleTime.start();
+        
         if (get_sample(myCtx-&gt;pid, mem, cpu)) {
             bp::Map * m = new bp::Map;
             m-&gt;add(&quot;cpu&quot;, new bp::Double(cpu));
@@ -84,13 +88,20 @@ sampleThread(void * arg)
             }
         }
 
-        // now pause SAMPLE_INTERVAL_MS
-        usleep(1000 * SAMPLE_INTERVAL_MS);
+        // taking a sample takes time.  sleep less.
+        int msToSleep = SAMPLE_INTERVAL_MS;
+        int sampleTookMS = (int) (sampleTime.elapsedSec() * 1000);        
+        if (msToSleep &gt; sampleTookMS) msToSleep -= sampleTookMS;
+
+        // now pause
+        usleep(1000 * msToSleep);
     }
 
     g_bpCoreFunctions-&gt;postResults(myCtx-&gt;tid, myCtx-&gt;samples.elemPtr());    
+    std::cout &lt;&lt; &quot;sampling thread returning&quot; &lt;&lt; std::endl;
+
+    myCtx-&gt;samples.clear();
 
-    // XXX: clear samples list
     return NULL;
 }
 
@@ -123,7 +134,7 @@ myAllocate(void ** instance, unsigned int, const BPElement * ctx)
 static void
 myDestroy(void * instance)
 {
-    ServiceContext * myCtx = new ServiceContext;
+    ServiceContext * myCtx = (ServiceContext *) instance;
 
     if (myCtx-&gt;running) {
         void * ignore;
@@ -145,6 +156,9 @@ myInvoke(void * instance, const char * funcName,
 {
     ServiceContext * myCtx = (ServiceContext *) instance;
 
+    std::cout &lt;&lt; funcName &lt;&lt; &quot; called!&quot;&lt;&lt; std::endl;
+        
+
     if (!strcmp(funcName, &quot;start&quot;))
     {
         if (myCtx-&gt;running) {
@@ -159,8 +173,17 @@ myInvoke(void * instance, const char * funcName,
         myCtx-&gt;sw.reset();
         myCtx-&gt;sw.start();
 
-        // extract callback if present
+        // use bptypeutil to simplify argument extraction
         bp::Object * o = bp::Object::build(elem);
+
+        // invoke &quot;started callback&quot; if present
+        if (o-&gt;has(&quot;startedCallback&quot;, BPTCallBack))
+        {
+            long long scb = ((bp::CallBack *) o-&gt;get(&quot;startedCallback&quot;))-&gt;value();
+            g_bpCoreFunctions-&gt;invoke(tid, scb, bp::Null().elemPtr());
+        }
+
+        // extract callback if present
         if (o-&gt;has(&quot;callback&quot;, BPTCallBack))
         {
             myCtx-&gt;cb = (int) ((bp::CallBack *) o-&gt;get(&quot;callback&quot;))-&gt;value();
@@ -218,6 +241,15 @@ myInvoke(void * instance, const char * funcName,
 
 static BPArgumentDefinition s_startArgs[] = {
     {
+        &quot;startedCallback&quot;,
+        &quot;A callback which will be invoked immediately (when provided) at &quot;
+        &quot;the point when sampling begins.  The intention of this callback is &quot;
+        &quot;to allow javascript based code and sampling to attain a correlated &quot;
+        &quot;zero point for the correlation of resource usage and execution state.&quot;,
+        BPTCallBack,
+        BP_FALSE
+    },
+    {
         &quot;callback&quot;,
         &quot;If provided callback will be invoked for each sample rather than &quot;
         &quot;returning all data in an array at the end of sampling&quot;,
@@ -229,7 +261,7 @@ static BPArgumentDefinition s_startArgs[] = {
 static BPFunctionDefinition s_myServiceFunctions[] = {
     {
         &quot;start&quot;,
-        &quot;start taking samples.  (XXX)&quot;,
+        &quot;Begin taking samples.  (XXX)&quot;,
         sizeof(s_startArgs)/sizeof(s_startArgs[0]),
         s_startArgs
     },
@@ -250,7 +282,7 @@ static BPFunctionDefinition s_myServiceFunctions[] = {
 
 static BPCoreletDefinition s_myServiceDef = {
     &quot;BrowserProfiler&quot;,
-    0, 1, 0,
+    0, 1, 1,
     &quot;A service that analyzes the memory and cpu usage of a web browser.  &quot;
     &quot;The service can take 1 sample or multiple samples at a specified interval.  &quot;
     &quot;When sampling at intervals, at most 1,000 samples are taken.  If you provide &quot;</diff>
      <filename>src/native_service/service.cpp</filename>
    </modified>
    <modified>
      <diff>@@ -28,31 +28,31 @@
 
 &lt;script&gt;
 
-    var cpuData = [];
+    var startTime = null;
 
     var stopProfile = function() {
         BrowserPlus.BrowserProfiler.stop({}, function(x) {});
-        var report = YAHOO.tool.Profiler.getFullReport(function(data){
-            return data.calls &gt; 0;
-        });
-        buildReport(cpuData, report);
-        //console.log(cpuData);
-        //console.log(report);
     };
     var startProfile = function() {
+        var beforeCall = (new Date()).getTime();
         BrowserPlus.BrowserProfiler.start({
-            interval: 0.1,
-            callback: function(data) {
-                //console.log(arguments);
-                var o = {
-                    stamp: Math.round(parseFloat(data.stamp) /10),
-                    cpu: data.browsers[1].cpu,
-                    mem: data.browsers[1].mem
-                };
-                cpuData.push(o);
-                //console.log(Math.round(parseFloat(data.stamp) /10), Math.round((new Date()).getTime() / 10));
+            startedCallback: function(data) {
+				var afterCall = (new Date()).getTime();
+				startTime = (afterCall + beforeCall) / 2;
+				console.log(&quot;startedCallback delay: &quot; + 
+							(afterCall - beforeCall) + &quot;ms&quot;);
             }
-        }, function(x) {});
+        }, function(cpuData) {
+			var report = YAHOO.tool.Profiler.getFullReport(function(data){
+				return data.calls &gt; 0;
+			});
+			buildReport(cpuData.value, report);
+			console.log(cpuData.value);
+			console.log(report);
+
+            YAHOO.tool.Profiler.unregisterObject(&quot;YAHOO.util.DD&quot;);
+            YAHOO.tool.Profiler.unregisterObject(&quot;YAHOO.util.Dom&quot;);
+		});
 
         YAHOO.tool.Profiler.registerObject(&quot;YAHOO.util.DD&quot;);
         YAHOO.tool.Profiler.registerObject(&quot;YAHOO.util.Dom&quot;);
@@ -66,7 +66,7 @@
                 {
                     service: &quot;BrowserProfiler&quot;,
                     version: &quot;0&quot;,
-                    minversion: &quot;0.0.6&quot;
+                    minversion: &quot;0.1.1&quot;
                 }
             ]}, function(r) {
             if (!r.success) {
@@ -83,41 +83,36 @@
     var buildReport = function(cpuData, report) {
         //console.log(arguments);
         //This is really hacky, but oh well it's a hack ;)
-        var data = {};
+		// (lth) and I doubled the hackery
         for (var i in report) {
             //console.log(i);
             var stamps = report[i].stamps;
             for (var s = 0; s &lt; stamps.length; s++) {
-                var start = Math.round(stamps[s].start / 10);
-                if (!data[start]) {
-                    data[start] = {};
-                    data[start].methods = [];
-                }
-                data[start].methods.push(i);
-            }
-        }
-        for (var i in cpuData) {
-            var stamp = cpuData[i].stamp;
-            //Cover a +- 100 millisecond gap in data..
-            var s_stamp = stamp - 10;
-            var e_stamp = stamp + 10;
-            for (var s_stamp; s_stamp &lt;= e_stamp; s_stamp++) {
-                //console.log(s_stamp);
-                if (data[s_stamp] &amp;&amp; !data[s_stamp].cpu) {
-                    data[s_stamp].cpu = cpuData[i].cpu;
-                    data[s_stamp].mem = cpuData[i].mem;
-                }
-            }
+				
+                var start = (stamps[s].start - startTime) / 1000.0;
+				// find which bucket to drop this in, yeah, x^3
+				for (var j in cpuData) {
+					if ((cpuData[j].offset + .1) &gt; start) {
+						if (!cpuData[j].methods) cpuData[j].methods = [];
+						cpuData[j].methods.push(i);
+						break;
+					}
+				}
+			}
         }
         //console.log(report);
         //console.log(data);
         var r = document.getElementById('results');
         r.innerHTML = '';
         var str = '&lt;table border=&quot;1&quot; width=&quot;50%&quot; cellpadding=&quot;2&quot; cellspacing=&quot;2&quot;&gt;';
-        str += '&lt;tr&gt;&lt;th&gt;Method calls&lt;/th&gt;&lt;th&gt;CPU&lt;/th&gt;&lt;th&gt;Memory&lt;/th&gt;&lt;/tr&gt;';
+        str += '&lt;tr&gt;&lt;th&gt;offset&lt;/th&gt;&lt;th&gt;cpu&lt;/th&gt;&lt;th&gt;memory&lt;/th&gt;&lt;th&gt;# of calls&lt;/th&gt;&lt;/tr&gt;';
 
-        for (var i in data) {
-            str += '&lt;tr&gt;&lt;td&gt;' + data[i].methods.length + '&lt;/td&gt;&lt;td&gt;' + data[i].cpu + '&lt;/td&gt;&lt;td&gt;' + data[i].mem + '&lt;/td&gt;&lt;/tr&gt;';
+        for (var i in cpuData) {
+			console.log(i);
+			console.log(cpuData[i]);
+            str += '&lt;tr&gt;&lt;td&gt;' + cpuData[i].offset +'&lt;/td&gt;&lt;td&gt;'
+				+ cpuData[i].cpu + '&lt;/td&gt;&lt;td&gt;' + cpuData[i].mem + '&lt;/td&gt;&lt;td&gt;'
+				+ (cpuData[i].methods ? cpuData[i].methods.length : 0) + '&lt;/td&gt;&lt;/tr&gt;';
         }
 
         str += '&lt;/table&gt;';</diff>
      <filename>tests/profiler.htm</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>src/native_service/BrowserProfiler/libBrowserProfiler.so.dSYM/Contents/Info.plist</filename>
    </removed>
    <removed>
      <filename>src/native_service/BrowserProfiler/libBrowserProfiler.so.dSYM/Contents/Resources/DWARF/libBrowserProfiler.so</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>000cdf3e10ef7ce2465356471d597d5723cf67a5</id>
    </parent>
  </parents>
  <author>
    <name>Lloyd Hilaiel</name>
    <email>lloydh@fancyfront-hilaiel-com.local</email>
  </author>
  <url>http://github.com/davglass/bp-profiler/commit/bd4e2e3b5f4625084bba72faf9e2e1bd5f28a4df</url>
  <id>bd4e2e3b5f4625084bba72faf9e2e1bd5f28a4df</id>
  <committed-date>2008-12-22T10:14:07-08:00</committed-date>
  <authored-date>2008-12-22T10:14:07-08:00</authored-date>
  <message>hack on profiler a bit.  don't use callback method to reduce profiling
overhead during execution, play with correlation of sampling data and
javascript call data.</message>
  <tree>dc224ad342324bccf55262f62f532315d7343cb1</tree>
  <committer>
    <name>Lloyd Hilaiel</name>
    <email>lloydh@fancyfront-hilaiel-com.local</email>
  </committer>
</commit>
