Index: tracing/tracing/value/diagnostics/composition.html |
diff --git a/tracing/tracing/value/diagnostics/composition.html b/tracing/tracing/value/diagnostics/composition.html |
index c58f29d0b02db5dc3551286a1d97428c68963c93..657969c5ccb40fbf151c0f9ffae4c6e361546f31 100644 |
--- a/tracing/tracing/value/diagnostics/composition.html |
+++ b/tracing/tracing/value/diagnostics/composition.html |
@@ -5,26 +5,111 @@ Use of this source code is governed by a BSD-style license that can be |
found in the LICENSE file. |
--> |
-<link rel="import" href="/tracing/value/diagnostics/related_value_set.html"> |
+<link rel="import" href="/tracing/value/diagnostics/related_value_map.html"> |
<script> |
'use strict'; |
tr.exportTo('tr.v.d', function() { |
- /** @constructor */ |
- function Composition(opt_values) { |
- tr.v.d.RelatedValueSet.call(this, opt_values); |
+ /** |
+ * Composition encapsulates an additive relationship between NumericValues: |
+ * the Value that contains this Composition diagnostic is composed of the |
+ * Values referenced by this Composition diagnostic. Composition is a |
+ * "breakdown" of its containing Value into its contained Values. This |
+ * additive relationship can apply to groups of other things besides Events, |
+ * such as memory allocations. Compositions over groups of Events is expected |
+ * to be the most common way of building Compositions, though it is not the |
+ * only way. See buildFromEvents() for an example of how to build a |
+ * Composition from an EventSet and a grouping function. |
+ * |
+ * @constructor |
+ */ |
+ function Composition() { |
+ tr.v.d.RelatedValueMap.call(this); |
} |
+ /** |
+ * Build a Composition and its NumericValues from |events|. Group events using |
+ * |categoryForEvent|. Add the NumericValues to |values|. NumericValues' names |
+ * are prefixed with |namePrefix|. Numerics are built by |numericBuilder|. The |
+ * Numeric sample for each Event is derived from |opt_sampleForEvent|, which |
+ * defaults to event.cpuSelfTime. The caller must add the result Composition |
+ * to their Value's diagnostics. |
+ * |
+ * @param {!tr.v.ValueSet} values |
+ * @param {string} namePrefix |
+ * @param {!tr.model.EventSet} events |
+ * @param {!tr.v.NumericBuilder} numericBuilder |
+ * @param {!function(!tr.model.Event):string} categoryForEvent |
+ * @param {!function(!tr.model.Event):number=} opt_sampleForEvent |
+ * @param {*=} opt_this |
+ * @return {!Composition} |
+ */ |
+ Composition.buildFromEvents = function( |
+ values, namePrefix, events, numericBuilder, categoryForEvent, |
+ opt_sampleForEvent, opt_this) { |
+ var sampleForEvent = opt_sampleForEvent || ((event) => event.cpuSelfTime); |
+ |
+ var composition = new Composition(); |
+ for (var event of events) { |
+ var sample = sampleForEvent.call(opt_this, event); |
+ if (sample === undefined) |
+ continue; |
+ |
+ var eventCategory = categoryForEvent.call(opt_this, event); |
+ var value = composition.get(eventCategory); |
+ if (value === undefined) { |
+ value = new tr.v.NumericValue( |
+ namePrefix + eventCategory, numericBuilder.build()); |
+ values.addValue(value); |
+ composition.set(eventCategory, value); |
+ } |
+ |
+ value.numeric.add(sample, new tr.v.d.RelatedEventSet([event])); |
+ } |
+ return composition; |
+ }; |
+ |
Composition.prototype = { |
- __proto__: tr.v.d.RelatedValueSet.prototype |
+ __proto__: tr.v.d.RelatedValueMap.prototype, |
+ |
+ /** |
+ * Add a Value by an explicit name to this map. |
+ * |
+ * @param {string} name |
+ * @param {!(tr.v.d.ValueRef|tr.v.Value)} value |
+ */ |
+ set: function(name, value) { |
+ if (!(value instanceof tr.v.d.ValueRef)) { |
+ if (!(value instanceof tr.v.NumericValue)) |
+ throw new Error('Composition can only contain NumericValues'); |
+ |
+ if (value.name.indexOf(name) !== (value.name.length - name.length)) |
+ throw new Error('Composition name must be a suffix of value.name'); |
+ |
+ var existingValues = this.values; |
+ if ((existingValues.length > 0) && |
+ (value.numeric.unit !== existingValues[0].numeric.unit)) { |
+ throw new Error('Units mismatch', existingValues[0].numeric.unit, |
+ value.numeric.unit); |
+ } |
+ } |
+ |
+ tr.v.d.RelatedValueMap.prototype.set.call(this, name, value); |
+ } |
}; |
Composition.fromDict = function(d) { |
- return new Composition(d.guids.map(guid => new tr.v.d.ValueRef(guid))); |
+ var composition = new Composition(); |
+ tr.b.iterItems(d.values, function(name, guid) { |
+ composition.set(name, new tr.v.d.ValueRef(guid)); |
+ }); |
+ return composition; |
}; |
- tr.v.d.Diagnostic.register(Composition); |
+ tr.v.d.Diagnostic.register(Composition, { |
+ elementName: 'tr-v-ui-composition-span' |
+ }); |
return { |
Composition: Composition |