top of page

Speeding up Python code with Nim



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

0 comments
bottom of page