Bug 1253781 - Better perf with pure render. r=gl
authorJ. Ryan Stinnett <jryans@gmail.com>
Fri, 04 Mar 2016 18:03:34 -0600
changeset 287029 b8e594c21349c24f07bf6a63764f3c1bb9734e46
parent 287028 92fc2f7c1932c2de200fe11c818818836e9fb100
child 287030 7280ed7ecd34d1507624a326bc7e84c5ef451c16
push id18045
push userjryans@gmail.com
push dateMon, 07 Mar 2016 18:31:17 +0000
treeherderfx-team@b8e594c21349 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgl
bugs1253781
milestone47.0a1
Bug 1253781 - Better perf with pure render. r=gl There are few easy wins that greatly improve our perf with React: * Add the PureRenderMixin to pure components that always render the same thing given the same props and state. This implements React's shouldComponentUpdate as a shallow equality check of the props and state, so render() will be skipped if they match the previous values. * Change action dispatch functions so they are only created once instead of on each render(). If an outer component creates new functions for each render() call, then the PureRenderMixin equality check fails for only the new function instances, even though no data has changed. MozReview-Commit-ID: D96X048nEF4
devtools/client/responsive.html/app.js
devtools/client/responsive.html/components/browser.js
devtools/client/responsive.html/components/global-toolbar.js
devtools/client/responsive.html/components/viewport-toolbar.js
devtools/client/responsive.html/components/viewport.js
devtools/client/responsive.html/components/viewports.js
--- a/devtools/client/responsive.html/app.js
+++ b/devtools/client/responsive.html/app.js
@@ -18,36 +18,47 @@ let App = createClass({
   displayName: "App",
 
   propTypes: {
     location: Types.location.isRequired,
     viewports: PropTypes.arrayOf(PropTypes.shape(Types.viewport)).isRequired,
     onExit: PropTypes.func.isRequired,
   },
 
+  onRotateViewport(id) {
+    this.props.dispatch(rotateViewport(id));
+  },
+
+  onResizeViewport(id, width, height) {
+    this.props.dispatch(resizeViewport(id, width, height));
+  },
+
   render() {
     let {
-      dispatch,
       location,
       viewports,
       onExit,
     } = this.props;
 
+    let {
+      onRotateViewport,
+      onResizeViewport,
+    } = this;
+
     return dom.div(
       {
         id: "app",
       },
       GlobalToolbar({
         onExit,
       }),
       Viewports({
         location,
         viewports,
-        onRotateViewport: id => dispatch(rotateViewport(id)),
-        onResizeViewport: (id, width, height) =>
-          dispatch(resizeViewport(id, width, height)),
+        onRotateViewport,
+        onResizeViewport,
       })
     );
   },
 
 });
 
 module.exports = connect(state => state)(App);
--- a/devtools/client/responsive.html/components/browser.js
+++ b/devtools/client/responsive.html/components/browser.js
@@ -1,23 +1,25 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
   require("devtools/client/shared/vendor/react");
 
 const Types = require("../types");
 
 module.exports = createClass({
 
   displayName: "Browser",
 
+  mixins: [ addons.PureRenderMixin ],
+
   propTypes: {
     location: Types.location.isRequired,
     width: Types.viewport.width.isRequired,
     height: Types.viewport.height.isRequired,
     isResizing: PropTypes.bool.isRequired,
   },
 
   render() {
--- a/devtools/client/responsive.html/components/global-toolbar.js
+++ b/devtools/client/responsive.html/components/global-toolbar.js
@@ -1,22 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
 const { getStr } = require("./utils/l10n");
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
   require("devtools/client/shared/vendor/react");
 
 module.exports = createClass({
 
   displayName: "GlobalToolbar",
 
+  mixins: [ addons.PureRenderMixin ],
+
   propTypes: {
     onExit: PropTypes.func.isRequired,
   },
 
   render() {
     let {
       onExit,
     } = this.props;
--- a/devtools/client/responsive.html/components/viewport-toolbar.js
+++ b/devtools/client/responsive.html/components/viewport-toolbar.js
@@ -1,21 +1,23 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-const { DOM: dom, createClass, PropTypes } =
+const { DOM: dom, createClass, PropTypes, addons } =
   require("devtools/client/shared/vendor/react");
 
 module.exports = createClass({
 
   displayName: "ViewportToolbar",
 
+  mixins: [ addons.PureRenderMixin ],
+
   propTypes: {
     onRotateViewport: PropTypes.func.isRequired,
   },
 
   render() {
     let {
       onRotateViewport,
     } = this.props;
--- a/devtools/client/responsive.html/components/viewport.js
+++ b/devtools/client/responsive.html/components/viewport.js
@@ -17,23 +17,44 @@ module.exports = createClass({
 
   propTypes: {
     location: Types.location.isRequired,
     viewport: PropTypes.shape(Types.viewport).isRequired,
     onResizeViewport: PropTypes.func.isRequired,
     onRotateViewport: PropTypes.func.isRequired,
   },
 
+  onResizeViewport(width, height) {
+    let {
+      viewport,
+      onResizeViewport,
+    } = this.props;
+
+    onResizeViewport(viewport.id, width, height);
+  },
+
+  onRotateViewport() {
+    let {
+      viewport,
+      onRotateViewport,
+    } = this.props;
+
+    onRotateViewport(viewport.id);
+  },
+
   render() {
     let {
       location,
       viewport,
-      onResizeViewport,
+    } = this.props;
+
+    let {
       onRotateViewport,
-    } = this.props;
+      onResizeViewport,
+    } = this;
 
     return dom.div(
       {
         className: "viewport",
       },
       ResizableViewport({
         location,
         viewport,
--- a/devtools/client/responsive.html/components/viewports.js
+++ b/devtools/client/responsive.html/components/viewports.js
@@ -33,17 +33,16 @@ module.exports = createClass({
       {
         id: "viewports",
       },
       viewports.map(viewport => {
         return Viewport({
           key: viewport.id,
           location,
           viewport,
-          onResizeViewport: (width, height) =>
-            onResizeViewport(viewport.id, width, height),
-          onRotateViewport: () => onRotateViewport(viewport.id),
+          onResizeViewport,
+          onRotateViewport,
         });
       })
     );
   },
 
 });