Can someone explain to me how an interpreter written in Python works ? Has it become bootstrapped at some stage such that the entire interpreter is written in restricted Python which is now translated to C and compiled ?
Yes, actually. Exactly that. They wrote the interpreter in RPython (running over CPython), then wrote an RPython to C compiler in RPython (again on CPython), and then compiled the interpreter using the compiler.
Actually, it's because it contains some performance regressions. To quote their release notes:
"This release is not a typical beta, in a sense the stability is the same or better than 1.9 and can be used in production. It does however include a few performance regressions documented below that don’t allow us to label is as 2.0 final. (It also contains many performance improvements.)"
Numba can't deal with PyPy at the moment, I think. If you're doing lots of Numpy, then see whether PyPy's numpy support works for you, as it will be fastest. If not, then CPython and Numba might be what you want.
Also, you might not need Numpy at all. If you only adopted Numpy for its speed, and not its semantics, maybe you want to move back to simpler pure Python code.
Anecdotally, I moved Bravo from Numpy to array.array when becoming PyPy-compatible, and got speedups of around 60x in my math-intensive sections.
Many people pay for NumPy's creation of temporaries and such. If you have a lot of Numpy code and use a lot of long expressions, it's worth looking at NumExpr, which can give greatly improved performance because it eliminates temporaries and does multicore parallelization.