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

Side by Side Diff: tools/tickprocessor.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
OLDNEW
1 // Copyright 2009 the V8 project authors. All rights reserved. 1 // Copyright 2009 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
45 function readFile(fileName) { 45 function readFile(fileName) {
46 try { 46 try {
47 return read(fileName); 47 return read(fileName);
48 } catch (e) { 48 } catch (e) {
49 print(fileName + ': ' + (e.message || e)); 49 print(fileName + ': ' + (e.message || e));
50 throw e; 50 throw e;
51 } 51 }
52 } 52 }
53 53
54 54
55 function inherits(childCtor, parentCtor) {
56 function tempCtor() {};
57 tempCtor.prototype = parentCtor.prototype;
58 childCtor.prototype = new tempCtor();
59 };
60
61
55 function TickProcessor( 62 function TickProcessor(
56 cppEntriesProvider, separateIc, ignoreUnknown, stateFilter) { 63 cppEntriesProvider, separateIc, ignoreUnknown, stateFilter) {
64 devtools.profiler.LogReader.call(this, {
65 'shared-library': { parsers: [null, parseInt, parseInt],
66 processor: this.processSharedLibrary },
67 'code-creation': {
68 parsers: [null, this.createAddressParser('code'), parseInt, null],
69 processor: this.processCodeCreation, backrefs: true },
70 'code-move': { parsers: [this.createAddressParser('code'),
71 this.createAddressParser('code-move-to')],
72 processor: this.processCodeMove, backrefs: true },
73 'code-delete': { parsers: [this.createAddressParser('code')],
74 processor: this.processCodeDelete, backrefs: true },
75 'tick': { parsers: [this.createAddressParser('code'),
76 this.createAddressParser('stack'), parseInt, 'var-args'],
77 processor: this.processTick, backrefs: true },
78 'profiler': null,
79 // Obsolete row types.
80 'code-allocate': null,
81 'begin-code-region': null,
82 'end-code-region': null });
83
57 this.cppEntriesProvider_ = cppEntriesProvider; 84 this.cppEntriesProvider_ = cppEntriesProvider;
58 this.ignoreUnknown_ = ignoreUnknown; 85 this.ignoreUnknown_ = ignoreUnknown;
59 this.stateFilter_ = stateFilter; 86 this.stateFilter_ = stateFilter;
60 var ticks = this.ticks_ = 87 var ticks = this.ticks_ =
61 { total: 0, unaccounted: 0, excluded: 0, gc: 0 }; 88 { total: 0, unaccounted: 0, excluded: 0, gc: 0 };
62 89
63 Profile.prototype.handleUnknownCode = function( 90 Profile.prototype.handleUnknownCode = function(
64 operation, addr, opt_stackPos) { 91 operation, addr, opt_stackPos) {
65 var op = devtools.profiler.Profile.Operation; 92 var op = devtools.profiler.Profile.Operation;
66 switch (operation) { 93 switch (operation) {
(...skipping 12 matching lines...) Expand all
79 } 106 }
80 break; 107 break;
81 } 108 }
82 }; 109 };
83 110
84 this.profile_ = new Profile(separateIc); 111 this.profile_ = new Profile(separateIc);
85 this.codeTypes_ = {}; 112 this.codeTypes_ = {};
86 // Count each tick as a time unit. 113 // Count each tick as a time unit.
87 this.viewBuilder_ = new devtools.profiler.ViewBuilder(1); 114 this.viewBuilder_ = new devtools.profiler.ViewBuilder(1);
88 this.lastLogFileName_ = null; 115 this.lastLogFileName_ = null;
89 this.aliases_ = {};
90 }; 116 };
117 inherits(TickProcessor, devtools.profiler.LogReader);
91 118
92 119
93 TickProcessor.VmStates = { 120 TickProcessor.VmStates = {
94 JS: 0, 121 JS: 0,
95 GC: 1, 122 GC: 1,
96 COMPILER: 2, 123 COMPILER: 2,
97 OTHER: 3, 124 OTHER: 3,
98 EXTERNAL: 4 125 EXTERNAL: 4
99 }; 126 };
100 127
101 128
102 TickProcessor.CodeTypes = { 129 TickProcessor.CodeTypes = {
103 CPP: 0, 130 CPP: 0,
104 SHARED_LIB: 1 131 SHARED_LIB: 1
105 }; 132 };
106 // Otherwise, this is JS-related code. We are not adding it to 133 // Otherwise, this is JS-related code. We are not adding it to
107 // codeTypes_ map because there can be zillions of them. 134 // codeTypes_ map because there can be zillions of them.
108 135
109 136
110 TickProcessor.RecordsDispatch = { 137 TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0;
111 'shared-library': { parsers: [null, parseInt, parseInt], 138
112 processor: 'processSharedLibrary' }, 139
113 'code-creation': { parsers: [null, parseInt, parseInt, null], 140 /**
114 processor: 'processCodeCreation' }, 141 * @override
115 'code-move': { parsers: [parseInt, parseInt], 142 */
116 processor: 'processCodeMove' }, 143 TickProcessor.prototype.printError = function(str) {
117 'code-delete': { parsers: [parseInt], processor: 'processCodeDelete' }, 144 print(str);
118 'tick': { parsers: [parseInt, parseInt, parseInt, 'var-args'],
119 processor: 'processTick' },
120 'alias': { parsers: [null, null], processor: 'processAlias' },
121 'profiler': null,
122 // Obsolete row types.
123 'code-allocate': null,
124 'begin-code-region': null,
125 'end-code-region': null
126 }; 145 };
127 146
128 TickProcessor.CALL_PROFILE_CUTOFF_PCT = 2.0;
129
130 147
131 TickProcessor.prototype.setCodeType = function(name, type) { 148 TickProcessor.prototype.setCodeType = function(name, type) {
132 this.codeTypes_[name] = TickProcessor.CodeTypes[type]; 149 this.codeTypes_[name] = TickProcessor.CodeTypes[type];
133 }; 150 };
134 151
135 152
136 TickProcessor.prototype.isSharedLibrary = function(name) { 153 TickProcessor.prototype.isSharedLibrary = function(name) {
137 return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB; 154 return this.codeTypes_[name] == TickProcessor.CodeTypes.SHARED_LIB;
138 }; 155 };
139 156
140 157
141 TickProcessor.prototype.isCppCode = function(name) { 158 TickProcessor.prototype.isCppCode = function(name) {
142 return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP; 159 return this.codeTypes_[name] == TickProcessor.CodeTypes.CPP;
143 }; 160 };
144 161
145 162
146 TickProcessor.prototype.isJsCode = function(name) { 163 TickProcessor.prototype.isJsCode = function(name) {
147 return !(name in this.codeTypes_); 164 return !(name in this.codeTypes_);
148 }; 165 };
149 166
150 167
151 TickProcessor.prototype.processLogFile = function(fileName) { 168 TickProcessor.prototype.processLogFile = function(fileName) {
152 this.lastLogFileName_ = fileName; 169 this.lastLogFileName_ = fileName;
153 var contents = readFile(fileName); 170 var contents = readFile(fileName);
154 this.processLog(contents.split('\n')); 171 this.processLogChunk(contents);
155 }; 172 };
156 173
157 174
158 TickProcessor.prototype.processLog = function(lines) {
159 var csvParser = new devtools.profiler.CsvParser();
160 for (var i = 0, n = lines.length; i < n; ++i) {
161 var line = lines[i];
162 if (!line) {
163 continue;
164 }
165 var fields = csvParser.parseLine(line);
166 this.dispatchLogRow(fields);
167 }
168 };
169
170
171 TickProcessor.prototype.dispatchLogRow = function(fields) {
172 // Obtain the dispatch.
173 var command = fields[0];
174 if (!(command in TickProcessor.RecordsDispatch)) {
175 throw new Error('unknown command: ' + command);
176 }
177 var dispatch = TickProcessor.RecordsDispatch[command];
178
179 if (dispatch === null) {
180 return;
181 }
182
183 // Parse fields.
184 var parsedFields = [];
185 for (var i = 0; i < dispatch.parsers.length; ++i) {
186 var parser = dispatch.parsers[i];
187 if (parser === null) {
188 parsedFields.push(fields[1 + i]);
189 } else if (typeof parser == 'function') {
190 parsedFields.push(parser(fields[1 + i]));
191 } else {
192 // var-args
193 parsedFields.push(fields.slice(1 + i));
194 break;
195 }
196 }
197
198 // Run the processor.
199 this[dispatch.processor].apply(this, parsedFields);
200 };
201
202
203 TickProcessor.prototype.processSharedLibrary = function( 175 TickProcessor.prototype.processSharedLibrary = function(
204 name, startAddr, endAddr) { 176 name, startAddr, endAddr) {
205 var entry = this.profile_.addStaticCode(name, startAddr, endAddr); 177 var entry = this.profile_.addStaticCode(name, startAddr, endAddr);
206 this.setCodeType(entry.getName(), 'SHARED_LIB'); 178 this.setCodeType(entry.getName(), 'SHARED_LIB');
207 179
208 var self = this; 180 var self = this;
209 var libFuncs = this.cppEntriesProvider_.parseVmSymbols( 181 var libFuncs = this.cppEntriesProvider_.parseVmSymbols(
210 name, startAddr, endAddr, function(fName, fStart, fEnd) { 182 name, startAddr, endAddr, function(fName, fStart, fEnd) {
211 self.profile_.addStaticCode(fName, fStart, fEnd); 183 self.profile_.addStaticCode(fName, fStart, fEnd);
212 self.setCodeType(fName, 'CPP'); 184 self.setCodeType(fName, 'CPP');
213 }); 185 });
214 }; 186 };
215 187
216 188
217 TickProcessor.prototype.processAlias = function(symbol, expansion) {
218 if (expansion in TickProcessor.RecordsDispatch) {
219 TickProcessor.RecordsDispatch[symbol] =
220 TickProcessor.RecordsDispatch[expansion];
221 } else {
222 this.aliases_[symbol] = expansion;
223 }
224 };
225
226
227 TickProcessor.prototype.processCodeCreation = function( 189 TickProcessor.prototype.processCodeCreation = function(
228 type, start, size, name) { 190 type, start, size, name) {
229 if (type in this.aliases_) { 191 var entry = this.profile_.addCode(
230 type = this.aliases_[type]; 192 this.expandAlias(type), name, start, size);
231 }
232 var entry = this.profile_.addCode(type, name, start, size);
233 }; 193 };
234 194
235 195
236 TickProcessor.prototype.processCodeMove = function(from, to) { 196 TickProcessor.prototype.processCodeMove = function(from, to) {
237 this.profile_.moveCode(from, to); 197 this.profile_.moveCode(from, to);
238 }; 198 };
239 199
240 200
241 TickProcessor.prototype.processCodeDelete = function(start) { 201 TickProcessor.prototype.processCodeDelete = function(start) {
242 this.profile_.deleteCode(start); 202 this.profile_.deleteCode(start);
243 }; 203 };
244 204
245 205
246 TickProcessor.prototype.includeTick = function(vmState) { 206 TickProcessor.prototype.includeTick = function(vmState) {
247 return this.stateFilter_ == null || this.stateFilter_ == vmState; 207 return this.stateFilter_ == null || this.stateFilter_ == vmState;
248 }; 208 };
249 209
250 210
251 TickProcessor.prototype.processTick = function(pc, sp, vmState, stack) { 211 TickProcessor.prototype.processTick = function(pc, sp, vmState, stack) {
252 this.ticks_.total++; 212 this.ticks_.total++;
253 if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++; 213 if (vmState == TickProcessor.VmStates.GC) this.ticks_.gc++;
254 if (!this.includeTick(vmState)) { 214 if (!this.includeTick(vmState)) {
255 this.ticks_.excluded++; 215 this.ticks_.excluded++;
256 return; 216 return;
257 } 217 }
258 218
259 var fullStack = [pc]; 219 this.profile_.recordTick(this.processStack(pc, stack));
260 var prevFrame = pc;
261 for (var i = 0, n = stack.length; i < n; ++i) {
262 var frame = stack[i];
263 var firstChar = frame.charAt(0);
264 // Leave only numbers starting with 0x. Filter possible 'overflow' string.
265 if (firstChar == '0') {
266 fullStack.push(parseInt(frame, 16));
267 } else if (firstChar == '+' || firstChar == '-') {
268 // An offset from the previous frame.
269 prevFrame += parseInt(frame, 16);
270 fullStack.push(prevFrame);
271 }
272 }
273 this.profile_.recordTick(fullStack);
274 }; 220 };
275 221
276 222
277 TickProcessor.prototype.printStatistics = function() { 223 TickProcessor.prototype.printStatistics = function() {
278 print('Statistical profiling result from ' + this.lastLogFileName_ + 224 print('Statistical profiling result from ' + this.lastLogFileName_ +
279 ', (' + this.ticks_.total + 225 ', (' + this.ticks_.total +
280 ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' + 226 ' ticks, ' + this.ticks_.unaccounted + ' unaccounted, ' +
281 this.ticks_.excluded + ' excluded).'); 227 this.ticks_.excluded + ' excluded).');
282 228
283 if (this.ticks_.total == 0) return; 229 if (this.ticks_.total == 0) return;
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 403
458 CppEntriesProvider.prototype.loadSymbols = function(libName) { 404 CppEntriesProvider.prototype.loadSymbols = function(libName) {
459 }; 405 };
460 406
461 407
462 CppEntriesProvider.prototype.parseNextLine = function() { 408 CppEntriesProvider.prototype.parseNextLine = function() {
463 return false; 409 return false;
464 }; 410 };
465 411
466 412
467 function inherits(childCtor, parentCtor) {
468 function tempCtor() {};
469 tempCtor.prototype = parentCtor.prototype;
470 childCtor.prototype = new tempCtor();
471 };
472
473
474 function UnixCppEntriesProvider() { 413 function UnixCppEntriesProvider() {
475 this.symbols = []; 414 this.symbols = [];
476 this.parsePos = 0; 415 this.parsePos = 0;
477 }; 416 };
478 inherits(UnixCppEntriesProvider, CppEntriesProvider); 417 inherits(UnixCppEntriesProvider, CppEntriesProvider);
479 418
480 419
481 UnixCppEntriesProvider.FUNC_RE = /^([0-9a-fA-F]{8}) [tTwW] (.*)$/; 420 UnixCppEntriesProvider.FUNC_RE = /^([0-9a-fA-F]{8}) [tTwW] (.*)$/;
482 421
483 422
484 UnixCppEntriesProvider.prototype.loadSymbols = function(libName) { 423 UnixCppEntriesProvider.prototype.loadSymbols = function(libName) {
485 this.parsePos = 0; 424 this.parsePos = 0;
486 try { 425 try {
487 this.symbols = [ 426 this.symbols = [
488 os.system('nm', ['-C', '-n', libName], -1, -1), 427 os.system('nm', ['-C', '-n', libName], -1, -1),
489 os.system('nm', ['-C', '-n', '-D', libName], -1, -1) 428 os.system('nm', ['-C', '-n', '-D', libName], -1, -1)
490 ]; 429 ];
491 } catch (e) { 430 } catch (e) {
492 // If the library cannot be found on this system let's not panic. 431 // If the library cannot be found on this system let's not panic.
493 this.symbols = [ '', '' ]; 432 this.symbols = ['', ''];
494 } 433 }
495 }; 434 };
496 435
497 436
498 UnixCppEntriesProvider.prototype.parseNextLine = function() { 437 UnixCppEntriesProvider.prototype.parseNextLine = function() {
499 if (this.symbols.length == 0) { 438 if (this.symbols.length == 0) {
500 return false; 439 return false;
501 } 440 }
502 var lineEndPos = this.symbols[0].indexOf('\n', this.parsePos); 441 var lineEndPos = this.symbols[0].indexOf('\n', this.parsePos);
503 if (lineEndPos == -1) { 442 if (lineEndPos == -1) {
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 592
654 var params = processArguments(arguments); 593 var params = processArguments(arguments);
655 var tickProcessor = new TickProcessor( 594 var tickProcessor = new TickProcessor(
656 params.platform == 'unix' ? new UnixCppEntriesProvider() : 595 params.platform == 'unix' ? new UnixCppEntriesProvider() :
657 new WindowsCppEntriesProvider(), 596 new WindowsCppEntriesProvider(),
658 params.separateIc, 597 params.separateIc,
659 params.ignoreUnknown, 598 params.ignoreUnknown,
660 params.stateFilter); 599 params.stateFilter);
661 tickProcessor.processLogFile(params.logFileName); 600 tickProcessor.processLogFile(params.logFileName);
662 tickProcessor.printStatistics(); 601 tickProcessor.printStatistics();
OLDNEW
« tools/logreader.js ('K') | « tools/logreader.js ('k') | tools/windows-tick-processor.bat » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698