summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authormnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 13:05:51 +0000
committermnaganov@chromium.org <mnaganov@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-14 13:05:51 +0000
commitfbcd92d686f77817f43c262d773ca523bf16d9ae (patch)
treecb94f783b328154916ae9fcfaf0c1ccdc6b32988 /webkit
parent3244c8cb2fd6f976c7d4c7da181347dfceab9f70 (diff)
downloadchromium_src-fbcd92d686f77817f43c262d773ca523bf16d9ae.zip
chromium_src-fbcd92d686f77817f43c262d773ca523bf16d9ae.tar.gz
chromium_src-fbcd92d686f77817f43c262d773ca523bf16d9ae.tar.bz2
DevTools: implement comparison of heap snapshots in Heap profiler.
BUG=none TEST=none Review URL: http://codereview.chromium.org/164557 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23434 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/glue/devtools/js/devtools_host_stub.js24
-rw-r--r--webkit/glue/devtools/js/heap_profiler_panel.js222
-rw-r--r--webkit/glue/devtools/js/profiler_processor.js6
-rw-r--r--webkit/glue/devtools_strings.grd47
4 files changed, 250 insertions, 49 deletions
diff --git a/webkit/glue/devtools/js/devtools_host_stub.js b/webkit/glue/devtools/js/devtools_host_stub.js
index 783d29c..b53c990 100644
--- a/webkit/glue/devtools/js/devtools_host_stub.js
+++ b/webkit/glue/devtools/js/devtools_host_stub.js
@@ -14,6 +14,7 @@ RemoteDebuggerAgentStub = function() {
this.activeProfilerModules_ =
devtools.DebuggerAgent.ProfilerModules.PROFILER_MODULE_NONE;
this.profileLogPos_ = 0;
+ this.heapProfSample_ = 0;
this.heapProfLog_ = '';
};
@@ -39,9 +40,16 @@ RemoteDebuggerAgentStub.prototype.StartProfiling = function(modules) {
this.heapProfLog_ +=
'heap-sample-begin,"Heap","allocated",' +
(new Date()).getTime() + '\n' +
- 'heap-sample-stats,"Heap","allocated",10000,1000\n' +
- 'heap-js-cons-item,"foo",10,1000\n' +
- 'heap-js-cons-item,"bar",20,2000\n' +
+ 'heap-sample-stats,"Heap","allocated",10000,1000\n';
+ var sample = RemoteDebuggerAgentStub.HeapSamples[this.heapProfSample_];
+ if (++this.heapProfSample_ == RemoteDebuggerAgentStub.HeapSamples.length)
+ this.heapProfSample_ = 0;
+ for (var obj in sample) {
+ this.heapProfLog_ +=
+ 'heap-js-cons-item,"' + obj + '",' + sample[obj][0] +
+ ',' + sample[obj][1] + '\n';
+ }
+ this.heapProfLog_ +=
'heap-sample-end,"Heap","allocated"\n';
}
} else {
@@ -186,6 +194,16 @@ RemoteDebuggerAgentStub.ProfilerLogBuffer =
'profiler,pause\n';
+RemoteDebuggerAgentStub.HeapSamples = [
+ {foo: [1, 100], bar: [20, 2000]},
+ {foo: [2000, 200000], bar: [10, 1000]},
+ {foo: [15, 1500], bar: [15, 1500]},
+ {bar: [20, 2000]},
+ {foo: [15, 1500], bar: [15, 1500]},
+ {bar: [20, 2000], baz: [15, 1500]}
+];
+
+
/**
* @constructor
*/
diff --git a/webkit/glue/devtools/js/heap_profiler_panel.js b/webkit/glue/devtools/js/heap_profiler_panel.js
index 6db8a06..49f34b3 100644
--- a/webkit/glue/devtools/js/heap_profiler_panel.js
+++ b/webkit/glue/devtools/js/heap_profiler_panel.js
@@ -83,13 +83,16 @@ WebInspector.HeapProfilerPanel.prototype = {
addSnapshot: function(snapshot) {
this._snapshots.push(snapshot);
+ snapshot.list = this._snapshots;
+ snapshot.listIndex = this._snapshots.length - 1;
- var sidebarParent = this.sidebarTree;
var snapshotsTreeElement = new WebInspector.HeapSnapshotSidebarTreeElement(snapshot);
snapshotsTreeElement.small = false;
snapshot._snapshotsTreeElement = snapshotsTreeElement;
- sidebarParent.appendChild(snapshotsTreeElement);
+ this.sidebarTree.appendChild(snapshotsTreeElement);
+
+ this.dispatchEventToListeners("snapshot added");
},
showSnapshot: function(snapshot) {
@@ -118,7 +121,7 @@ WebInspector.HeapProfilerPanel.prototype = {
if (!snapshot)
return null;
if (!snapshot._snapshotView)
- snapshot._snapshotView = new WebInspector.HeapSnapshotView(snapshot);
+ snapshot._snapshotView = new WebInspector.HeapSnapshotView(this, snapshot);
return snapshot._snapshotView;
},
@@ -177,18 +180,25 @@ WebInspector.HeapProfilerPanel.prototype = {
WebInspector.HeapProfilerPanel.prototype.__proto__ = WebInspector.Panel.prototype;
-WebInspector.HeapSnapshotView = function(snapshot)
+WebInspector.HeapSnapshotView = function(parent, snapshot)
{
WebInspector.View.call(this);
this.element.addStyleClass("heap-snapshot-view");
+ this.parent = parent;
+ this.parent.addEventListener("snapshot added", this._updateBaseOptions, this);
+
this.showCountAsPercent = true;
this.showSizeAsPercent = true;
+ this.showCountDeltaAsPercent = true;
+ this.showSizeDeltaAsPercent = true;
var columns = { "cons": { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
"count": { title: WebInspector.UIString("Count"), width: "54px", sortable: true },
- "size": { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true } };
+ "size": { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true },
+ "countDelta": { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true },
+ "sizeDelta": { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true } };
this.dataGrid = new WebInspector.DataGrid(columns);
this.dataGrid.addEventListener("sorting changed", this._sortData, this);
@@ -196,11 +206,18 @@ WebInspector.HeapSnapshotView = function(snapshot)
this.element.appendChild(this.dataGrid.element);
this.snapshot = snapshot;
- this.snapshotDataGridList = this.createSnapshotDataGridList();
- this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator("objectsSize", false));
- this.percentButton = document.createElement("button");
- this.percentButton.className = "percent-time-status-bar-item status-bar-item";
+ this.baseSelectElement = document.createElement("select");
+ this.baseSelectElement.className = "status-bar-item";
+ this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
+ this._updateBaseOptions();
+ if (this.snapshot.listIndex > 0)
+ this.baseSelectElement.selectedIndex = this.snapshot.listIndex - 1;
+ else
+ this.baseSelectElement.selectedIndex = this.snapshot.listIndex;
+ this._resetDataGridList();
+
+ this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
this.refresh();
@@ -211,7 +228,7 @@ WebInspector.HeapSnapshotView = function(snapshot)
WebInspector.HeapSnapshotView.prototype = {
get statusBarItems()
{
- return [this.percentButton];
+ return [this.baseSelectElement, this.percentButton.element];
},
get snapshot()
@@ -224,11 +241,16 @@ WebInspector.HeapSnapshotView.prototype = {
this._snapshot = snapshot;
},
- createSnapshotDataGridList: function()
+ show: function(parentElement)
{
- if (!this._snapshotDataGridList)
- this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.snapshot.entries);
- return this._snapshotDataGridList;
+ WebInspector.View.prototype.show.call(this, parentElement);
+ this.dataGrid.updateWidths();
+ },
+
+ resize: function()
+ {
+ if (this.dataGrid)
+ this.dataGrid.updateWidths();
},
refresh: function()
@@ -256,19 +278,40 @@ WebInspector.HeapSnapshotView.prototype = {
}
},
+ _changeBase: function() {
+ if (this.baseSnapshot === this.snapshot.list[this.baseSelectElement.selectedIndex])
+ return;
+
+ this._resetDataGridList();
+ this.refresh();
+ },
+
+ _createSnapshotDataGridList: function()
+ {
+ if (this._snapshotDataGridList)
+ delete this._snapshotDataGridList;
+
+ this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.snapshot.entries);
+ return this._snapshotDataGridList;
+ },
+
_mouseDownInDataGrid: function(event)
{
if (event.detail < 2)
return;
var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
- if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column")))
+ if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column")))
return;
if (cell.hasStyleClass("count-column"))
this.showCountAsPercent = !this.showCountAsPercent;
else if (cell.hasStyleClass("size-column"))
this.showSizeAsPercent = !this.showSizeAsPercent;
+ else if (cell.hasStyleClass("countDelta-column"))
+ this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent;
+ else if (cell.hasStyleClass("sizeDelta-column"))
+ this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent;
this.refreshShowAsPercents();
@@ -276,14 +319,32 @@ WebInspector.HeapSnapshotView.prototype = {
event.stopPropagation();
},
+ get _isShowingAsPercent()
+ {
+ return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent;
+ },
+
_percentClicked: function(event)
{
- var currentState = this.showCountAsPercent && this.showSizeAsPercent;
+ var currentState = this._isShowingAsPercent;
this.showCountAsPercent = !currentState;
this.showSizeAsPercent = !currentState;
+ this.showCountDeltaAsPercent = !currentState;
+ this.showSizeDeltaAsPercent = !currentState;
this.refreshShowAsPercents();
},
+ _resetDataGridList: function()
+ {
+ this.baseSnapshot = this.snapshot.list[this.baseSelectElement.selectedIndex];
+ var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("objectsSize", false);
+ if (this.snapshotDataGridList) {
+ lastComparator = this.snapshotDataGridList.lastComparator;
+ }
+ this.snapshotDataGridList = this._createSnapshotDataGridList();
+ this.snapshotDataGridList.sort(lastComparator, true);
+ },
+
_sortData: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
@@ -291,7 +352,9 @@ WebInspector.HeapSnapshotView.prototype = {
var sortProperty = {
"cons": "constructorName",
"count": "objectsCount",
- "size": "objectsSize"
+ "size": "objectsSize",
+ "countDelta": this.showCountDeltaAsPercent ? "objectsCountDeltaPercent" : "objectsCountDelta",
+ "sizeDelta": this.showSizeDeltaAsPercent ? "objectsSizeDeltaPercent" : "objectsSizeDelta"
}[sortColumnIdentifier];
this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty, sortAscending));
@@ -299,14 +362,27 @@ WebInspector.HeapSnapshotView.prototype = {
this.refresh();
},
+ _updateBaseOptions: function()
+ {
+ // We're assuming that snapshots can only be added.
+ if (this.baseSelectElement.length == this.snapshot.list.length)
+ return;
+
+ for (var i = this.baseSelectElement.length, n = this.snapshot.list.length; i < n; ++i) {
+ var baseOption = document.createElement("option");
+ baseOption.label = WebInspector.UIString("Compared to %s", this.snapshot.list[i].title);
+ this.baseSelectElement.appendChild(baseOption);
+ }
+ },
+
_updatePercentButton: function()
{
- if (this.showCountAsPercent && this.showSizeAsPercent) {
- this.percentButton.title = WebInspector.UIString("Show absolute counts and sized.");
- this.percentButton.addStyleClass("toggled-on");
+ if (this._isShowingAsPercent) {
+ this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
+ this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
- this.percentButton.removeStyleClass("toggled-on");
+ this.percentButton.toggled = false;
}
}
};
@@ -316,7 +392,7 @@ WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;
WebInspector.HeapSnapshotSidebarTreeElement = function(snapshot)
{
this.snapshot = snapshot;
- this._snapshotNumber = snapshot.number;
+ this.snapshot.title = WebInspector.UIString("Snapshot %d", this.snapshot.number);
WebInspector.SidebarTreeElement.call(this, "heap-snapshot-sidebar-tree-item", "", "", snapshot, false);
@@ -333,7 +409,7 @@ WebInspector.HeapSnapshotSidebarTreeElement.prototype = {
{
if (this._mainTitle)
return this._mainTitle;
- return WebInspector.UIString("Snapshot %d", this._snapshotNumber);
+ return this.snapshot.title;
},
set mainTitle(x)
@@ -346,7 +422,7 @@ WebInspector.HeapSnapshotSidebarTreeElement.prototype = {
{
if (this._subTitle)
return this._subTitle;
- return WebInspector.UIString("Used %s of %s (%.0f%)", Number.bytesToString(this.snapshot.used, null, false), Number.bytesToString(this.snapshot.capacity, null, false), this.snapshot.used / this.snapshot.capacity * 100.0);
+ return WebInspector.UIString("Used %s of %s (%.0f%%)", Number.bytesToString(this.snapshot.used, null, false), Number.bytesToString(this.snapshot.capacity, null, false), this.snapshot.used / this.snapshot.capacity * 100.0);
},
set subtitle(x)
@@ -358,61 +434,119 @@ WebInspector.HeapSnapshotSidebarTreeElement.prototype = {
WebInspector.HeapSnapshotSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;
-WebInspector.HeapSnapshotDataGridNode = function(snapshotView, snapshotEntry, owningList)
+WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningList)
{
- this.snapshotView = snapshotView;
- this.snapshotEntry = snapshotEntry;
-
WebInspector.DataGridNode.call(this, null, false);
+ this.snapshotView = snapshotView;
this.list = owningList;
- this.lastComparator = null;
+ if (!snapshotEntry)
+ snapshotEntry = { cons: baseEntry.cons, count: 0, size: 0 };
this.constructorName = snapshotEntry.cons;
this.objectsCount = snapshotEntry.count;
this.objectsSize = snapshotEntry.size;
+
+ if (!baseEntry)
+ baseEntry = { count: 0, size: 0 };
+ this.baseObjectsCount = baseEntry.count;
+ this.objectsCountDelta = this.objectsCount - this.baseObjectsCount;
+ this.baseObjectsSize = baseEntry.size;
+ this.objectsSizeDelta = this.objectsSize - this.baseObjectsSize;
};
WebInspector.HeapSnapshotDataGridNode.prototype = {
get data()
{
- var data = {
- cons: this.constructorName
- };
+ var data = {};
+
+ data["cons"] = this.constructorName;
if (this.snapshotView.showCountAsPercent)
- data["count"] = WebInspector.UIString("%.2f%%", this.countPercent);
+ data["count"] = WebInspector.UIString("%.2f%%", this.objectsCountPercent);
else
data["count"] = this.objectsCount;
if (this.snapshotView.showSizeAsPercent)
- data["size"] = WebInspector.UIString("%.2f%%", this.sizePercent);
+ data["size"] = WebInspector.UIString("%.2f%%", this.objectsSizePercent);
else
data["size"] = Number.bytesToString(this.objectsSize);
+ function signForDelta(delta) {
+ if (delta == 0)
+ return "";
+ if (delta > 0)
+ return "+";
+ else
+ // Math minus sign, same width as plus.
+ return "\u2212";
+ }
+
+ function showDeltaAsPercent(value) {
+ if (value === Number.POSITIVE_INFINITY)
+ return WebInspector.UIString("new");
+ else if (value === Number.NEGATIVE_INFINITY)
+ return WebInspector.UIString("deleted");
+ if (value > 1000.0)
+ return WebInspector.UIString("%s >1000%%", signForDelta(value));
+ return WebInspector.UIString("%s%.2f%%", signForDelta(value), Math.abs(value));
+ }
+
+ if (this.snapshotView.showCountDeltaAsPercent)
+ data["countDelta"] = showDeltaAsPercent(this.objectsCountDeltaPercent);
+ else
+ data["countDelta"] = WebInspector.UIString("%s%d", signForDelta(this.objectsCountDelta), Math.abs(this.objectsCountDelta));
+
+ if (this.snapshotView.showSizeDeltaAsPercent)
+ data["sizeDelta"] = showDeltaAsPercent(this.objectsSizeDeltaPercent);
+ else
+ data["sizeDelta"] = WebInspector.UIString("%s%s", signForDelta(this.objectsSizeDelta), Number.bytesToString(Math.abs(this.objectsSizeDelta)));
+
return data;
},
- get countPercent()
+ get objectsCountPercent()
{
return this.objectsCount / this.list.objectsCount * 100.0;
},
- get sizePercent()
+ get objectsSizePercent()
{
return this.objectsSize / this.list.objectsSize * 100.0;
+ },
+
+ get objectsCountDeltaPercent()
+ {
+ if (this.baseObjectsCount > 0) {
+ if (this.objectsCount > 0)
+ return this.objectsCountDelta / this.baseObjectsCount * 100.0;
+ else
+ return Number.NEGATIVE_INFINITY;
+ } else
+ return Number.POSITIVE_INFINITY;
+ },
+
+ get objectsSizeDeltaPercent()
+ {
+ if (this.baseObjectsSize > 0) {
+ if (this.objectsSize > 0)
+ return this.objectsSizeDelta / this.baseObjectsSize * 100.0;
+ else
+ return Number.NEGATIVE_INFINITY;
+ } else
+ return Number.POSITIVE_INFINITY;
}
};
WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;
-WebInspector.HeapSnapshotDataGridList = function(snapshotView, snapshotEntries)
+WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries)
{
this.list = this;
this.snapshotView = snapshotView;
this.children = [];
this.lastComparator = null;
- this.populateChildren(snapshotEntries);
+ this.populateChildren(baseEntries, snapshotEntries);
};
WebInspector.HeapSnapshotDataGridList.prototype = {
@@ -431,11 +565,15 @@ WebInspector.HeapSnapshotDataGridList.prototype = {
this.children = [];
},
- populateChildren: function(snapshotEntries)
+ populateChildren: function(baseEntries, snapshotEntries)
{
- var count = snapshotEntries.length;
- for (var index = 0; index < count; ++index)
- this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, snapshotEntries[index], this));
+ for (var item in snapshotEntries)
+ this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseEntries[item], snapshotEntries[item], this));
+
+ for (item in baseEntries) {
+ if (!(item in snapshotEntries))
+ this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseEntries[item], null, this));
+ }
},
sort: function(comparator, force) {
diff --git a/webkit/glue/devtools/js/profiler_processor.js b/webkit/glue/devtools/js/profiler_processor.js
index 351d0be..556841d 100644
--- a/webkit/glue/devtools/js/profiler_processor.js
+++ b/webkit/glue/devtools/js/profiler_processor.js
@@ -387,7 +387,7 @@ devtools.profiler.Processor.prototype.processHeapSampleBegin_ = function(
if (space != 'Heap') return;
this.currentHeapSnapshot_ = {
number: this.heapSnapshotId_++,
- entries: [],
+ entries: {},
ticks: ticks
};
};
@@ -404,9 +404,9 @@ devtools.profiler.Processor.prototype.processHeapSampleStats_ = function(
devtools.profiler.Processor.prototype.processHeapJsConsItem_ = function(
item, number, size) {
if (!this.currentHeapSnapshot_) return;
- this.currentHeapSnapshot_.entries.push({
+ this.currentHeapSnapshot_.entries[item] = {
cons: item, count: number, size: size
- });
+ };
};
diff --git a/webkit/glue/devtools_strings.grd b/webkit/glue/devtools_strings.grd
index 650ca36..1e97a2d 100644
--- a/webkit/glue/devtools_strings.grd
+++ b/webkit/glue/devtools_strings.grd
@@ -46,11 +46,56 @@ Google Chrome Developer Tools. -->
<message name="IDS_WINDOW_HEADER" desc="DevTools window header.">
Developer Tools - <ph name="URL">%s<ex>http://www.example.com/</ex></ph>
</message>
+ <message name="IDS_HEAP_TAB_TITLE" desc="Title of the heap profiler tab.">
+ Heap
+ </message>
+ <message name="IDS_TAKE_HEAP_SNAPSHOT" desc="Title of a button that takes heap snapshot.">
+ Take heap snapshot.
+ </message>
<message name="IDS_HEAP_SNAPSHOT" desc="Heap snapshot title.">
Snapshot <ph name="COUNT">%d<ex>1</ex></ph>
</message>
<message name="IDS_HEAP_USAGE" desc="Heap usage.">
- Used <ph name="USED">%1$s<ex>100MB</ex></ph> of <ph name="CAPACITY">%2$s<ex>200MB</ex></ph>
+ Used <ph name="USED">%1$s<ex>100MB</ex></ph> of <ph name="CAPACITY">%2$s<ex>200MB</ex></ph> (<ph name="PERCENT">%3$.0f<ex>50</ex></ph>%%)
+ </message>
+ <message name="IDS_HEAP_SNAPSHOT_GRID_CONSTRUCTOR" desc="Title of a heap snapshot grid column showing object's constructor name.">
+ Constructor
+ </message>
+ <message name="IDS_HEAP_SNAPSHOT_GRID_COUNT" desc="Title of a heap snapshot grid column showing objects count.">
+ Count
+ </message>
+ <message name="IDS_HEAP_SNAPSHOT_GRID_COUNT_DELTA" desc="Title of a heap snapshot grid column showing delta of objects count.">
+ ± Count
+ </message>
+ <message name="IDS_HEAP_SNAPSHOT_GRID_SIZE_DELTA" desc="Title of a heap snapshot grid column showing delta of objects size.">
+ ± Size
+ </message>
+ <message name="IDS_HEAP_SNAPSHOT_COMPARED_TO" desc="An option to choose a snapshot to compare current snapshot with.">
+ Compared to <ph name="BASE">%s<ex>Snapshot 1</ex></ph>
+ </message>
+ <message name="IDS_ABSOLUTE_OBJ_COUNTS_AND_SIZES" desc="An option to show absolute objects counts and sizes.">
+ Show absolute counts and sizes.
+ </message>
+ <message name="IDS_PERCENTAGE_OBJ_COUNTS_AND_SIZES" desc="An option to show objects counts and sizes as percentages.">
+ Show counts and sizes as percentages.
+ </message>
+ <message name="IDS_NEW_OBJECTS_IN_DELTA" desc="Indicates that object instances are new compared to base state.">
+ new
+ </message>
+ <message name="IDS_DELETED_OBJECTS_IN_DELTA" desc="Indicates that object instances have disappeared compared to base state.">
+ deleted
+ </message>
+ <message name="IDS_VERY_LARGE_DELTA" desc="Shows very large delta in percents">
+ <ph name="SIGN">%s<ex>+</ex></ph> >1000%%
+ </message>
+ <message name="IDS_SHARE_IN_PERCENTS_SIGNED" desc="Share in percents, with sign.">
+ <ph name="SIGN">%$1s<ex>+</ex></ph><ph name="SHARE">%$2.2f<ex>5</ex></ph>%%
+ </message>
+ <message name="IDS_SIGNED_DELTA" desc="Signed delta.">
+ %$1s%$2d
+ </message>
+ <message name="IDS_SIGNED_STRING_DELTA" desc="Signed string delta.">
+ %$1s%$2s
</message>
</messages>
</release>