]> git.parisson.com Git - pdf.js.git/commitdiff
Start of the benchmark recording framework.
authorBrendan Dahl <brendan.dahl@gmail.com>
Thu, 12 Jan 2012 00:48:51 +0000 (16:48 -0800)
committerBrendan Dahl <brendan.dahl@gmail.com>
Thu, 12 Jan 2012 00:48:51 +0000 (16:48 -0800)
src/core.js
src/util.js
web/viewer.css
web/viewer.js

index 765a239b740b0a9d9eee3a45d316c9a2f6f5bb53..90fcb09d5d5b2a665f5acee25501b5a734b83c60 100644 (file)
@@ -60,13 +60,8 @@ var Page = (function PageClosure() {
   function Page(xref, pageNumber, pageDict, ref) {
     this.pageNumber = pageNumber;
     this.pageDict = pageDict;
-    this.stats = {
-      create: Date.now(),
-      compile: 0.0,
-      fonts: 0.0,
-      images: 0.0,
-      render: 0.0
-    };
+    this.bench = new Bench();
+    this.bench.enabled = !!globalScope.PDFJS.enableBench;
     this.xref = xref;
     this.ref = ref;
 
@@ -187,6 +182,8 @@ var Page = (function PageClosure() {
         return this.IRQueue;
       }
 
+      this.bench.time('Build IR Queue');
+
       var xref = this.xref;
       var content = xref.fetchIfRef(this.content);
       var resources = xref.fetchIfRef(this.resources);
@@ -201,11 +198,14 @@ var Page = (function PageClosure() {
       var pe = this.pe = new PartialEvaluator(
                                 xref, handler, 'p' + this.pageNumber + '_');
       var IRQueue = {};
-      return (this.IRQueue = pe.getIRQueue(content, resources, IRQueue,
-                                           dependency));
+      this.IRQueue = pe.getIRQueue(content, resources, IRQueue, dependency);
+
+      this.bench.timeEnd('Build IR Queue');
+      return this.IRQueue;
     },
 
     ensureFonts: function pageEnsureFonts(fonts, callback) {
+      this.bench.time('Font Loading');
       // Convert the font names to the corresponding font obj.
       for (var i = 0, ii = fonts.length; i < ii; i++) {
         fonts[i] = this.objs.objs[fonts[i]].data;
@@ -215,7 +215,7 @@ var Page = (function PageClosure() {
       var fontObjs = FontLoader.bind(
         fonts,
         function pageEnsureFontsFontObjs(fontObjs) {
-          this.stats.fonts = Date.now();
+          this.bench.timeEnd('Font Loading');
 
           callback.call(this);
         }.bind(this),
@@ -224,6 +224,8 @@ var Page = (function PageClosure() {
     },
 
     display: function pageDisplay(gfx, callback) {
+      var bench = this.bench;
+      bench.time('Rendering');
       var xref = this.xref;
       var resources = xref.fetchIfRef(this.resources);
       var mediaBox = xref.fetchIfRef(this.mediaBox);
@@ -244,8 +246,9 @@ var Page = (function PageClosure() {
       function next() {
         startIdx = gfx.executeIRQueue(IRQueue, startIdx, next);
         if (startIdx == length) {
-          self.stats.render = Date.now();
           gfx.endDrawing();
+          bench.timeEnd('Rendering');
+          bench.timeEnd('Overall');
           if (callback) callback();
         }
       }
@@ -388,15 +391,14 @@ var Page = (function PageClosure() {
       return items;
     },
     startRendering: function pageStartRendering(ctx, callback, textLayer)  {
-      this.startRenderingTime = Date.now();
-
+      var bench = this.bench;
+      bench.time('Overall');
       // If there is no displayReadyPromise yet, then the IRQueue was never
       // requested before. Make the request and create the promise.
       if (!this.displayReadyPromise) {
         this.pdf.startRendering(this);
         this.displayReadyPromise = new Promise();
       }
-
       // Once the IRQueue and fonts are loaded, perform the actual rendering.
       this.displayReadyPromise.then(
         function pageDisplayReadyPromise() {
@@ -677,7 +679,7 @@ var PDFDoc = (function PDFDocClosure() {
         var pageNum = data.pageNum;
         var page = this.pageCache[pageNum];
         var depFonts = data.depFonts;
-
+        page.bench.timeEnd('Page Request');
         page.startRenderingFromIRQueue(data.IRQueue, depFonts);
       }, this);
 
@@ -786,6 +788,7 @@ var PDFDoc = (function PDFDocClosure() {
     startRendering: function pdfDocStartRendering(page) {
       // The worker might not be ready to receive the page request yet.
       this.workerReadyPromise.then(function pdfDocStartRenderingThen() {
+        page.bench.time('Page Request');
         this.messageHandler.send('page_request', page.pageNumber + 1);
       }.bind(this));
     },
index 99b422296bba454b0a472b5065c48aa0f0e1ad7e..80cf937c46886d933626a637c2116ca660b719b4 100644 (file)
@@ -338,3 +338,55 @@ var Promise = (function PromiseClosure() {
   return Promise;
 })();
 
+var Bench = (function BenchClosure() {
+  function rpad(str, pad, length) {
+    while (str.length < length)
+      str += pad;
+    return str;
+  }
+  function Bench() {
+    this.started = {};
+    this.times = [];
+    this.enabled = true;
+  }
+  Bench.prototype = {
+    time: function benchTime(name) {
+      if (!this.enabled)
+        return;
+      if (name in this.started)
+        throw 'Timer is already running for ' + name;
+      this.started[name] = Date.now();
+    },
+    timeEnd: function benchTimeEnd(name) {
+      if (!this.enabled)
+        return;
+      if (!(name in this.started))
+        throw 'Timer has not been started for ' + name;
+      this.times.push({
+        'name': name,
+        'start': this.started[name],
+        'end': Date.now()
+      });
+      // Remove timer from started so it can be called again.
+      delete this.started[name];
+    },
+    toString: function benchToString() {
+      var times = this.times;
+      var out = '';
+      // Find the longest name for padding purposes.
+      var longest = 0;
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var name = times[i]['name'];
+        if (name.length > longest)
+          longest = name.length;
+      }
+      for (var i = 0, ii = times.length; i < ii; ++i) {
+        var span = times[i];
+        var duration = span.end - span.start;
+        out += rpad(span['name'], ' ', longest) + ' ' + duration + 'ms\n';
+      }
+      return out;
+    }
+  }
+  return Bench;
+})();
index e355f7fc246cf3cb8c3a360a475c9cc3708a2060..d5c18504cbfeb391892e55c1e4ac2fe5773844b8 100644 (file)
@@ -67,6 +67,12 @@ body {
 
 span#info {
   display: none;
+  position: fixed;
+  top: 32px;
+  right: 0px;
+  font-size: 10px;
+  white-space: pre;
+  font-family: courier;
 }
 
 @-moz-document regexp("http:.*debug=1.*") {
index ac3fbff0ca190ffddfe5b6f313174e25355db599..fc7d99cdd7318f7ba7ecfe32123d855bf01de6ed 100644 (file)
@@ -222,6 +222,7 @@ var PDFView = {
       return;
     }
 
+    pages[val - 1].updateStats();
     currentPageNumber = val;
     var event = document.createEvent('UIEvents');
     event.initUIEvent('pagechange', false, false, window, 0);
@@ -421,7 +422,7 @@ var PDFView = {
     for (var i = 1; i <= pagesCount; i++) {
       var page = pdf.getPage(i);
       var pageView = new PageView(container, page, i, page.width, page.height,
-                                  page.stats, this.navigateTo.bind(this));
+                                  page.bench, this.navigateTo.bind(this));
       var thumbnailView = new ThumbnailView(sidebar, page, i,
                                             page.width / page.height);
       bindOnAfterDraw(pageView, thumbnailView);
@@ -581,7 +582,7 @@ var PDFView = {
 };
 
 var PageView = function pageView(container, content, id, pageWidth, pageHeight,
-                                 stats, navigateTo) {
+                                 bench, navigateTo) {
   this.id = id;
   this.content = content;
 
@@ -800,11 +801,11 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
     ctx.restore();
     ctx.translate(-this.x * scale, -this.y * scale);
 
-    stats.begin = Date.now();
     this.content.startRendering(ctx,
       (function pageViewDrawCallback(error) {
         if (error)
           PDFView.error('An error occurred while rendering the page.', error);
+        this.stats = content.bench;
         this.updateStats();
         if (this.onAfterDraw)
           this.onAfterDraw();
@@ -819,10 +820,12 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
   };
 
   this.updateStats = function pageViewUpdateStats() {
-    var t1 = stats.compile, t2 = stats.fonts, t3 = stats.render;
-    var str = 'Time to compile/fonts/render: ' +
-              (t1 - stats.begin) + '/' + (t2 - t1) + '/' + (t3 - t2) + ' ms';
-    document.getElementById('info').innerHTML = str;
+    if (!PDFJS.enableBench || !this.stats || PDFView.page != this.id)
+      return;
+    var stats = this.stats;
+    var statsHtml = 'Page ' + this.id + '\n';
+    statsHtml += stats.toString().replace(/\n/g, '<br>');
+    document.getElementById('info').innerHTML = statsHtml;
   };
 };
 
@@ -1016,6 +1019,11 @@ window.addEventListener('load', function webViewerLoad(evt) {
   if ('disableTextLayer' in params)
     PDFJS.disableTextLayer = (params['disableTextLayer'] === 'true');
 
+  if ('enableBench' in params)
+    PDFJS.enableBench = (params['enableBench'] === 'true');
+  if (PDFJS.enableBench)
+    document.getElementById('info').style.display = 'block';
+
   var sidebarScrollView = document.getElementById('sidebarScrollView');
   sidebarScrollView.addEventListener('scroll', updateThumbViewArea, true);
 }, true);