Python is one of the most popular and accessible programming languages of all time but is far from being the fastest. Many library and framework creators resorted to using C extensions to make their code run faster than native Python. Although that works well enough, for someone un-acquainted with C, it’s a hell on earth to manage garbage collection and memory safety. And that’s where Nim comes in.
What is Nim?
It’s a statically typed, compiled, object-oriented programming language. Nim was created to be a language as fast as C, as expressive as Python, and as extensible as Lisp. Due to its syntax similarity to Python, it’s an amazing choice for an extension language when C isn’t your cup of tea.
Getting started with Nim
To get started with writing Nim code, you first have to install it on your system. To do that, head over to nim-lang.org, download, and then install it.
Once you’re done, let’s write your first lines of Nim code. First, we’ll create our file, I’ll name mine hello.nim , you can name yours whatever you want. Now, we’ll open it with any text editor and write the following:
echo("Hello, world!")
Save and close the file, then open Command Prompt in the file’s location and type:
nim compile hello.nim
And voila! “Hello, World!” should have been printed to the console. That’s the basics on Nim for you, now let’s get into the main focus of this article.
Embedding Nim in Python applications
Nim comes preinstalled with a module called nimpy , and a module called nimporter is available for Python. The latter can be installed using pip install nimporter. Those are the two packages that are going to be essential when working with those languages together.
To demonstrate Nim’s capabilities, we’ll create a simple benchmark comparing the speeds of both languages using a naive function finding the nth number of the Fibonacci Sequence.
Let’s create a folder called Benchmark , with 3 files inside:
main.py — the file we’ll be running
nmath.nim — the file that’ll hold the Nim version of our fib function
pmath.py — the file that’ll hold the Python version of our fib function
First, let’s write our fib function in pmath.py
def fib(n):
if n == 0:
return 0
elif n < 3:
return 1
return fib(n - 1) + fib(n - 2)
Let’s move to nmath.nim . First off, we have to import nimpy like this:
import nimpy
Just like Python, right? Now, for the function itself:
import nimpy
proc fib(n: int): int {.exportpy.} =
if n == 0:
return 0
elif n < 3:
return 1
return fib(n-1) + fib(n-2)
Let’s break this down.
We define a function fib using the proc keyword. We specify the return type as an integer, and Woah! What’s that monstrosity? {.exportpy.} signals Nim that this function is meant to be used in another, Python module. Other than that, everything is exactly the same as in Python.
Benchmarking
In main.py we’re going to create a simple benchmark:
import nimporter
from time import perf_counter
import nmath # Nim imports!
import pmathprint('Measuring Python...')
start_py = perf_counter()
for i in range(0, 40):
print(pmath.fib(i))
end_py = perf_counter()
print('Measuring Nim...')
start_nim = perf_counter()
for i in range(0, 40):
print(nmath.fib(i))
end_nim = perf_counter()
print('---------')
print('Python Elapsed: {:.2f}'.format(end_py - start_py))
print('Nim Elapsed: {:.2f}'.format(end_nim - start_nim))
And that’s it!
The nimporter package resolves Nim imports into regular Python modules to be used just like native ones. Cool right?
To run the code, type the usual python main.py command into Command Prompt and observe!
Python Elapsed: 33.60
Nim Elapsed: 1.05
Summary
And that’s it for the quick rundown of embedding Nim in Python. Nim came out to be about 30x times faster, although keep in mind that differences in speed may vary depending on the task being done.
Source: Medium
The Tech Platform
Comments