Title: [112218] trunk/Source/WebCore
Revision
112218
Author
[email protected]
Date
2012-03-27 00:48:09 -0700 (Tue, 27 Mar 2012)

Log Message

[V8][Performance] Optimize createTextNode(), createElement(), cloneNode(), etc
https://bugs.webkit.org/show_bug.cgi?id=82201

Reviewed by Adam Barth.

This patch improves performance of createTextNode() by 13%, createElement() by 14%,
and cloneNode() by 16%. Similar performance improvement will be observed in
DOM methods that create a new object every time.

Performance test: https://bugs.webkit.org/attachment.cgi?id=133799

The performance test results are as follows. Since the performance of V8's GC is
really unstable, the average of measured times makes no sense in Chromium.
Instead, let us focus on the median. I believe that this performance
improvement has impact on Dromaeo, but we cannot observe the improvement
due to the unsteadiness of V8's GC, as shown below.

Chromium/V8/Linux (without the patch):
createTextNode : median=277ms (mean=460.88ms, min=270ms, max=3381ms)
createElement : median=379ms (mean=637.52ms, min=372ms, max=3022ms)
cloneNode : median=369ms (mean=581.72ms, min=363ms, max=3050ms)
Dromaeo/dom-modify/createElement: 439.17runs/s +-31.60% (<--- pretty noisy)
Dromaeo/dom-modify/createTextNode: 287.71runs/s +-28.39% (<--- pretty noisy)
Dromaeo/dom-modify/cloneNode: 174.62runs/s +-25.68% (<--- pretty noisy)

Chromium/V8/Linux (with the patch):
createTextNode : median=240ms (mean=411.12ms, min=237ms, max=2965ms)
createElement : median=325ms (mean=585.30ms, min=317ms, max=2984ms)
cloneNode : median=310ms (mean=522.48ms, min=302ms, max=2988ms)
Dromaeo/dom-modify/createElement: 507.15runs/s +-36.00% (<--- pretty noisy)
Dromaeo/dom-modify/createTextNode: 251.01runs/s +-6.57%
Dromaeo/dom-modify/cloneNode: 177.85runs/s +-28.74% (<--- pretty noisy)

Chromium/V8/Mac (without the patch):
createTextNode : median=317ms (mean=439.08ms, min=303ms, max=3126ms)
createElement : median=403ms (mean=695.70ms, min=398ms, max=5615ms)
cloneNode : median=384ms (mean=577.96ms, min=372ms, max=5313ms)
Dromaeo/dom-modify/createElement: 493.89runs/s +-28.32% (<--- pretty noisy)
Dromaeo/dom-modify/createTextNode: 279.66runs/s +-1.91%
Dromaeo/dom-modify/cloneNode: 173.06runs/s +-24.41% (<--- pretty noisy)

Chromium/V8/Mac (with the patch):
createTextNode : median=277ms (mean=460.88ms, min=270ms, max=3381ms)
createElement : median=379ms (mean=637.52ms, min=372ms, max=3022ms)
cloneNode : median=369ms (mean=581.72ms, min=363ms, max=3050ms)
Dromaeo/dom-modify/createElement: 510.47runs/s +-28.13% (<--- pretty noisy)
Dromaeo/dom-modify/createTextNode: 215.80runs/s +-20.99% (<--- pretty noisy)
Dromaeo/dom-modify/cloneNode: 174.41runs/s +-24.85% (<--- pretty noisy)

Safari/_javascript_Core/Mac:
createTextNode : median=142ms (mean=141.04ms, min=110ms, max=168ms)
createElement : median=234ms (mean=245.74ms, min=219ms, max=305ms)
cloneNode : median=210ms (mean=213.36ms, min=204ms, max=284ms)
Dromaeo/dom-modify/createElement: 822.49runs/s +-1.69%
Dromaeo/dom-modify/createTextNode: 735.57runs/s +-0.91%
Dromaeo/dom-modify/cloneNode: 135.20runs/s +-4.13%

This patch makes the following two optimizations:

[1] If the currently running context is equal to the context that we are about to enter,
we do not call context->Enter().
[2] We do not create a Local handle of the context until we really need to enter the context.

* bindings/scripts/CodeGeneratorV8.pm:
(GenerateToV8Converters):
* bindings/v8/V8Proxy.cpp:
(WebCore::V8Proxy::persistentContext):
(WebCore):
* bindings/v8/V8Proxy.h:
(V8Proxy):

* WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp: Updated run-bindings-tests results.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (112217 => 112218)


--- trunk/Source/WebCore/ChangeLog	2012-03-27 07:38:47 UTC (rev 112217)
+++ trunk/Source/WebCore/ChangeLog	2012-03-27 07:48:09 UTC (rev 112218)
@@ -1,3 +1,78 @@
+2012-03-27  Kentaro Hara  <[email protected]>
+
+        [V8][Performance] Optimize createTextNode(), createElement(), cloneNode(), etc
+        https://bugs.webkit.org/show_bug.cgi?id=82201
+
+        Reviewed by Adam Barth.
+
+        This patch improves performance of createTextNode() by 13%, createElement() by 14%,
+        and cloneNode() by 16%. Similar performance improvement will be observed in
+        DOM methods that create a new object every time.
+
+        Performance test: https://bugs.webkit.org/attachment.cgi?id=133799
+
+        The performance test results are as follows. Since the performance of V8's GC is
+        really unstable, the average of measured times makes no sense in Chromium.
+        Instead, let us focus on the median. I believe that this performance
+        improvement has impact on Dromaeo, but we cannot observe the improvement
+        due to the unsteadiness of V8's GC, as shown below.
+
+        Chromium/V8/Linux (without the patch):
+        createTextNode : median=277ms (mean=460.88ms, min=270ms, max=3381ms)
+        createElement : median=379ms (mean=637.52ms, min=372ms, max=3022ms)
+        cloneNode : median=369ms (mean=581.72ms, min=363ms, max=3050ms)
+        Dromaeo/dom-modify/createElement: 439.17runs/s +-31.60% (<--- pretty noisy)
+        Dromaeo/dom-modify/createTextNode: 287.71runs/s +-28.39% (<--- pretty noisy)
+        Dromaeo/dom-modify/cloneNode: 174.62runs/s +-25.68% (<--- pretty noisy)
+
+        Chromium/V8/Linux (with the patch):
+        createTextNode : median=240ms (mean=411.12ms, min=237ms, max=2965ms)
+        createElement : median=325ms (mean=585.30ms, min=317ms, max=2984ms)
+        cloneNode : median=310ms (mean=522.48ms, min=302ms, max=2988ms)
+        Dromaeo/dom-modify/createElement: 507.15runs/s +-36.00% (<--- pretty noisy)
+        Dromaeo/dom-modify/createTextNode: 251.01runs/s +-6.57%
+        Dromaeo/dom-modify/cloneNode: 177.85runs/s +-28.74% (<--- pretty noisy)
+
+        Chromium/V8/Mac (without the patch):
+        createTextNode : median=317ms (mean=439.08ms, min=303ms, max=3126ms)
+        createElement : median=403ms (mean=695.70ms, min=398ms, max=5615ms)
+        cloneNode : median=384ms (mean=577.96ms, min=372ms, max=5313ms)
+        Dromaeo/dom-modify/createElement: 493.89runs/s +-28.32% (<--- pretty noisy)
+        Dromaeo/dom-modify/createTextNode: 279.66runs/s +-1.91%
+        Dromaeo/dom-modify/cloneNode: 173.06runs/s +-24.41% (<--- pretty noisy)
+
+        Chromium/V8/Mac (with the patch):
+        createTextNode : median=277ms (mean=460.88ms, min=270ms, max=3381ms)
+        createElement : median=379ms (mean=637.52ms, min=372ms, max=3022ms)
+        cloneNode : median=369ms (mean=581.72ms, min=363ms, max=3050ms)
+        Dromaeo/dom-modify/createElement: 510.47runs/s +-28.13% (<--- pretty noisy)
+        Dromaeo/dom-modify/createTextNode: 215.80runs/s +-20.99% (<--- pretty noisy)
+        Dromaeo/dom-modify/cloneNode: 174.41runs/s +-24.85% (<--- pretty noisy)
+
+        Safari/_javascript_Core/Mac:
+        createTextNode : median=142ms (mean=141.04ms, min=110ms, max=168ms)
+        createElement : median=234ms (mean=245.74ms, min=219ms, max=305ms)
+        cloneNode : median=210ms (mean=213.36ms, min=204ms, max=284ms)
+        Dromaeo/dom-modify/createElement: 822.49runs/s +-1.69%
+        Dromaeo/dom-modify/createTextNode: 735.57runs/s +-0.91%
+        Dromaeo/dom-modify/cloneNode: 135.20runs/s +-4.13%
+
+        This patch makes the following two optimizations:
+
+        [1] If the currently running context is equal to the context that we are about to enter,
+        we do not call context->Enter().
+        [2] We do not create a Local handle of the context until we really need to enter the context.
+
+        * bindings/scripts/CodeGeneratorV8.pm:
+        (GenerateToV8Converters):
+        * bindings/v8/V8Proxy.cpp:
+        (WebCore::V8Proxy::persistentContext):
+        (WebCore):
+        * bindings/v8/V8Proxy.h:
+        (V8Proxy):
+
+        * WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp: Updated run-bindings-tests results.
+
 2012-03-27  Bill Budge  <[email protected]>
 
         cross-origin XMLHttpRequest doesn't work with redirect

Modified: trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm (112217 => 112218)


--- trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm	2012-03-27 07:38:47 UTC (rev 112217)
+++ trunk/Source/WebCore/bindings/scripts/CodeGeneratorV8.pm	2012-03-27 07:48:09 UTC (rev 112218)
@@ -3144,13 +3144,15 @@
     if (IsNodeSubType($dataNode) || IsVisibleAcrossOrigins($dataNode)) {
         push(@implContent, <<END);
 
+    // Enter the node's context and create the wrapper in that context.
     v8::Handle<v8::Context> context;
-    if (proxy)
+    if (proxy && !proxy->matchesCurrentContext()) {
+        // For performance, we enter the context only if the currently running context
+        // is different from the context that we are about to enter.
         context = proxy->context();
-
-    // Enter the node's context and create the wrapper in that context.
-    if (!context.IsEmpty())
-        context->Enter();
+        if (!context.IsEmpty())
+            context->Enter();
+    }
 END
     }
 

Modified: trunk/Source/WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp (112217 => 112218)


--- trunk/Source/WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp	2012-03-27 07:38:47 UTC (rev 112217)
+++ trunk/Source/WebCore/bindings/scripts/test/V8/V8TestActiveDOMObject.cpp	2012-03-27 07:48:09 UTC (rev 112218)
@@ -168,13 +168,15 @@
             proxy->windowShell()->initContextIfNeeded();
     }
 
+    // Enter the node's context and create the wrapper in that context.
     v8::Handle<v8::Context> context;
-    if (proxy)
+    if (proxy && !proxy->matchesCurrentContext()) {
+        // For performance, we enter the context only if the currently running context
+        // is different from the context that we are about to enter.
         context = proxy->context();
-
-    // Enter the node's context and create the wrapper in that context.
-    if (!context.IsEmpty())
-        context->Enter();
+        if (!context.IsEmpty())
+            context->Enter();
+    }
     wrapper = V8DOMWrapper::instantiateV8Object(proxy, &info, impl.get());
     // Exit the node's context if it was entered.
     if (!context.IsEmpty())

Modified: trunk/Source/WebCore/bindings/v8/V8Proxy.cpp (112217 => 112218)


--- trunk/Source/WebCore/bindings/v8/V8Proxy.cpp	2012-03-27 07:38:47 UTC (rev 112217)
+++ trunk/Source/WebCore/bindings/v8/V8Proxy.cpp	2012-03-27 07:48:09 UTC (rev 112218)
@@ -642,6 +642,20 @@
     return v8::Local<v8::Context>::New(windowShell()->context());
 }
 
+bool V8Proxy::matchesCurrentContext()
+{
+    v8::Handle<v8::Context> context;
+    if (V8IsolatedContext* isolatedContext = V8IsolatedContext::getEntered()) {
+        context = isolatedContext->sharedContext()->get();
+        if (m_frame != V8Proxy::retrieveFrame(context))
+            return false;
+    } else {
+        windowShell()->initContextIfNeeded();
+        context = windowShell()->context();
+    }
+    return context == context->GetCurrent();
+}
+
 v8::Local<v8::Context> V8Proxy::mainWorldContext(Frame* frame)
 {
     V8Proxy* proxy = retrieve(frame);

Modified: trunk/Source/WebCore/bindings/v8/V8Proxy.h (112217 => 112218)


--- trunk/Source/WebCore/bindings/v8/V8Proxy.h	2012-03-27 07:38:47 UTC (rev 112217)
+++ trunk/Source/WebCore/bindings/v8/V8Proxy.h	2012-03-27 07:48:09 UTC (rev 112218)
@@ -243,6 +243,7 @@
 
         v8::Local<v8::Context> context();
         v8::Local<v8::Context> mainWorldContext();
+        bool matchesCurrentContext();
 
         // FIXME: This should eventually take DOMWrapperWorld argument!
         V8DOMWindowShell* windowShell() const { return m_windowShell.get(); }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to