50x performance hit vs <canvas>
Perhaps I'm doing something trivially wrong, but with the below code which draws 2000 random rectangles on the canvas, react-art runs at about 5fps on my machine. The comparable code that uses the canvas API directly runs at a smooth 60fps. In fact, it takes until about 100,000 rects to bring the
Most (~70%) of the time seems to be spent in the ReactMultiChild.Mixin._updateChildren method:

Most of the self-time that isn't GC is in ReactElement:

Here's the code:
Test = React.createClass
render: ->
React.createElement 'div',
onMouseMove: => @forceUpdate()
onMouseDown: => @ivl = setInterval (=> @forceUpdate()), 16
onMouseUp: => clearInterval @ivl
React.createElement Surface,
width: 800, height: 800
React.createElement Group,
y: 10, x: 10
for [1..2000]
React.createElement Rectangle, x: Math.random() * 800, y: Math.random() * 800, width: Math.random() * 40, height: Math.random() * 40, fill: 'red'
TestCanvas = React.createClass
render: ->
React.createElement 'canvas',
width: 800 * devicePixelRatio, height: 800 * devicePixelRatio
style: {
width: 800
height: 800
}
onMouseMove: => @paint()
onMouseDown: => @ivl = setInterval @paint, 16
onMouseUp: => clearInterval @ivl
componentDidMount: ->
@paint()
paint: ->
ctx = @getDOMNode().getContext '2d'
ctx.save()
ctx.scale(devicePixelRatio, devicePixelRatio)
ctx.clearRect(0, 0, 800, 800)
ctx.fillStyle = 'red'
for [1..2000]
ctx.fillRect Math.random() * 800, Math.random() * 800, Math.random() * 40, Math.random() * 40
ctx.restore()
What are you using to measure your canvas frame rate?
Chrome devtools fps meter. On Wed, Jul 8, 2015 at 12:14 dmcmillen [email protected] wrote:
What are you using to measure your canvas frame rate?
— Reply to this email directly or view it on GitHub https://github.com/reactjs/react-art/issues/52#issuecomment-119700163.
At the very least, you should be using the production (minified, NODE_ENV=production) version of React.
I'm not sure if this would completely solve your problem, but I see some things that don't look right to me. That ReactMultiChild.Mixin._updateChildren is called from ReactEventListener.dispatchEvent, that's probably because of onMouseMove: => @paint() and onMouseMove: => @forceUpdate(). Mouse move events are firing at a very high rate, what you want to do is save the last event object to a variable, and then only render component with those last mouse move values once per frame. Now I know that react is not using request animation frame by default, you may want to look into https://github.com/petehunt/react-raf-batching.