browser/devtools/profiler/cleopatra/js/parser.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rwxr-xr-x

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 Array.prototype.clone = function() { return this.slice(0); }
     9 function makeSample(frames, extraInfo, lines) {
    10   return {
    11     frames: frames,
    12     extraInfo: extraInfo,
    13     lines: lines
    14   };
    15 }
    17 function cloneSample(sample) {
    18   return makeSample(sample.frames.clone(), sample.extraInfo, sample.lines.clone());
    19 }
    21 function bucketsBySplittingArray(array, maxItemsPerBucket) {
    22   var buckets = [];
    23   while (buckets.length * maxItemsPerBucket < array.length) {
    24     buckets.push(array.slice(buckets.length * maxItemsPerBucket,
    25                              (buckets.length + 1) * maxItemsPerBucket));
    26   }
    27   return buckets;
    28 }
    30 var gParserWorker = new Worker("profiler/cleopatra/js/parserWorker.js");
    31 gParserWorker.nextRequestID = 0;
    33 function WorkerRequest(worker) {
    34   var self = this;
    35   this._eventListeners = {};
    36   var requestID = worker.nextRequestID++;
    37   this._requestID = requestID;
    38   this._worker = worker;
    39   this._totalReporter = new ProgressReporter();
    40   this._totalReporter.addListener(function (reporter) {
    41     self._fireEvent("progress", reporter.getProgress(), reporter.getAction());
    42   })
    43   this._sendChunkReporter = this._totalReporter.addSubreporter(500);
    44   this._executeReporter = this._totalReporter.addSubreporter(3000);
    45   this._receiveChunkReporter = this._totalReporter.addSubreporter(100);
    46   this._totalReporter.begin("Processing task in worker...");
    47   var partialResult = null;
    48   function onMessageFromWorker(msg) {
    49     pendingMessages.push(msg);
    50     scheduleMessageProcessing();
    51   }
    52   function processMessage(msg) {
    53     var startTime = Date.now();
    54     var data = msg.data;
    55     var readTime = Date.now() - startTime;
    57     if (data.requestID == requestID || !data.requestID) {
    58       switch(data.type) {
    59         case "error":
    60           self._sendChunkReporter.setAction("Error in worker: " + data.error);
    61           self._executeReporter.setAction("Error in worker: " + data.error);
    62           self._receiveChunkReporter.setAction("Error in worker: " + data.error);
    63           self._totalReporter.setAction("Error in worker: " + data.error);
    64           PROFILERERROR("Error in worker: " + data.error);
    65           self._fireEvent("error", data.error);
    66           break;
    67         case "progress":
    68           self._executeReporter.setProgress(data.progress);
    69           break;
    70         case "finished":
    71           self._executeReporter.finish();
    72           self._receiveChunkReporter.begin("Receiving data from worker...");
    73           self._receiveChunkReporter.finish();
    74           self._fireEvent("finished", data.result);
    75           worker.removeEventListener("message", onMessageFromWorker);
    76           break;
    77         case "finishedStart":
    78           partialResult = null;
    79           self._totalReceiveChunks = data.numChunks;
    80           self._gotReceiveChunks = 0;
    81           self._executeReporter.finish();
    82           self._receiveChunkReporter.begin("Receiving data from worker...");
    83           break;
    84         case "finishedChunk":
    85           partialResult = partialResult ? partialResult.concat(data.chunk) : data.chunk;
    86           var chunkIndex = self._gotReceiveChunks++;
    87           self._receiveChunkReporter.setProgress((chunkIndex + 1) / self._totalReceiveChunks);
    88           break;
    89         case "finishedEnd":
    90           self._receiveChunkReporter.finish();
    91           self._fireEvent("finished", partialResult);
    92           worker.removeEventListener("message", onMessageFromWorker);
    93           break;
    94       }
    95       // dump log if present
    96       if (data.log) {
    97         for (var line in data.log) {
    98           PROFILERLOG(line);
    99         }
   100       }
   101     }
   102   }
   103   var pendingMessages = [];
   104   var messageProcessingTimer = 0;
   105   function processMessages() {
   106     messageProcessingTimer = 0;
   107     processMessage(pendingMessages.shift());
   108     if (pendingMessages.length)
   109       scheduleMessageProcessing();
   110   }
   111   function scheduleMessageProcessing() {
   112     if (messageProcessingTimer)
   113       return;
   114     messageProcessingTimer = setTimeout(processMessages, 10);
   115   }
   116   worker.addEventListener("message", onMessageFromWorker);
   117 }
   119 WorkerRequest.prototype = {
   120   send: function WorkerRequest_send(task, taskData) {
   121     this._sendChunkReporter.begin("Sending data to worker...");
   122     var startTime = Date.now();
   123     this._worker.postMessage({
   124       requestID: this._requestID,
   125       task: task,
   126       taskData: taskData
   127     });
   128     var postTime = Date.now() - startTime;
   129     this._sendChunkReporter.finish();
   130     this._executeReporter.begin("Processing worker request...");
   131   },
   132   sendInChunks: function WorkerRequest_sendInChunks(task, taskData, params, maxChunkSize) {
   133     this._sendChunkReporter.begin("Sending data to worker...");
   134     var self = this;
   135     var chunks = bucketsBySplittingArray(taskData, maxChunkSize);
   136     var pendingMessages = [
   137       {
   138         requestID: this._requestID,
   139         task: "chunkedStart",
   140         numChunks: chunks.length
   141       }
   142     ].concat(chunks.map(function (chunk) {
   143       return {
   144         requestID: self._requestID,
   145         task: "chunkedChunk",
   146         chunk: chunk
   147       };
   148     })).concat([
   149       {
   150         requestID: this._requestID,
   151         task: "chunkedEnd"
   152       },
   153       {
   154         requestID: this._requestID,
   155         params: params,
   156         task: task
   157       },
   158     ]);
   159     var totalMessages = pendingMessages.length;
   160     var numSentMessages = 0;
   161     function postMessage(msg) {
   162       var msgIndex = numSentMessages++;
   163       var startTime = Date.now();
   164       self._worker.postMessage(msg);
   165       var postTime = Date.now() - startTime;
   166       self._sendChunkReporter.setProgress((msgIndex + 1) / totalMessages);
   167     }
   168     var messagePostingTimer = 0;
   169     function postMessages() {
   170       messagePostingTimer = 0;
   171       postMessage(pendingMessages.shift());
   172       if (pendingMessages.length) {
   173         scheduleMessagePosting();
   174       } else {
   175         self._sendChunkReporter.finish();
   176         self._executeReporter.begin("Processing worker request...");
   177       }
   178     }
   179     function scheduleMessagePosting() {
   180       if (messagePostingTimer)
   181         return;
   182       messagePostingTimer = setTimeout(postMessages, 10);
   183     }
   184     scheduleMessagePosting();
   185   },
   187   // TODO: share code with TreeView
   188   addEventListener: function WorkerRequest_addEventListener(eventName, callbackFunction) {
   189     if (!(eventName in this._eventListeners))
   190       this._eventListeners[eventName] = [];
   191     if (this._eventListeners[eventName].indexOf(callbackFunction) != -1)
   192       return;
   193     this._eventListeners[eventName].push(callbackFunction);
   194   },
   195   removeEventListener: function WorkerRequest_removeEventListener(eventName, callbackFunction) {
   196     if (!(eventName in this._eventListeners))
   197       return;
   198     var index = this._eventListeners[eventName].indexOf(callbackFunction);
   199     if (index == -1)
   200       return;
   201     this._eventListeners[eventName].splice(index, 1);
   202   },
   203   _fireEvent: function WorkerRequest__fireEvent(eventName, eventObject, p1) {
   204     if (!(eventName in this._eventListeners))
   205       return;
   206     this._eventListeners[eventName].forEach(function (callbackFunction) {
   207       callbackFunction(eventObject, p1);
   208     });
   209   },
   210 }
   212 var Parser = {
   213   parse: function Parser_parse(data, params) {
   214     var request = new WorkerRequest(gParserWorker);
   215     request.sendInChunks("parseRawProfile", data, params, 3000000);
   216     return request;
   217   },
   219   updateFilters: function Parser_updateFilters(filters) {
   220     var request = new WorkerRequest(gParserWorker);
   221     request.send("updateFilters", {
   222       filters: filters,
   223       profileID: 0
   224     });
   225     return request;
   226   },
   228   updateViewOptions: function Parser_updateViewOptions(options) {
   229     var request = new WorkerRequest(gParserWorker);
   230     request.send("updateViewOptions", {
   231       options: options,
   232       profileID: 0
   233     });
   234     return request;
   235   },
   237   getSerializedProfile: function Parser_getSerializedProfile(complete, callback) {
   238     var request = new WorkerRequest(gParserWorker);
   239     request.send("getSerializedProfile", {
   240       profileID: 0,
   241       complete: complete
   242     });
   243     request.addEventListener("finished", callback);
   244   },
   246   calculateHistogramData: function Parser_calculateHistogramData() {
   247     var request = new WorkerRequest(gParserWorker);
   248     request.send("calculateHistogramData", {
   249       profileID: 0
   250     });
   251     return request;
   252   },
   254   calculateDiagnosticItems: function Parser_calculateDiagnosticItems(meta) {
   255     var request = new WorkerRequest(gParserWorker);
   256     request.send("calculateDiagnosticItems", {
   257       profileID: 0,
   258       meta: meta
   259     });
   260     return request;
   261   },
   263   updateLogSetting: function Parser_updateLogSetting() {
   264     var request = new WorkerRequest(gParserWorker);
   265     request.send("initWorker", {
   266       debugLog: gDebugLog,
   267       debugTrace: gDebugTrace,
   268     });
   269     return request;
   270   },
   271 };

mercurial