These are the results of benchmarks comparing this bc
(at version 2.1.0
) and GNU bc
(at version 1.07.1
).
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
.
Note: some mistakes were made when updating these benchmarks for 2.1.0
. First, I did not update this bc
's version in this file. Second, I ran this bc
after compiling with clang
when the GNU bc
was almost certainly compiled with gcc
. Those mistakes have been fixed.
The command used was:
tests/script.sh bc add.bc 0 1 1 [bc]
For GNU bc
:
Running bc script: add.bc real 2.06 user 1.09 sys 0.96
For this bc
:
Running bc script: add.bc real 0.95 user 0.90 sys 0.05
The command used was:
tests/script.sh bc subtract.bc 0 1 1 [bc]
For GNU bc
:
Running bc script: subtract.bc real 2.08 user 1.13 sys 0.94
For this bc
:
Running bc script: subtract.bc real 0.92 user 0.88 sys 0.04
The command used was:
tests/script.sh bc multiply.bc 0 1 1 [bc]
For GNU bc
:
Running bc script: multiply.bc real 5.54 user 3.72 sys 1.81
For this bc
:
Running bc script: multiply.bc real 2.06 user 2.01 sys 0.05
The command used was:
tests/script.sh bc divide.bc 0 1 1 [bc]
For GNU bc
:
Running bc script: divide.bc real 2.80 user 1.68 sys 1.11
For this bc
:
Running bc script: divide.bc real 1.45 user 1.42 sys 0.02
The command used was:
printf '1234567890^100000; halt\n' | time -p [bc] -lq > /dev/null
For GNU bc
:
real 11.46 user 11.45 sys 0.00
For this bc
:
real 0.75 user 0.75 sys 0.00
This file was downloaded, saved at ../timeconst.bc
and the following patch was applied:
--- tests/bc/scripts/timeconst.bc 2018-09-28 11:32:22.808669000 -0600 +++ ../timeconst.bc 2019-06-07 07:26:36.359913078 -0600 @@ -108,8 +108,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.16 user 14.59 sys 0.56
For this bc
:
real 11.63 user 11.63 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 12.84 user 12.84 sys 0.00
For this bc
:
real 21.20 user 21.20 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 13.80 user 13.80 sys 0.00
For this bc
:
real 14.90 user 14.90 sys 0.00
It seems that my bc
runs while
loops faster than for
loops. I don't know why it does that because both loops are using the same code underneath the hood.
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 this bc
with the recommended optimizations, the results are as follows.
For the first script:
real 9.85 user 9.85 sys 0.00
For the second script:
real 18.04 user 18.04 sys 0.00
For the third script:
real 12.66 user 12.66 sys 0.00
This is more competitive.
In addition, when compiling with the above recommendation, this bc
gets even faster when doing math.
When I ran these benchmarks with my bc
compiled under clang
, it performed much better. I recommend compiling this bc
with clang
.