Merge pull request #2795 from weaveworks/improve-firefox-performance

Improve Firefox performance
This commit is contained in:
Filip Barl
2017-08-08 15:36:10 +01:00
committed by GitHub
9 changed files with 45 additions and 28 deletions

View File

@@ -2,7 +2,7 @@ import React from 'react';
import { Motion, spring } from 'react-motion';
import { Map as makeMap } from 'immutable';
import { line, curveBasis } from 'd3-shape';
import { each, omit, times, constant } from 'lodash';
import { each, times, constant } from 'lodash';
import { NODES_SPRING_ANIMATION_CONFIG } from '../constants/animation';
import { NODE_BASE_SIZE, EDGE_WAYPOINTS_CAP } from '../constants/styles';
@@ -70,8 +70,7 @@ export default class EdgeContainer extends React.PureComponent {
}
render() {
const { isAnimated, waypoints } = this.props;
const forwardedProps = omit(this.props, 'isAnimated', 'waypoints', 'scale');
const { isAnimated, waypoints, scale, ...forwardedProps } = this.props;
if (!isAnimated) {
return transformedEdge(forwardedProps, waypoints.toJS(), this.state.thickness);

View File

@@ -14,9 +14,9 @@ class Edge extends React.Component {
}
render() {
const { id, path, highlighted, blurred, focused, thickness, source, target } = this.props;
const { id, path, highlighted, focused, thickness, source, target } = this.props;
const shouldRenderMarker = (focused || highlighted) && (source !== target);
const className = classNames('edge', { highlighted, blurred });
const className = classNames('edge', { highlighted });
return (
<g

View File

@@ -1,29 +1,25 @@
import React from 'react';
import { omit } from 'lodash';
import { Motion, spring } from 'react-motion';
import { NODES_SPRING_ANIMATION_CONFIG } from '../constants/animation';
import Node from './node';
const transformedNode = (otherProps, { x, y, k, opacity }) => (
const transformedNode = (otherProps, { x, y, k }) => (
// NOTE: Controlling blurring and transform from here seems to re-render
// faster than adding a CSS class and controlling it from there.
<g transform={`translate(${x},${y}) scale(${k})`} style={{opacity}}>
<g transform={`translate(${x},${y}) scale(${k})`}>
<Node {...otherProps} />
</g>
);
export default class NodeContainer extends React.PureComponent {
render() {
const { dx, dy, isAnimated, scale, blurred, contrastMode } = this.props;
const nodeBlurOpacity = contrastMode ? 0.6 : 0.25;
const forwardedProps = omit(this.props, 'dx', 'dy', 'isAnimated', 'scale', 'blurred');
const opacity = blurred ? nodeBlurOpacity : 1;
const { dx, dy, isAnimated, scale, ...forwardedProps } = this.props;
if (!isAnimated) {
// Show static node for optimized rendering
return transformedNode(forwardedProps, { x: dx, y: dy, k: scale, opacity });
return transformedNode(forwardedProps, { x: dx, y: dy, k: scale });
}
return (
@@ -33,7 +29,6 @@ export default class NodeContainer extends React.PureComponent {
x: spring(dx, NODES_SPRING_ANIMATION_CONFIG),
y: spring(dy, NODES_SPRING_ANIMATION_CONFIG),
k: spring(scale, NODES_SPRING_ANIMATION_CONFIG),
opacity: spring(opacity, NODES_SPRING_ANIMATION_CONFIG),
}}>
{interpolated => transformedNode(forwardedProps, interpolated)}
</Motion>

View File

@@ -1,6 +1,7 @@
import React from 'react';
import classNames from 'classnames';
import { connect } from 'react-redux';
import { Map as makeMap, List as makeList } from 'immutable';
import { fromJS, Map as makeMap, List as makeList } from 'immutable';
import NodeContainer from './node-container';
import EdgeContainer from './edge-container';
@@ -152,7 +153,6 @@ class NodesChartElements extends React.Component {
matches={node.get('matches')}
networks={node.get('networks')}
metric={node.get('metric')}
blurred={node.get('blurred')}
focused={node.get('focused')}
highlighted={node.get('highlighted')}
shape={node.get('shape')}
@@ -183,14 +183,30 @@ class NodesChartElements extends React.Component {
waypoints={edge.get('points')}
highlighted={edge.get('highlighted')}
focused={edge.get('focused')}
blurred={edge.get('blurred')}
scale={edge.get('scale')}
isAnimated={isAnimated}
/>
);
}
renderOverlay(element) {
// NOTE: This piece of code is a bit hacky - as we can't set the absolute coords for the
// SVG element, we set the zoom level high enough that we're sure it covers the screen.
const className = classNames('nodes-chart-overlay', { active: element.get('isActive') });
const scale = (this.props.selectedScale || 1) * 100000;
return (
<rect
className={className} key="nodes-chart-overlay"
transform={`scale(${scale})`} fill="#fff"
x={-1} y={-1} width={2} height={2}
/>
);
}
renderElement(element) {
if (element.get('isOverlay')) {
return this.renderOverlay(element);
}
// This heuristics is not ideal but it works.
return element.get('points') ? this.renderEdge(element) : this.renderNode(element);
}
@@ -220,6 +236,7 @@ class NodesChartElements extends React.Component {
const orderedElements = makeList([
edges.get(BLURRED_EDGES_LAYER, makeList()),
nodes.get(BLURRED_NODES_LAYER, makeList()),
fromJS([{ isOverlay: true, isActive: !!nodes.get(BLURRED_NODES_LAYER) }]),
edges.get(NORMAL_EDGES_LAYER, makeList()),
nodes.get(NORMAL_NODES_LAYER, makeList()),
edges.get(HIGHLIGHTED_EDGES_LAYER, makeList()),

View File

@@ -1,3 +1,3 @@
export const NODES_SPRING_ANIMATION_CONFIG = { stiffness: 80, damping: 20, precision: 0.1 };
export const NODES_SPRING_ANIMATION_CONFIG = { stiffness: 200, damping: 25, precision: 1 };
export const NODES_SPRING_FAST_ANIMATION_CONFIG = { stiffness: 800, damping: 50, precision: 1 };

View File

@@ -46,7 +46,7 @@ export const graphExceedsComplexityThreshSelector = createSelector(
state => state.getIn(['currentTopology', 'stats', 'node_count']) || 0,
state => state.getIn(['currentTopology', 'stats', 'edge_count']) || 0,
],
(nodeCount, edgeCount) => (nodeCount + (2 * edgeCount)) > 1000
(nodeCount, edgeCount) => (nodeCount + (2 * edgeCount)) > 500
);
// Options for current topology, sub-topologies share options with parent

View File

@@ -411,6 +411,15 @@
}
.nodes-chart-overlay {
pointer-events: none;
opacity: 0;
&.active {
opacity: $node-elements-in-background-opacity;
}
}
.nodes-chart, .nodes-resources {
&-error, &-loading {
@@ -438,7 +447,8 @@
li { padding-top: 5px; }
}
&-loading &-error-icon-container {
// Make watermarks blink only if actually shown (otherwise the FF performance decreses weirdly).
&-loading:not(.hide) &-error-icon-container {
@extend .blinkable;
}
@@ -468,7 +478,6 @@
}
.nodes-chart-elements .node {
transition: opacity .2s $base-ease;
text-align: center;
.node-label {
@@ -562,12 +571,6 @@
}
.edge {
transition: opacity .5s $base-ease;
&.blurred {
opacity: $edge-opacity-blurred;
}
.link {
fill: none;
stroke: $edge-color;
@@ -628,7 +631,6 @@
fill: none;
stroke-opacity: 1;
stroke-width: $node-border-stroke-width;
transition: stroke-opacity 0.333s $base-ease, fill 0.333s $base-ease;
}
&.metrics .border {

View File

@@ -12,6 +12,8 @@ $text-darker-color: darken($text-color, 20%);
$white: white;
$edge-color: black;
$node-elements-in-background-opacity: 0.4;
$node-highlight-shadow-opacity: 0.4;
$node-highlight-stroke-opacity: 0.5;
$node-highlight-stroke-width: 0.16;

View File

@@ -31,6 +31,8 @@ $border-radius: 4px;
$terminal-header-height: 44px;
$node-elements-in-background-opacity: 0.7;
$node-highlight-shadow-opacity: 0.5;
$node-highlight-stroke-opacity: 0.4;
$node-highlight-stroke-width: 0.04;