Is Python Slow? Use Cases and Comparison to Other Languages

Marcin Żołądkiewicz

Slow

Python is well known to be one of the most useful programming languages. You can do almost anything with it — from web/desktop applications, through image processing, to data science and machine learning. It’s like a Swiss army knife for programmers. However, some developers continue to claim that although Python is easy to learn because of its syntax and being a dynamically typed language, it is simply too slow. "Why is Python so slow?," they ask.

I have been programming in Python for over five years now and in the early days of my time with the language, I had similar doubts, but my experience since has proven these concerns to be unfounded. So, I will try to lay out the truth for you as objectively as I possibly can.

Cta image

What Does It Mean that A Language Is Slow?

Why is Python so slow? It's not simple.

Every programming language can be described in a variety of ways. In terms of language effectiveness, two categories come to mind—code delivery speed and performance.

In which of these could we say that Python is slow? Let’s check!

Code Delivery Speed

In many cases, the delivery speed of a language is its most important parameter. It tells us when we can potentially expect delivery of a finished app and allows us to design proper release timing.

Because Python can be used at almost every stage of a given project (we can use it to create the application, test it, and prepare the project environment), one skilled developer could take care of the whole delivery process from start to finish.

Because of the higher development speed, using Python might actually translate into a smaller number of developers required for a project, bringing the additional benefit of reducing project costs.

But dealing with projects is more than just creating brand new applications—it also means continued maintenance and support. Code written in Python is very crisp and easy to read thanks to its syntax and PEP8 standard.

Just take a look at this sample quicksort implementation written in different languages. The examples are taken from here.

Java

 
import java.util.*;

import java.util.function.*;

import java.util.stream.Stream;

 

import static com.google.common.collect.Iterables.concat;

import static java.lang.System.out;

import static java.util.Arrays.asList;

import static java.util.stream.Collectors.partitioningBy;

import static org.assertj.core.util.Lists.newArrayList;

 

public  List qs(List l, BiPredicate<t, t=""> isLower) {

if (l.size() < 2) {

return l;

} else {

T x = l.get(0);

Stream xs = l.stream().skip(1);

Map<boolean, list<t="">> part = xs.collect(partitioningBy(item -> isLower.test(item, x)));

List lowers = part.get(true);

List highers = part.get(false);

 

return newArrayList(concat(qs(lowers, isLower), asList(x), qs(highers, isLower)));

}

}

</boolean,></t,>

Python


def qsort(L):

if L == []: return []

return qsort([x for x in L[1:] if x< L[0]]) + L[0:1] + \

qsort([x for x in L[1:] if x>=L[0]])

C++


#include <functional>
#include <algorithm>
#include <iterator>

template< typename BidirectionalIterator, typename Compare >
void quick_sort( BidirectionalIterator first, BidirectionalIterator last, Compare cmp ) {
    if( first != last ) {
        BidirectionalIterator left  = first;
        BidirectionalIterator right = last;
        BidirectionalIterator pivot = left++;

        while( left != right ) {
            if( cmp( *left, *pivot ) ) {
                ++left;
            } else {
                while( (left != right) && cmp( *pivot, *right ) )
                    --right;
                std::iter_swap( left, right );
            }
        }

        --left;
        std::iter_swap( pivot, left );

        quick_sort( first, left, cmp );
        quick_sort( right, last, cmp );
    }
}

template< typename BidirectionalIterator >
    inline void quick_sort( BidirectionalIterator first, BidirectionalIterator last ) {
        quick_sort( first, last,
                std::less_equal< typename std::iterator_traits< BidirectionalIterator >::value_type >()
                );
    }
    

Go



func QSort(data []int) {
    if len(data) < 2 {
        return
    }
    pivot := data[0]
    l, r := 1, len(data) - 1
    for l <= r {
        for l <= r && data[l] <= pivot {
            l ++
        }
        for r >= l && data[r] >= pivot {
            r --
        }
        if l < r {
            data[l], data[r] = data[r], data[l]
        }
    }
 
    if r > 0 {
        data[0], data[r] = data[r], data[0]
        qsort(data[0:r])
    }
    qsort(data[l:])
}

And now let's take a statistical approach.

graph showing median hours to solve a problem

How long does it take to write a string-processing application in various languages? (Prechelt and Garret

As you can see in the graph above, there can be no doubt that Python absolutely outperforms other languages in terms of delivery speed.

According to the data, Python equals Perl in delivery speed, and then outmatches the competition. The approximate median time for Python (3 hours) is less than half that of C (8 hours), and less than three times that of Java (10 hours) and C++ (11 hours).

Python Performance

This parameter tells us how quickly a programming language can deal with a problem. As of this writing, the languages that shine brightest in that respect are C and C++. And indeed, it makes sense to use them in some cases, such as creating computer games, compilers, or whenever there’s a need for a large volume of calculations and good memory control.

But what about other cases? What about Web development or—to name a few recent hot topics —data science, image preprocessing, and machine learning? Can we say that Python is slow in these use cases?

Python performance in data science, image preprocessing, and machine learning

Every single use case mentioned above requires a huge amount of calculations. Nevertheless, Python continues to be the most popular language used in machine learning or image processing. Now let me explain why.

Back in the opening paragraph, I mentioned that Python is often accused of being slow, which is only partially true. I don’t want to insult anyone, but the truth is that most of the time this argument is used by beginners.

If the project uses machine learning, more often than not, it will need to draw on some external libraries, such as SciKit and TensorFlow, both of which are available for Python.

Because those libraries are written in C++, when using them in Python scripts, we’re using C++ in the background. That makes the development process fast because of Python, and makes our script as fast as those written in C++. The same is true for image preprocessing (OpenCV library).

You can clearly see that in this case, too, Python serves as a kind of a “wrapper” for C++.

Web development

Python is great for creating Web applications. And when starting your Web development journey, it’s not exactly easy to choose your first Web framework and when it comes to Python, the selection on offer is rather broad: we have Django, Flask, TurboGears, and many others.

Django is by far the most popular Python Web framework, and it powers some of the biggest apps and websites you know, including Spotify, Washington Post, YouTube (although it was initially built with PHP), and BitBucket.

Read more: Flask vs Django – Which Python Framework To Choose and When?

Were Python so bad as some people claim, those projects probably wouldn’t have been as successful as they have. Furthermore, assuming that the performance of a Web application depends only on the code and chosen language is a huge mistake. The world is actually much more complicated than that.

Application performance is driven by a number of factors and properly written and optimized code is just one of them. Overall performance is also limited by bottlenecks. What are they? Well, the name is rather self-explanatory. Fluid velocity is limited by the bottlenecks it encounters. You are only as good as your weakest link, and it’s really rare for code to be the bottleneck.

The thing that separates a good developer from a bad developer is that good ones know when to optimize code. Nick Humrich, Python Guru and former Amazon engineer, explains that sentiment quite well:

If your optimizations aren’t touching the bottleneck, you’re wasting your time and not fixing the real issue. You won't get any serious improvements until you optimize the bottleneck (…) Optimizing code before you measure and determine where the bottleneck is, is known as “premature optimization". - Nick Humrich 

If you still think that optimization is the most important thing in order to boost the speed of the app, maybe someone like Donald Knuth, the author of The Art of Computer Programming, will convince you:

We should forget about small efficiencies, say about 97% of the time: premature optimization is the root of all evil. Yet we should not pass up our opportunities in that critical 3%. - Donald Knuth 

Spending countless hours improving the code just for the sake of making it a couple of nanoseconds faster doesn’t make sense, especially from the client’s perspective.

Conclusion

Is Python slow? Although native Python code may seem to have a high execution time, especially when we look at the benchmarks, when it comes to commercial use, the speed it offers is more than satisfactory for most applications.

What makes Python so powerful? Primarily its top-shelf development speed and its variety of uses. Additionally, you’d be hard-pressed to find a programming language that makes developing applications easier and more pleasant than Python.

Cta image
Marcin Żołądkiewicz avatar
Marcin Żołądkiewicz
Python Developer