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