Skip to content
This repository has been archived by the owner on Jul 19, 2019. It is now read-only.

50x performance hit vs <canvas> #52

Open
nornagon opened this issue Jul 6, 2015 · 4 comments
Open

50x performance hit vs <canvas> #52

nornagon opened this issue Jul 6, 2015 · 4 comments

Comments

@nornagon
Copy link

nornagon commented Jul 6, 2015

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 implementation down to 5fps.

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:
developer_tools_-_http___localhost_5000_transcriptic_p17rvy7j9dzrw_runs_r17rvydszmnab_admin

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()
@demc
Copy link

demc commented Jul 8, 2015

What are you using to measure your canvas frame rate?

@nornagon
Copy link
Author

nornagon commented Jul 8, 2015

Chrome devtools fps meter.
On Wed, Jul 8, 2015 at 12:14 dmcmillen notifications@github.com wrote:

What are you using to measure your canvas frame rate?


Reply to this email directly or view it on GitHub
#52 (comment).

@sophiebits
Copy link
Member

At the very least, you should be using the production (minified, NODE_ENV=production) version of React.

@pavlelekic
Copy link

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants