Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / trace-viewer / trace_viewer / tracing / trace_model / thread.html
1 <!DOCTYPE html>
2 <!--
3 Copyright (c) 2013 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
6 -->
7
8 <link rel="import" href="/tracing/trace_model/slice.html">
9 <link rel="import" href="/tracing/trace_model/slice_group.html">
10 <link rel="import" href="/tracing/trace_model/async_slice_group.html">
11 <link rel="import" href="/base/guid.html">
12 <link rel="import" href="/base/range.html">
13
14 <script>
15 'use strict';
16
17 /**
18  * @fileoverview Provides the Thread class.
19  */
20 tv.exportTo('tracing.trace_model', function() {
21   var Slice = tracing.trace_model.Slice;
22   var SliceGroup = tracing.trace_model.SliceGroup;
23   var AsyncSlice = tracing.trace_model.AsyncSlice;
24   var AsyncSliceGroup = tracing.trace_model.AsyncSliceGroup;
25
26   /**
27    * A ThreadSlice represents an interval of time on a thread resource
28    * with associated nestinged slice information.
29    *
30    * ThreadSlices are typically associated with a specific trace event pair on a
31    * specific thread.
32    * For example,
33    *   TRACE_EVENT_BEGIN1("x","myArg", 7) at time=0.1ms
34    *   TRACE_EVENT_END0()                 at time=0.3ms
35    * This results in a single slice from 0.1 with duration 0.2 on a
36    * specific thread.
37    *
38    * @constructor
39    */
40   function ThreadSlice(cat, title, colorId, start, args, opt_duration,
41                        opt_cpuStart, opt_cpuDuration) {
42     Slice.call(this, cat, title, colorId, start, args, opt_duration,
43                opt_cpuStart, opt_cpuDuration);
44     // Do not modify this directly.
45     // subSlices is configured by SliceGroup.rebuildSubRows_.
46     this.subSlices = [];
47   }
48
49   ThreadSlice.prototype = {
50     __proto__: Slice.prototype
51   };
52
53   /**
54    * A Thread stores all the trace events collected for a particular
55    * thread. We organize the synchronous slices on a thread by "subrows," where
56    * subrow 0 has all the root slices, subrow 1 those nested 1 deep, and so on.
57    * The asynchronous slices are stored in an AsyncSliceGroup object.
58    *
59    * The slices stored on a Thread should be instances of
60    * ThreadSlice.
61    *
62    * @constructor
63    */
64   function Thread(parent, tid) {
65     this.guid_ = tv.GUID.allocate();
66     if (!parent)
67       throw new Error('Parent must be provided.');
68     this.parent = parent;
69     this.sortIndex = 0;
70     this.tid = tid;
71     this.name = undefined;
72     this.samples_ = undefined; // Set during createSubSlices
73
74     var that = this;
75     function ThreadSliceForThisThread(
76         cat, title, colorId, start, args, opt_duration,
77         opt_cpuStart, opt_cpuDuration) {
78       ThreadSlice.call(this, cat, title, colorId, start, args, opt_duration,
79                        opt_cpuStart, opt_cpuDuration);
80       this.parentThread = that;
81     }
82     ThreadSliceForThisThread.prototype = {
83       __proto__: ThreadSlice.prototype
84     };
85
86     this.sliceGroup = new SliceGroup(this, ThreadSliceForThisThread, 'slices');
87     this.timeSlices = undefined;
88     this.kernelSliceGroup = new SliceGroup(this, undefined, 'kernel-slices');
89     this.asyncSliceGroup = new AsyncSliceGroup(this, 'async-slices');
90     this.bounds = new tv.Range();
91   }
92
93   Thread.prototype = {
94
95     /*
96      * @return {Number} A globally unique identifier for this counter.
97      */
98     get guid() {
99       return this.guid_;
100     },
101
102     compareTo: function(that) {
103       return Thread.compare(this, that);
104     },
105
106     toJSON: function() {
107       var obj = new Object();
108       var keys = Object.keys(this);
109       for (var i = 0; i < keys.length; i++) {
110         var key = keys[i];
111         if (typeof this[key] == 'function')
112           continue;
113         if (key == 'parent') {
114           obj[key] = this[key].guid;
115           continue;
116         }
117         obj[key] = this[key];
118       }
119       return obj;
120     },
121
122     /**
123      * Shifts all the timestamps inside this thread forward by the amount
124      * specified.
125      */
126     shiftTimestampsForward: function(amount) {
127       this.sliceGroup.shiftTimestampsForward(amount);
128
129       if (this.timeSlices) {
130         for (var i = 0; i < this.timeSlices.length; i++) {
131           var slice = this.timeSlices[i];
132           slice.start += amount;
133         }
134       }
135
136       this.kernelSliceGroup.shiftTimestampsForward(amount);
137       this.asyncSliceGroup.shiftTimestampsForward(amount);
138     },
139
140     /**
141      * Determines whether this thread is empty. If true, it usually implies
142      * that it should be pruned from the model.
143      */
144     get isEmpty() {
145       if (this.sliceGroup.length)
146         return false;
147       if (this.sliceGroup.openSliceCount)
148         return false;
149       if (this.timeSlices && this.timeSlices.length)
150         return false;
151       if (this.kernelSliceGroup.length)
152         return false;
153       if (this.asyncSliceGroup.length)
154         return false;
155       if (this.samples_.length)
156         return false;
157       return true;
158     },
159
160     /**
161      * Updates the bounds based on the
162      * current objects associated with the thread.
163      */
164     updateBounds: function() {
165       this.bounds.reset();
166
167       this.sliceGroup.updateBounds();
168       this.bounds.addRange(this.sliceGroup.bounds);
169
170       this.kernelSliceGroup.updateBounds();
171       this.bounds.addRange(this.kernelSliceGroup.bounds);
172
173       this.asyncSliceGroup.updateBounds();
174       this.bounds.addRange(this.asyncSliceGroup.bounds);
175
176       if (this.timeSlices && this.timeSlices.length) {
177         this.bounds.addValue(this.timeSlices[0].start);
178         this.bounds.addValue(
179             this.timeSlices[this.timeSlices.length - 1].end);
180       }
181
182       if (this.samples_ && this.samples_.length) {
183         this.bounds.addValue(this.samples_[0].start);
184         this.bounds.addValue(
185             this.samples_[this.samples_.length - 1].end);
186       }
187     },
188
189     addCategoriesToDict: function(categoriesDict) {
190       for (var i = 0; i < this.sliceGroup.length; i++)
191         categoriesDict[this.sliceGroup.slices[i].category] = true;
192       for (var i = 0; i < this.kernelSliceGroup.length; i++)
193         categoriesDict[this.kernelSliceGroup.slices[i].category] = true;
194       for (var i = 0; i < this.asyncSliceGroup.length; i++)
195         categoriesDict[this.asyncSliceGroup.slices[i].category] = true;
196       if (this.samples_) {
197         for (var i = 0; i < this.samples_.length; i++)
198           categoriesDict[this.samples_[i].category] = true;
199       }
200     },
201
202     autoCloseOpenSlices: function(opt_maxTimestamp) {
203       this.sliceGroup.autoCloseOpenSlices(opt_maxTimestamp);
204       this.kernelSliceGroup.autoCloseOpenSlices(opt_maxTimestamp);
205     },
206
207     mergeKernelWithUserland: function() {
208       if (this.kernelSliceGroup.length > 0) {
209         var newSlices = SliceGroup.merge(
210             this.sliceGroup, this.kernelSliceGroup);
211         this.sliceGroup.slices = newSlices.slices;
212         this.kernelSliceGroup = new SliceGroup(this);
213         this.updateBounds();
214       }
215     },
216
217     createSubSlices: function() {
218       this.sliceGroup.createSubSlices();
219       this.samples_ = this.parent.model.samples.filter(function(sample) {
220         return sample.thread == this;
221       }, this);
222     },
223
224     /**
225      * @return {String} A user-friendly name for this thread.
226      */
227     get userFriendlyName() {
228       return this.name || this.tid;
229     },
230
231     /**
232      * @return {String} User friendly details about this thread.
233      */
234     get userFriendlyDetails() {
235       return 'tid: ' + this.tid +
236           (this.name ? ', name: ' + this.name : '');
237     },
238
239     getSettingsKey: function() {
240       if (!this.name)
241         return undefined;
242       var parentKey = this.parent.getSettingsKey();
243       if (!parentKey)
244         return undefined;
245       return parentKey + '.' + this.name;
246     },
247
248     /*
249      * Returns the index of the slice in the timeSlices array, or undefined.
250      */
251     indexOfTimeSlice: function(timeSlice) {
252       var i = tv.findLowIndexInSortedArray(
253           this.timeSlices,
254           function(slice) { return slice.start; },
255           timeSlice.start);
256       if (this.timeSlices[i] !== timeSlice)
257         return undefined;
258       return i;
259     },
260
261     iterateAllEvents: function(callback, opt_this) {
262       this.sliceGroup.iterateAllEvents(callback, opt_this);
263       this.kernelSliceGroup.iterateAllEvents(callback, opt_this);
264       this.asyncSliceGroup.iterateAllEvents(callback, opt_this);
265
266       if (this.timeSlices && this.timeSlices.length)
267         this.timeSlices.forEach(callback, opt_this);
268     },
269
270     iterateAllPersistableObjects: function(cb) {
271       cb(this);
272       if (this.sliceGroup.length)
273         cb(this.sliceGroup);
274       this.asyncSliceGroup.viewSubGroups.forEach(cb);
275     },
276
277     get samples() {
278       return this.samples_;
279     }
280   };
281
282   /**
283    * Comparison between threads that orders first by parent.compareTo,
284    * then by names, then by tid.
285    */
286   Thread.compare = function(x, y) {
287     var tmp = x.parent.compareTo(y.parent);
288     if (tmp)
289       return tmp;
290
291     tmp = x.sortIndex - y.sortIndex;
292     if (tmp)
293       return tmp;
294
295     tmp = tv.comparePossiblyUndefinedValues(
296         x.name, y.name,
297         function(x, y) { return x.localeCompare(y); });
298     if (tmp)
299       return tmp;
300
301     return x.tid - y.tid;
302   };
303
304   return {
305     ThreadSlice: ThreadSlice,
306     Thread: Thread
307   };
308 });
309 </script>