Well, the answer to both is YES.
Python codes can run as fast as C programs.
Python is an interpreted language whereas C is a compiled language. Interpreted codes are always slower than direct machine code because it takes a lot more instructions in order to implement an interpreted instruction than to implement an actual machine instruction. In the case of other languages such as Java and.NET, Java bytecode, and .NET bytecode respectively run faster than Python because a JIT compiler compiles bytecode to native code at runtime. CPython cannot have a JIT compiler because the dynamic nature of Python makes it difficult to write one.
AOT (Ahead of Time) Compiler: The purpose of an AOT compiler is to convert human-readable source code to machine code that the CPU can understand. It will do all the conversion before the code is run which justifies its name too. This compilation process will produce a single native executable. Some languages implemented using AOT are C, C++, Rust, Go.
Python is normally implemented using CPython, its reference C-based implementation. In CPython, GIL (Global Interpreter Lock) is a mutex that protects access to python objects, which prevents multiple threads from executing Python bytecodes simultaneously, Our systems are enhanced with multi-cores but GIL binds the execution only to single-core and leaving rest cores unused, which makes it slower as instructions wait until the previous instruction is executed completely.
This is where PyPy comes into play, it is a Python runtime written in Python, which performs 4.4 times faster than CPython. But there is a catch PyPy too has a GIL, so how it is able to run faster than CPython?
Features of PyPy
- On average PyPy 4.4 times faster than CPython.
- It is Memory efficient.
- It is compatible with almost all third-party python libraries.
- It supports stackless Python.
GIL is important for the execution of Python code if we remove GIL then the reference count variable will not be protected anymore as two threads may vary their values simultaneously and if this happens, it can cause either memory leaks that is never released or, incorrectly releasing the memory while a reference to that object still exists. This can cause crashes or bugs in the code. But along with GIL, PyPy uses JIT compilation and the combination of both makes it much faster than CPython.
PyPy uses a specific type of JIT compiler that is the Tracing JIT compiler. It is built on basic assumptions such as
- programs spend most of their runtime on loops.
- several iterations of the same loop are likely to take similar code paths.
So, basically Tracing JIT generates machine code for only hot code paths of commonly executed loops and interprets the rest of the program.
Visual representation of how PyPy works
RPython is a language that is a restrictive subset of Python and also a framework for implementing interpreters and virtual machines for programming languages, especially for dynamic languages.
Here is a snippet of a python code implemented using CPython and with a run time of 0.4408s.
Now, the same Python code is implemented using PyPy with a run time of 0.0655s
As it is concluded from the above results that PyPy has shown some pretty impressive results which is almost 7 times better than CPython.
“If you want your code to run faster, you should probably just use PyPy.” — Guido van Rossum
- Short-running processes: If a code is too short that the processes won’t even last a few seconds then JIT compiler will not help speed up the execution as the compiler will not have enough time to warm up (means there will be nothing to be traced as the code is to short).
- If all the time is spent in run-time libraries (i.e. in C functions) and not actually running Python Code, then PyPy(JIT compiler) will not be helpful.
Thanks for reading the article. I hope you liked it. I wrote this article best out of my knowledge gained from the documentation and other articles. How do you likePyPy??