| The bm_diff Family |
| ==== |
| |
| This family of python scripts can be incredibly useful for fast iteration over |
| different performance tweaks. The tools allow you to save performance data from |
| a baseline commit, then quickly compare data from your working branch to that |
| baseline data to see if you have made any performance wins. |
| |
| The tools operate with three concrete steps, which can be invoked separately, |
| or all together via the driver script, bm_main.py. This readme will describe |
| the typical workflow for these scripts, then it will include sections on the |
| details of every script for advanced usage. |
| |
| ## Normal Workflow |
| |
| Let's say you are working on a performance optimization for grpc_error. You have |
| made some significant changes and want to see some data. From your branch, run |
| (ensure everything is committed first): |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_main.py -b bm_error -l 5 -d master` |
| |
| This will build the `bm_error` binary on your branch, and then it will checkout |
| master and build it there too. It will then run these benchmarks 5 times each. |
| Lastly it will compute the statistically significant performance differences |
| between the two branches. This should show the nice performance wins your |
| changes have made. |
| |
| If you have already invoked bm_main with `-d master`, you should instead use |
| `-o` for subsequent runs. This allows the script to skip re-building and |
| re-running the unchanged master branch. For example: |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_main.py -b bm_error -l 5 -o` |
| |
| This will only build and run `bm_error` on your branch. It will then compare |
| the output to the saved runs from master. |
| |
| ## Advanced Workflow |
| |
| If you have a deeper knowledge of these scripts, you can use them to do more |
| fine tuned benchmark comparisons. For example, you could build, run, and save |
| the benchmark output from two different base branches. Then you could diff both |
| of these baselines against your working branch to see how the different metrics |
| change. The rest of this doc goes over the details of what each of the |
| individual modules accomplishes. |
| |
| ## bm_build.py |
| |
| This scrips builds the benchmarks. It takes in a name parameter, and will |
| store the binaries based on that. Both `opt` and `counter` configurations |
| will be used. The `opt` is used to get cpu_time and real_time, and the |
| `counters` build is used to track other metrics like allocs, atomic adds, |
| etc etc etc. |
| |
| For example, if you were to invoke (we assume everything is run from the |
| root of the repo): |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_build.py -b bm_error -n baseline` |
| |
| then the microbenchmark binaries will show up under |
| `bm_diff_baseline/{opt,counters}/bm_error` |
| |
| ## bm_run.py |
| |
| This script runs the benchmarks. It takes a name parameter that must match the |
| name that was passed to `bm_build.py`. The script then runs the benchmark |
| multiple times (default is 20, can be toggled via the loops parameter). The |
| output is saved as `<benchmark name>.<config>.<name>.<loop idx>.json` |
| |
| For example, if you were to run: |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_run.py -b bm_error -b baseline -l 5` |
| |
| Then an example output file would be `bm_error.opt.baseline.0.json` |
| |
| ## bm_diff.py |
| |
| This script takes in the output from two benchmark runs, computes the diff |
| between them, and prints any significant improvements or regressions. It takes |
| in two name parameters, old and new. These must have previously been built and |
| run. |
| |
| For example, assuming you had already built and run a 'baseline' microbenchmark |
| from master, and then you also built and ran a 'current' microbenchmark from |
| the branch you were working on, you could invoke: |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_diff.py -b bm_error -o baseline -n current -l 5` |
| |
| This would output the percent difference between your branch and master. |
| |
| ## bm_main.py |
| |
| This is the driver script. It uses the previous three modules and does |
| everything for you. You pass in the benchmarks to be run, the number of loops, |
| number of CPUs to use, and the commit to compare to. Then the script will: |
| * Build the benchmarks at head, then checkout the branch to compare to and |
| build the benchmarks there |
| * Run both sets of microbenchmarks |
| * Run bm_diff.py to compare the two, outputs the difference. |
| |
| For example, one might run: |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_main.py -b bm_error -l 5 -d master` |
| |
| This would compare the current branch's error benchmarks to master. |
| |
| This script is invoked by our infrastructure on every PR to protect against |
| regressions and demonstrate performance wins. |
| |
| However, if you are iterating over different performance tweaks quickly, it is |
| unnecessary to build and run the baseline commit every time. That is why we |
| provide a different flag in case you are sure that the baseline benchmark has |
| already been built and run. In that case use the --old flag to pass in the name |
| of the baseline. This will only build and run the current branch. For example: |
| |
| `tools/profiling/microbenchmarks/bm_diff/bm_main.py -b bm_error -l 5 -o old` |
| |