# Benchmarks These are the results of benchmarks comparing this `bc` (at version `2.7.0`) and GNU `bc` (at version `1.07.1`), both compiled with `clang 9` at `-O2`. Note: all benchmarks were run four times, and the fastest run is the one shown. Also, `[bc]` means whichever `bc` was being run, and the assumed working directory is the root directory of this repository. Also, this `bc` was built at `-O2`. ### Addition The command used was: ``` tests/script.sh bc add.bc 1 0 1 1 [bc] ``` For GNU `bc`: ``` real 2.06 user 1.11 sys 0.95 ``` For this `bc`: ``` real 0.98 user 0.95 sys 0.02 ``` ### Subtraction The command used was: ``` tests/script.sh bc subtract.bc 1 0 1 1 [bc] ``` For GNU `bc`: ``` real 2.04 user 1.04 sys 0.99 ``` For this `bc`: ``` real 1.02 user 1.00 sys 0.01 ``` ### Multiplication The command used was: ``` tests/script.sh bc multiply.bc 1 0 1 1 [bc] ``` For GNU `bc`: ``` real 5.96 user 4.27 sys 1.68 ``` For this `bc`: ``` real 2.15 user 2.11 sys 0.04 ``` ### Division The command used was: ``` tests/script.sh bc divide.bc 1 0 1 1 [bc] ``` For GNU `bc`: ``` real 2.74 user 1.84 sys 0.89 ``` For this `bc`: ``` real 1.49 user 1.48 sys 0.00 ``` ### Power The command used was: ``` printf '1234567890^100000; halt\n' | time -p [bc] -lq > /dev/null ``` For GNU `bc`: ``` real 9.60 user 9.58 sys 0.01 ``` For this `bc`: ``` real 0.67 user 0.66 sys 0.00 ``` ### Scripts [This file][1] was downloaded, saved at `../timeconst.bc` and the following patch was applied: ``` --- ../timeconst.bc 2018-09-28 11:32:22.808669000 -0600 +++ ../timeconst.bc 2019-06-07 07:26:36.359913078 -0600 @@ -110,8 +110,10 @@ print "#endif /* KERNEL_TIMECONST_H */\n" } - halt } -hz = read(); -timeconst(hz) +for (i = 0; i <= 50000; ++i) { + timeconst(i) +} + +halt ``` The command used was: ``` time -p [bc] ../timeconst.bc > /dev/null ``` For GNU `bc`: ``` real 15.26 user 14.60 sys 0.64 ``` For this `bc`: ``` real 11.24 user 11.23 sys 0.00 ``` Because this `bc` is faster when doing math, it might be a better comparison to run a script that is not running any math. As such, I put the following into `../test.bc`: ``` for (i = 0; i < 100000000; ++i) { y = i } i y halt ``` The command used was: ``` time -p [bc] ../test.bc > /dev/null ``` For GNU `bc`: ``` real 14.89 user 14.88 sys 0.00 ``` For this `bc`: ``` real 22.19 user 22.18 sys 0.00 ``` However, when I put the following into `../test2.bc`: ``` i = 0 while (i < 100000000) { ++i } i halt ``` the results were surprising. The command used was: ``` time -p [bc] ../test2.bc > /dev/null ``` For GNU `bc`: ``` real 42.92 user 32.70 sys 10.19 ``` For this `bc`: ``` real 28.50 user 28.44 sys 0.02 ``` I have no idea why the performance of both `bc`'s fell off a cliff, especially the dismal showing by the GNU `bc`. Note that, when running the benchmarks, the optimization used is not the one I recommend, which is `-O3 -flto -march=native`. This `bc` separates its code into modules that, when optimized at link time, removes a lot of the inefficiency that comes from function overhead. This is most keenly felt with one function: `bc_vec_item()`, which should turn into just one instruction (on `x86_64`) when optimized at link time and inlined. There are other functions that matter as well. When compiling both `bc`'s with the recommended optimizations, the results are as follows. For the first script, the command was: ``` time -p [bc] ../timeconst.bc > /dev/null ``` For GNU `bc`: ``` real 14.01 user 13.41 sys 0.59 ``` For this `bc`: ``` real 9.40 user 9.39 sys 0.00 ``` For the second script, the command was: ``` time -p [bc] ../test.bc > /dev/null ``` For GNU `bc`: ``` real 12.58 user 12.58 sys 0.00 ``` For this `bc`: ``` real 17.99 user 17.98 sys 0.00 ``` For the third script, the command was: ``` time -p [bc] ../test2.bc > /dev/null ``` For GNU `bc`: ``` real 39.74 user 27.28 sys 12.44 ``` For this `bc`: ``` real 23.31 user 23.27 sys 0.02 ``` This is more competitive. In addition, when compiling with the above recommendation, this `bc` gets even faster when doing math. ### Recommended Compiler When I ran these benchmarks with my `bc` compiled under `clang` vs. `gcc`, it performed much better under `clang`. I recommend compiling this `bc` with `clang`. [1]: https://github.com/torvalds/linux/blob/master/kernel/time/timeconst.bc