React Bailout Perf Test

by wuct

HTML

<script src="https://unpkg.com/eventemitter2/lib/eventemitter2.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-with-addons.min.js"></script>
<script src="https://unpkg.com/[email protected]/dist/react-dom.min.js"></script>

<div id="root"></div>

Babel + JSX

const Dot = ({ cx, cy, r }) => {
  return (
    <circle
      fill="#013f8e"
      cx={cx}
      cy={cy}
      r={r}
    />
  )
}

let ID = 0
const dots = []
for (let i = 0; i < 200; i++) {
  dots.push(React.createElement(Dot, {
    key: ID++,
    cx: Math.ceil(Math.random() * 200),
    cy: Math.ceil(Math.random() * 200),
    r: Math.ceil(Math.random() * 4)
  }))
}

const Dots = () => {
  return (
    <svg viewBox="0 0 200 200">
      {dots}
    </svg>
  )
}


class Parent extends React.Component {
  render() {
    return this.props.children
  }
}


const staticObject = {}
class ParentWithContext extends React.Component {
	static childContextTypes = {}
  getChildContext() {
    return staticObject
  }

  render() {
    return this.props.children
  }
}

const rootEle = document.getElementById('root')


// Start perf test
console.log('Start testing...')

const parent = ReactDOM.render(
  <Parent><Dots /></Parent>, rootEle
)

const NUM_OF_UPDATES = 100

updateInstanceByTimes(parent, NUM_OF_UPDATES)
.then((results) => {
  console.log('With Bailout: ')
  renderResults(results)

  ReactDOM.unmountComponentAtNode(rootEle)

  // Start perf test without bailout
  const parentWithContext= ReactDOM.render(
    <ParentWithContext><Dots /></ParentWithContext>, rootEle
  )

  return updateInstanceByTimes(parentWithContext, NUM_OF_UPDATES)
})
.then((results) => {
  console.log('\n\n')
  console.log('Without Bailout: ')
  renderResults(results)
})


// Test Utils
function updateInstanceByTimes(instance, numOfTimes) {
  return new Promise((resolve) => {
    const results = []
    const updateInstance = () => instance.setState({})

    for (let i = 0; i < numOfTimes; i ++) {
      setTimeout(() => {
        performTask(
          updateInstance,
          result => results.push(result)
        )
      }, i * 50) // update interval
    }

    setTimeout(() => {
      const computed =
      results.reduce((acc, { syncTime, asyncTime, total }) => ({
        syncTime: acc.syncTime +...