Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add React benchmarking infrastructure #9465

Merged
merged 71 commits into from
May 9, 2017

Conversation

trueadm
Copy link
Contributor

@trueadm trueadm commented Apr 20, 2017

This is currently a WIP and is not yet complete.

The aim of this PR is to give us better tracking of performance and bundle sizes as we make changes to the React codebase.

To do this, new infrastructure is needed to validate our code changes against pre-defined benchmarks. We can do this using Google's Lighthouse tool, performance markers in the benchmarks, an automated build process. For now the benchmarking script does a build and benchmark run comparing the local React repo and a remote merge base React repo.

The end goal is to have this process run on a CI pipeline which can provide us feedback in builds/PRs so we have constant feedback in regards to performance improvements and regressions.

To test how this works, run:

yarn bench

From the branch on this PR. It should take a few minutes to run and report back the performance metrics of local and remote merge base.

There are still things that need to be finished:

  • Provide a better visual output of results when yarn bench is run
  • Add bundle size comparison checks and remove the existing code for showing branches from the Rollup build process (it will become redundant with this feature)
  • Add more benchmarks other than the functional-components benchmark
  • Add bootstrapped sampled data over results to help show confidence in figures
  • Add additional CLI options to better refine bench runs

@gaearon gaearon changed the title [WIp} Adds React benchmarking infrastructure [WIP] Adds React benchmarking infrastructure Apr 20, 2017
@gaearon gaearon changed the title [WIP] Adds React benchmarking infrastructure Adds React benchmarking infrastructure May 5, 2017
@gaearon gaearon changed the title Adds React benchmarking infrastructure Add React benchmarking infrastructure May 5, 2017
@trueadm
Copy link
Contributor Author

trueadm commented May 5, 2017

@spicyj can you do one more pass on this review before I merge please?

@sophiebits
Copy link
Collaborator

Sure. Anything in particular you'd like me to focus on?

@trueadm
Copy link
Contributor Author

trueadm commented May 5, 2017

@spicyj I added a README.md and commented on the commands possible along with some tweaks to the benchmarks. I feel that this is in good shape to merge now – the variance we're seeing is as good as I feel I can get it at this point. If you can see anything I might have missed, please let me know.

@gaearon
Copy link
Collaborator

gaearon commented May 5, 2017

(I’m going to look at this now too.)

.eslintignore Outdated
@@ -13,6 +13,7 @@ fixtures/
# Ignore built files.
build/
coverage/
scripts/bench/bench-*.js
scripts/bench/benchmarks/**/*.js
scripts/old-bench/bench-*.js
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like this can be removed.

.flowconfig Outdated
@@ -4,6 +4,8 @@
<PROJECT_ROOT>/build/.*
<PROJECT_ROOT>/scripts/.*
<PROJECT_ROOT>/.*/node_modules/y18n/.*
<PROJECT_ROOT>/node_modules/chrome-devtools-frontend/.*
<PROJECT_ROOT>/node_modules/devtools-timeline-model/*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this end with .*?

circle.yml Outdated
@@ -2,7 +2,7 @@
machine:
timezone: America/Los_Angeles
node:
version: 6
version: 7
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we change this? We're not running benches on CI yet, are we?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node 7 should be faster than Node 6. Not a big deal though.

@@ -0,0 +1,7 @@
/**
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we avoid checking in built copies of React? People will attempt to edit or download them.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point


You'll need two folders to compare, each of them containing `react.min.js` and `react-dom-server.min.js`. You can run `npm run build` at the repo root to get a `build` folder with these files.
```bash
# will comapre local repo vs remote merge base repo (default run)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: compare (here and below).
What does "(default run)" mean?

package.json Outdated
@@ -60,16 +60,22 @@
"git-branch": "^0.3.0",
"glob": "^6.0.4",
"glob-stream": "^6.1.0",
"google-closure-compiler-js": "^20170409.0.0",
Copy link
Collaborator

@gaearon gaearon May 5, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it used currently, or was it added for future experimentation? If not used let's remove it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed, was used for static-www build

async function runRemoteBenchmarks(showResults) {
console.log(
chalk.white.bold('Running benchmarks for ')
+ chalk.yellow.bold('Remote (Merge Base)')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it would be helpful to have a commit hash here?
Or maybe even print a GitHub link to commit below.

@gaearon
Copy link
Collaborator

gaearon commented May 5, 2017

Can we avoid the scripts/bench/build/build name? I get confused by the double build and also I'm not sure which build it is. As a comparison, remote-repo is clear to me.

@trueadm
Copy link
Contributor Author

trueadm commented May 5, 2017

@gaearon I changed the path last week to be scripts/bench/remote-repo already :)

On a side note: all the feedback above has been addressed now!

@gaearon
Copy link
Collaborator

gaearon commented May 5, 2017

Ah, I got it now. I just had it from previous version.


For example, if you want to compare a stable verion against master, you can create folders called `build-stable` and `build-master` and use the benchmark scripts like this:
# will comapre local repo vs remote merge base repo
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: type here too

## Running one
One thing you can do with them is benchmark initial render time for a realistic hierarchy:
# runs benchmarks with Chrome in headless mode
yarn bench -- --headless
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it better? Should it be the default? When would you want to use it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me, the results weren't as effective by default. Headless runs everything much faster (it seems) so it was hard to get good feedback and it seems like it's still a new feature. We can revisit adding this by default in the future.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do they recommend to use it for perf testing?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had no official say-so for perf testing. I'll chase someone to get some feedback on using it before enabling it by default.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meaning the variance was higher?

Copy link
Contributor Author

@trueadm trueadm May 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The variance was all over the place in some runs and better in others. It was too unreliable and no one could tell me as why this is currently the case with headless mode.


You can name folders any way you like, this was just an example.
# same as "yarn build"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably "yarn bench"?

$ ./measure.py build-stable stable.txt build-master master.txt
$ ./analyze.py stable.txt master.txt
```
# will only build and run local repo against benchmarks
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't fully understand what these two commands do. (--local and --remote)
If I run --local will it not benchmark remote at all? Or will it just skip the build for remote?

If it doesn't run remote, how would I interpret the benchmark? Does it mean I'll only get absolute numbers as there's nothing to compare to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's only for absolute values

const mime = require('mime');

const options = {
// key: readFileSync(join(__dirname, 'certs', 'facebook-www.key')),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we delete this?

}

function addBundleSizeComparions(table, localResults, remoteMasterResults) {
const bunldesRowHeader = [chalk.white.bold('Bundles')];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: bunldes

Copy link
Collaborator

@gaearon gaearon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran this a few times, and it behaves mostly as I would expect. Seems like it's important not to switch the active process while the bench is running (e.g. brining Chromium into foreground during one run but not the other significantly skews it).

I did not review the statistical stuff as I trust @spicyj with this. I did not review in detail how you call Lighthouse since you have way more knowledge about this.

I'm approving but please make the instructions for different options clearer. As in "when would I want to run this".

Also please remove the remaining built react files from the repo (there's still a few being added in this PR).

@gaearon
Copy link
Collaborator

gaearon commented May 5, 2017

One additional nit is I'd like this to be tweaked:

├───────────────────────────────────────────────────────┼─────────────────────┼────────────────────────┼───────────────────┤
│ Load React                                            │ 394.51 ms +- 1.10   │ 280.76 ms +- 0.62      │ -28.8 % +- 0.3 %  │
├───────────────────────────────────────────────────────┼─────────────────────┼────────────────────────┼───────────────────┤
│ Load ReactDOM                                         │ 1081.16 ms +- 10.86 │ 1152.09 ms +- 1.48     │ +6.6 % +- 1.1 %   │

Note how in this example one of them improved and the other regressed, but it's not clear what the cumulative effect is. It would help to have a Load React + ReactDOM (Total).

@trueadm trueadm merged commit a7d8ebd into facebook:master May 9, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants