2011-04-28 Mikhail Naganov <mnaganov@chromium.org>
authormnaganov@chromium.org <mnaganov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2011 14:53:45 +0000 (14:53 +0000)
committermnaganov@chromium.org <mnaganov@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 28 Apr 2011 14:53:45 +0000 (14:53 +0000)
        Reviewed by Yury Semikhatsky.

        Web Inspector: [Chromium] Optimize detailed heap snapshots loading / parsing.
        https://bugs.webkit.org/show_bug.cgi?id=59454

        Test: inspector/profiler/heap-snapshot-loader.html

        * inspector/front-end/HeapSnapshot.js:
        (WebInspector.HeapSnapshotLoader):
        (WebInspector.HeapSnapshotLoader.prototype._findBalancedCurlyBrackets):
        (WebInspector.HeapSnapshotLoader.prototype.finishLoading):
        (WebInspector.HeapSnapshotLoader.prototype._parseNodes):
        (WebInspector.HeapSnapshotLoader.prototype._parseStringsArray):
        (WebInspector.HeapSnapshotLoader.prototype.pushJSONChunk):
        * inspector/front-end/HeapSnapshotProxy.js:
        (WebInspector.HeapSnapshotFakeWorker.prototype.postMessage):

2011-04-28  Mikhail Naganov  <mnaganov@chromium.org>

        Reviewed by Yury Semikhatsky.

        Web Inspector: [Chromium] Optimize detailed heap snapshots loading / parsing.
        https://bugs.webkit.org/show_bug.cgi?id=59454

        * inspector/profiler/heap-snapshot-loader-expected.txt: Added.
        * inspector/profiler/heap-snapshot-loader.html: Added.
        * inspector/profiler/heap-snapshot-test.js:
        (initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMock):
        (initialize_HeapSnapshotTest):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@85182 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/inspector/profiler/heap-snapshot-loader-expected.txt [new file with mode: 0644]
LayoutTests/inspector/profiler/heap-snapshot-loader.html [new file with mode: 0644]
LayoutTests/inspector/profiler/heap-snapshot-test.js
Source/WebCore/ChangeLog
Source/WebCore/inspector/front-end/HeapSnapshot.js
Source/WebCore/inspector/front-end/HeapSnapshotProxy.js

index d66cd0e..d7d1272 100644 (file)
@@ -1,3 +1,16 @@
+2011-04-28  Mikhail Naganov  <mnaganov@chromium.org>
+
+        Reviewed by Yury Semikhatsky.
+
+        Web Inspector: [Chromium] Optimize detailed heap snapshots loading / parsing.
+        https://bugs.webkit.org/show_bug.cgi?id=59454
+
+        * inspector/profiler/heap-snapshot-loader-expected.txt: Added.
+        * inspector/profiler/heap-snapshot-loader.html: Added.
+        * inspector/profiler/heap-snapshot-test.js:
+        (initialize_HeapSnapshotTest.InspectorTest.createHeapSnapshotMock):
+        (initialize_HeapSnapshotTest):
+
 2011-04-28  Mark Pilgrim  <pilgrim@chromium.org>
 
         Reviewed by Tony Chang.
diff --git a/LayoutTests/inspector/profiler/heap-snapshot-loader-expected.txt b/LayoutTests/inspector/profiler/heap-snapshot-loader-expected.txt
new file mode 100644 (file)
index 0000000..230a397
--- /dev/null
@@ -0,0 +1,5 @@
+This test checks HeapSnapshots loader.
+
+
+Running: heapSnapshotLoaderTest
+
diff --git a/LayoutTests/inspector/profiler/heap-snapshot-loader.html b/LayoutTests/inspector/profiler/heap-snapshot-loader.html
new file mode 100644 (file)
index 0000000..9727d3e
--- /dev/null
@@ -0,0 +1,39 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="heap-snapshot-test.js"></script>
+<script>
+
+function test()
+{
+    InspectorTest.assertSnapshotEquals = function(reference, actual)
+    {
+        InspectorTest.assertEquals(JSON.stringify(reference), JSON.stringify(actual));
+    }
+
+    InspectorTest.runTestSuite([
+        function heapSnapshotLoaderTest(next)
+        {
+            var source = InspectorTest.createHeapSnapshotMock();
+            var sourceStringified = JSON.stringify(source);
+            var partSize = sourceStringified.length >> 3;
+            var loader = new WebInspector.HeapSnapshotLoader();
+            for (var i = 0, l = sourceStringified.length; i < l; i += partSize)
+                loader.pushJSONChunk(sourceStringified.slice(i, i + partSize));
+            var result = loader.finishLoading();
+            InspectorTest.assertSnapshotEquals(new WebInspector.HeapSnapshot(source), result);
+            next();
+        }
+    ]);
+}
+
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+This test checks HeapSnapshots loader.
+</p>
+
+</body>
+</html>
index 8ade9b5..893365a 100644 (file)
@@ -40,6 +40,7 @@ InspectorTest.createHeapSnapshotMockObject = function()
 InspectorTest.createHeapSnapshotMock = function()
 {
     return {
+        snapshot: {},
         nodes: [
             { fields: ["type", "name", "id", "self_size", "retained_size", "dominator", "children_count", "children"],
               types: [["hidden", "object"], "", "", "", "", "", "", { fields: ["type", "name_or_index", "to_node"], types: [["element", "property"], "", ""] }] },
@@ -61,8 +62,7 @@ InspectorTest.createHeapSnapshotMock = function()
             1, 3, 4, 4, 10,  1, 1, 1, 11, 57,
             1, 4, 5, 5,  5, 27, 0,
             1, 5, 6, 6,  6, 40, 0],
-        strings: ["", "A", "B", "C", "D", "E", "a", "b", "ac", "bc", "bd", "ce"],
-        snapshot: {}
+        strings: ["", "A", "B", "C", "D", "E", "a", "b", "ac", "bc", "bd", "ce"]
     };
 };
 
index c06f865..11386a5 100644 (file)
@@ -1,3 +1,22 @@
+2011-04-28  Mikhail Naganov  <mnaganov@chromium.org>
+
+        Reviewed by Yury Semikhatsky.
+
+        Web Inspector: [Chromium] Optimize detailed heap snapshots loading / parsing.
+        https://bugs.webkit.org/show_bug.cgi?id=59454
+
+        Test: inspector/profiler/heap-snapshot-loader.html
+
+        * inspector/front-end/HeapSnapshot.js:
+        (WebInspector.HeapSnapshotLoader):
+        (WebInspector.HeapSnapshotLoader.prototype._findBalancedCurlyBrackets):
+        (WebInspector.HeapSnapshotLoader.prototype.finishLoading):
+        (WebInspector.HeapSnapshotLoader.prototype._parseNodes):
+        (WebInspector.HeapSnapshotLoader.prototype._parseStringsArray):
+        (WebInspector.HeapSnapshotLoader.prototype.pushJSONChunk):
+        * inspector/front-end/HeapSnapshotProxy.js:
+        (WebInspector.HeapSnapshotFakeWorker.prototype.postMessage):
+
 2011-04-28  ojab  <ojab@ojab.ru>
 
         Reviewed by David Levin.
index 277fda9..1df93c5 100644 (file)
 WebInspector.HeapSnapshotLoader = function()
 {
     this._json = "";
+    this._state = "find-snapshot-info";
+    this._snapshot = {};
 }
 
 WebInspector.HeapSnapshotLoader.prototype = {
+    _findBalancedCurlyBrackets: function()
+    {
+        var counter = 0;
+        var openingBracket = "{".charCodeAt(0), closingBracket = "}".charCodeAt(0);
+        for (var i = 0, l = this._json.length; i < l; ++i) {
+            var character = this._json.charCodeAt(i);
+            if (character === openingBracket)
+                ++counter;
+            else if (character === closingBracket) {
+                if (--counter === 0)
+                    return i + 1;
+            }
+        }
+        return -1;
+    },
+
     finishLoading: function()
     {
         if (!this._json)
             return null;
-        var rawSnapshot = JSON.parse(this._json);
+        this._parseStringsArray();
         this._json = "";
-        return new WebInspector.HeapSnapshot(rawSnapshot);
+        var result = new WebInspector.HeapSnapshot(this._snapshot);
+        this._json = "";
+        this._snapshot = {};
+        return result;
+    },
+
+    _parseNodes: function()
+    {
+        var index = 0;
+        var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0);
+        var length = this._json.length;
+        while (true) {
+            while (index < length) {
+                var code = this._json.charCodeAt(index);
+                if (char0 <= code && code <= char9)
+                    break;
+                else if (code === closingBracket) {
+                    this._json = this._json.slice(index + 1);
+                    // Shave off provisionally allocated space.
+                    this._snapshot.nodes = this._snapshot.nodes.slice(0);
+                    return false;
+                }
+                ++index;
+            }
+            if (index === length) {
+                this._json = "";
+                return true;
+            }
+            var startIndex = index;
+            while (index < length) {
+                var code = this._json.charCodeAt(index);
+                if (char0 > code || code > char9)
+                    break;
+                ++index;
+            }
+            if (index === length) {
+                this._json = this._json.slice(startIndex);
+                return true;
+            }
+            this._snapshot.nodes.push(parseInt(this._json.slice(startIndex, index)));
+        }
+    },
+
+    _parseStringsArray: function()
+    {
+        var closingBracketIndex = this._json.lastIndexOf("]");
+        if (closingBracketIndex === -1)
+            throw new Error("Incomplete JSON");
+        this._json = this._json.slice(0, closingBracketIndex + 1);
+        this._snapshot.strings = JSON.parse(this._json);
     },
 
     pushJSONChunk: function(chunk)
     {
         this._json += chunk;
+        switch (this._state) {
+        case "find-snapshot-info": {
+            var snapshotToken = "\"snapshot\"";
+            var snapshotTokenIndex = this._json.indexOf(snapshotToken);
+            if (snapshotTokenIndex === -1)
+                throw new Error("Snapshot token not found");
+            this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
+            this._state = "parse-snapshot-info";
+            this.pushJSONChunk("");
+            break;
+        }
+        case "parse-snapshot-info": {
+            var closingBracketIndex = this._findBalancedCurlyBrackets();
+            if (closingBracketIndex === -1)
+                return;
+            this._snapshot.snapshot = JSON.parse(this._json.slice(0, closingBracketIndex));
+            this._json = this._json.slice(closingBracketIndex);
+            this._state = "find-nodes";
+            this.pushJSONChunk("");
+            break;
+        }
+        case "find-nodes": {
+            var nodesToken = "\"nodes\"";
+            var nodesTokenIndex = this._json.indexOf(nodesToken);
+            if (nodesTokenIndex === -1)
+                return;
+            var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
+            if (bracketIndex === -1)
+                return;
+            this._json = this._json.slice(bracketIndex + 1);
+            this._state = "parse-nodes-meta-info";
+            this.pushJSONChunk("");
+            break;
+        }
+        case "parse-nodes-meta-info": {
+            var closingBracketIndex = this._findBalancedCurlyBrackets();
+            if (closingBracketIndex === -1)
+                return;
+            this._snapshot.nodes = [JSON.parse(this._json.slice(0, closingBracketIndex))];
+            this._json = this._json.slice(closingBracketIndex);
+            this._state = "parse-nodes";
+            this.pushJSONChunk("");
+            break;          
+        }
+        case "parse-nodes": {
+            if (this._parseNodes())
+                return;
+            this._state = "find-strings";
+            this.pushJSONChunk("");
+            break;
+        }
+        case "find-strings": {
+            var stringsToken = "\"strings\"";
+            var stringsTokenIndex = this._json.indexOf(stringsToken);
+            if (stringsTokenIndex === -1)
+                return;
+            var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
+            if (bracketIndex === -1)
+                return;
+            this._json = this._json.slice(bracketIndex);
+            this._state = "accumulate-strings";
+            break;
+        }
+        case "accumulate-strings":
+            break;
+        }
     }
 };
 
index 9863d89..94e28e2 100644 (file)
@@ -63,7 +63,8 @@ WebInspector.HeapSnapshotFakeWorker.prototype = {
     {
         function dispatch()
         {
-            this._dispatcher.dispatchMessage({data: message});
+            if (this._dispatcher)
+                this._dispatcher.dispatchMessage({data: message});
         }
         setTimeout(dispatch.bind(this), 0);
     },