Fix performance issue

When the root node was collapsed, it also was selected due to the click event.
The sidebar was updated every time a new message was receivend,
effectivly inhibiting the "render the tree if you got nothing else to do" optimization to render anything at all.

Fixes #7
This commit is contained in:
Thomas Nordquist
2019-01-14 10:45:15 +01:00
parent bd3b81273d
commit 2268175a38
4 changed files with 19 additions and 14 deletions

View File

@@ -9,6 +9,8 @@ import Paper from '@material-ui/core/Paper'
import Popper from '@material-ui/core/Popper' import Popper from '@material-ui/core/Popper'
import ValueRenderer from './ValueRenderer' import ValueRenderer from './ValueRenderer'
const throttle = require('lodash.throttle')
interface Props { interface Props {
node?: q.TreeNode node?: q.TreeNode
theme: Theme theme: Theme
@@ -26,9 +28,9 @@ class MessageHistory extends React.Component<Props, State> {
this.state = { } this.state = { }
} }
private updateNode = () => { private updateNode = throttle(() => {
this.setState(this.state) this.setState(this.state)
} }, 300)
public componentWillReceiveProps(nextProps: Props) { public componentWillReceiveProps(nextProps: Props) {
this.props.node && this.props.node.onMessage.unsubscribe(this.updateNode) this.props.node && this.props.node.onMessage.unsubscribe(this.updateNode)

View File

@@ -1,5 +1,6 @@
import * as React from 'react' import * as React from 'react'
import * as q from '../../../../backend/src/Model' import * as q from '../../../../backend/src/Model'
import { Typography } from '@material-ui/core' import { Typography } from '@material-ui/core'
interface Props { interface Props {

View File

@@ -22,6 +22,8 @@ import Topic from './Topic'
import ValueRenderer from './ValueRenderer' import ValueRenderer from './ValueRenderer'
import { connect } from 'react-redux' import { connect } from 'react-redux'
const throttle = require('lodash.throttle')
interface Props { interface Props {
node?: q.TreeNode, node?: q.TreeNode,
classes: any, classes: any,
@@ -36,9 +38,9 @@ interface State {
class Sidebar extends React.Component<Props, State> { class Sidebar extends React.Component<Props, State> {
private valueRef: any = React.createRef<HTMLDivElement>() private valueRef: any = React.createRef<HTMLDivElement>()
private updateNode = () => { private updateNode = throttle(() => {
this.setState(this.state) this.setState(this.state)
} }, 300)
constructor(props: any) { constructor(props: any) {
super(props) super(props)

View File

@@ -9,12 +9,11 @@ import { connect } from 'react-redux'
const MovingAverage = require('moving-average') const MovingAverage = require('moving-average')
declare const performance: any
declare const window: any
const timeInterval = 10 * 1000 const timeInterval = 10 * 1000
const average = MovingAverage(timeInterval) const average = MovingAverage(timeInterval)
declare var window: any
interface Props { interface Props {
autoExpandLimit: number autoExpandLimit: number
didSelectNode?: (node: q.TreeNode) => void didSelectNode?: (node: q.TreeNode) => void
@@ -44,22 +43,26 @@ class Tree extends React.Component<Props, TreeState> {
return time return time
} }
private performanceCallback = (ms: number) => {
average.push(Date.now(), ms)
}
public throttledStateUpdate(state: any) { public throttledStateUpdate(state: any) {
if (this.updateTimer) { if (this.updateTimer) {
return return
} }
const expectedRenderTime = average.forecast() const expectedRenderTime = average.forecast()
const updateInterval = Math.max(expectedRenderTime * 20, 300) const updateInterval = Math.max(expectedRenderTime * 7, 300)
const timeUntilNextUpdate = updateInterval - (performance.now() - this.lastUpdate) const timeUntilNextUpdate = updateInterval - (performance.now() - this.lastUpdate)
this.updateTimer = setTimeout(() => { this.updateTimer = setTimeout(() => {
window.requestAnimationFrame(() => { window.requestIdleCallback(() => {
this.lastUpdate = performance.now() this.lastUpdate = performance.now()
this.updateTimer && clearTimeout(this.updateTimer) this.updateTimer && clearTimeout(this.updateTimer)
this.updateTimer = undefined this.updateTimer = undefined
this.setState(state) this.setState(state)
}) }, { timeout: 500 })
}, Math.max(0, timeUntilNextUpdate)) }, Math.max(0, timeUntilNextUpdate))
} }
@@ -104,10 +107,6 @@ class Tree extends React.Component<Props, TreeState> {
cursor: 'default', cursor: 'default',
} }
const performanceCallback = (ms: number) => {
average.push(Date.now(), ms)
}
return ( return (
<div style={style}> <div style={style}>
<TreeNode <TreeNode
@@ -120,6 +119,7 @@ class Tree extends React.Component<Props, TreeState> {
collapsed={false} collapsed={false}
key="rootNode" key="rootNode"
lastUpdate={this.state.tree.lastUpdate} lastUpdate={this.state.tree.lastUpdate}
performanceCallback={this.performanceCallback}
/> />
</div> </div>
) )