It seems likely you're measuring something other than what you intended to measure, like the start-up time of the Python interpreter, time to byte-compile Python source, etc. fib(40) itself runs in 1.1us/loop on this Ryzen 3700X running Debian Buster and Python 3.7.3, excluding start-up costs using timeit:
python3 -mtimeit -s"
def fib(x):
a = 0
b = 1
for i in range(x):
a, b = a+b, a
return a
assert fib(40) == 102334155
" "fib(40)"
Even this takes only 3.5ms on the "task clock", counting all interpreter start-up time, bytecode compilation, etc:
perf stat python -S -c "
def fib(x):
a = 0
b = 1
for i in range(x):
a, b = a+b, a
return a
assert fib(40) == 102334155
"
(oops, that example changed to python2.7; python3.5 is a bit slower at 9ms)
BIPLAN supports only one numeric variable type that is by default int32_t
So, fib(48) will overflow, and probably will return a negative number.
Preferring to give the right answer over giving an answer fast is one of the design decisions Python made.
There also is the unconventional choice to use a global array to store variables, leading to “BIPLAN supports a maximum amount of 116 global variables”. I don’t think changing that to make it growable will affect speed much, though.