Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(72)

Side by Side Diff: tools/logreader.js

Issue 125256: Implemented processing of compressed log files. (Closed)
Patch Set: Added tests Created 11 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « tools/linux-tick-processor ('k') | tools/tickprocessor.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 /**
29 * @fileoverview Log Reader is used to process log file produced by V8.
30 */
31
32 // Initlialize namespaces
33 var devtools = devtools || {};
34 devtools.profiler = devtools.profiler || {};
35
36
37 /**
38 * Base class for processing log files.
39 *
40 * @param {Array.<Object>} dispatchTable A table used for parsing and processing
41 * log records.
42 * @constructor
43 */
44 devtools.profiler.LogReader = function(dispatchTable) {
45 /**
46 * @type {Array.<Object>}
47 */
48 this.dispatchTable_ = dispatchTable;
49 this.dispatchTable_['alias'] =
50 { parsers: [null, null], processor: this.processAlias_ };
51 this.dispatchTable_['repeat'] =
52 { parsers: [parseInt, 'var-args'], processor: this.processRepeat_,
53 backrefs: true };
54
55 /**
56 * A key-value map for aliases. Translates short name -> full name.
57 * @type {Object}
58 */
59 this.aliases_ = {};
60
61 /**
62 * A key-value map for previous address values.
63 * @type {Object}
64 */
65 this.prevAddresses_ = {};
66
67 /**
68 * A key-value map for events than can be backreference-compressed.
69 * @type {Object}
70 */
71 this.backRefsCommands_ = {};
72 this.initBackRefsCommands_();
73
74 /**
75 * Back references for decompression.
76 * @type {Array.<string>}
77 */
78 this.backRefs_ = [];
79 };
80
81
82 /**
83 * Creates a parser for an address entry.
84 *
85 * @param {string} addressTag Address tag to perform offset decoding.
86 * @return {function(string):number} Address parser.
87 */
88 devtools.profiler.LogReader.prototype.createAddressParser = function(
89 addressTag) {
90 var self = this;
91 return function addressParser (str) {
Søren Thygesen Gjesse 2009/06/18 06:57:44 Maybe add parentheses arround the function returne
Mikhail Naganov 2009/06/18 07:57:07 Parentheses added. I thought that giving a name ad
92 var value = parseInt(str, 16);
93 var firstChar = str.charAt(0);
94 if (firstChar == '+' || firstChar == '-') {
95 var addr = self.prevAddresses_[addressTag];
96 addr += value;
97 self.prevAddresses_[addressTag] = addr;
98 return addr;
99 } else if (firstChar != '0' || str.charAt(1) != 'x') {
100 self.prevAddresses_[addressTag] = value;
101 }
102 return value;
103 };
104 };
105
106
107 /**
108 * Expands an alias symbol, if applicable.
109 *
110 * @param {string} symbol Symbol to expand.
111 * @return {string} Expanded symbol, or the input symbol itself.
112 */
113 devtools.profiler.LogReader.prototype.expandAlias = function(symbol) {
114 return symbol in this.aliases_ ? this.aliases_[symbol] : symbol;
115 };
116
117
118 /**
119 * Used for printing error messages.
120 *
121 * @param {string} str Error message.
122 */
123 devtools.profiler.LogReader.prototype.printError = function(str) {
124 // Do nothing.
125 };
126
127
128 /**
129 * Processes a portion of V8 profiler event log.
130 *
131 * @param {string} chunk A portion of log.
132 */
133 devtools.profiler.LogReader.prototype.processLogChunk = function(chunk) {
134 this.processLog_(chunk.split('\n'));
135 };
136
137
138 /**
139 * Processes stack record.
140 *
141 * @param {number} pc Program counter.
142 * @param {Array.<string>} stack String representation of a stack.
143 * @return {Array.<number>} Processed stack.
144 */
145 devtools.profiler.LogReader.prototype.processStack = function(pc, stack) {
146 var fullStack = [pc];
147 var prevFrame = pc;
148 for (var i = 0, n = stack.length; i < n; ++i) {
149 var frame = stack[i];
150 var firstChar = frame.charAt(0);
151 if (firstChar == '+' || firstChar == '-') {
152 // An offset from the previous frame.
153 prevFrame += parseInt(frame, 16);
154 fullStack.push(prevFrame);
155 // Filter out possible 'overflow' string.
156 } else if (firstChar != 'o') {
157 fullStack.push(parseInt(frame, 16));
158 }
159 }
160 return fullStack;
161 };
162
163
164 /**
165 * Returns whether a particular dispatch must be skipped.
166 *
167 * @param {!Object} dispatch Dispatch record.
168 * @return {boolean} True if dispatch must be skipped.
169 */
170 devtools.profiler.LogReader.prototype.skipDispatch = function(dispatch) {
171 return false;
172 };
173
174
175 /**
176 * Does a dispatch of a log record.
177 *
178 * @param {Array.<string>} fields Log record.
179 * @private
180 */
181 devtools.profiler.LogReader.prototype.dispatchLogRow_ = function(fields) {
182 // Obtain the dispatch.
183 var command = fields[0];
184 if (!(command in this.dispatchTable_)) {
185 throw new Error('unknown command: ' + command);
186 }
187 var dispatch = this.dispatchTable_[command];
188
189 if (dispatch === null || this.skipDispatch(dispatch)) {
190 return;
191 }
192
193 // Parse fields.
194 var parsedFields = [];
195 for (var i = 0; i < dispatch.parsers.length; ++i) {
196 var parser = dispatch.parsers[i];
197 if (parser === null) {
198 parsedFields.push(fields[1 + i]);
199 } else if (typeof parser == 'function') {
200 parsedFields.push(parser(fields[1 + i]));
201 } else {
202 // var-args
203 parsedFields.push(fields.slice(1 + i));
204 break;
205 }
206 }
207
208 // Run the processor.
209 dispatch.processor.apply(this, parsedFields);
210 };
211
212
213 /**
214 * Decompresses a line if it was backreference-compressed.
215 *
216 * @param {string} line Possibly compressed line.
217 * @return {string} Decompressed line.
218 * @private
219 */
220 devtools.profiler.LogReader.prototype.expandBackRef_ = function(line) {
221 var backRefPos;
222 // Filter out case when a regexp is created containing '#'.
223 if (line.charAt(line.length - 1) != '"'
224 && (backRefPos = line.lastIndexOf('#')) != -1) {
225 var backRef = line.substr(backRefPos + 1);
226 var backRefIdx = parseInt(backRef, 10) - 1;
227 var colonPos = backRef.indexOf(':');
228 var backRefStart =
229 colonPos != -1 ? parseInt(backRef.substr(colonPos + 1), 10) : 0;
230 line = line.substr(0, backRefPos) +
231 this.backRefs_[backRefIdx].substr(backRefStart);
232 }
233 this.backRefs_.unshift(line);
234 if (this.backRefs_.length > 10) {
235 this.backRefs_.length = 10;
236 }
237 return line;
238 };
239
240
241 /**
242 * Initializes the map of backward reference compressible commands.
243 * @private
244 */
245 devtools.profiler.LogReader.prototype.initBackRefsCommands_ = function() {
246 for (var event in this.dispatchTable_) {
247 var dispatch = this.dispatchTable_[event];
248 if (dispatch && dispatch.backrefs) {
249 this.backRefsCommands_[event] = true;
250 }
251 }
252 };
253
254
255 /**
256 * Processes alias log record. Adds an alias to a corresponding map.
257 *
258 * @param {string} symbol Short name.
259 * @param {string} expansion Long name.
260 * @private
261 */
262 devtools.profiler.LogReader.prototype.processAlias_ = function(
263 symbol, expansion) {
264 if (expansion in this.dispatchTable_) {
265 this.dispatchTable_[symbol] = this.dispatchTable_[expansion];
266 if (expansion in this.backRefsCommands_) {
267 this.backRefsCommands_[symbol] = true;
268 }
269 } else {
270 this.aliases_[symbol] = expansion;
271 }
272 };
273
274
275 /**
276 * Processes log lines.
277 *
278 * @param {Array.<string>} lines Log lines.
279 * @private
280 */
281 devtools.profiler.LogReader.prototype.processLog_ = function(lines) {
282 var csvParser = new devtools.profiler.CsvParser();
283 try {
284 for (var i = 0, n = lines.length; i < n; ++i) {
285 var line = lines[i];
286 if (!line) {
287 continue;
288 }
289 if (line.charAt(0) == '#' ||
290 line.substr(0, line.indexOf(',')) in this.backRefsCommands_) {
291 line = this.expandBackRef_(line);
292 }
293 var fields = csvParser.parseLine(line);
294 this.dispatchLogRow_(fields);
295 }
296 } catch (e) {
297 this.printError('line ' + (i + 1) + ': ' + (e.message || e));
298 throw e;
299 }
300 };
301
302
303 /**
304 * Processes repeat log record. Expands it according to calls count and
305 * invokes processing.
306 *
307 * @param {number} count Count.
308 * @param {Array.<string>} cmd Parsed command.
309 * @private
310 */
311 devtools.profiler.LogReader.prototype.processRepeat_ = function(count, cmd) {
312 // Replace the repeat-prefixed command from backrefs list with a non-prefixed.
313 this.backRefs_[0] = cmd.join(',');
314 for (var i = 0; i < count; ++i) {
315 this.dispatchLogRow_(cmd);
316 }
317 };
OLDNEW
« no previous file with comments | « tools/linux-tick-processor ('k') | tools/tickprocessor.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698