{"id":24945,"date":"2019-12-10T12:15:06","date_gmt":"2019-12-10T10:15:06","guid":{"rendered":"https:\/\/www.webcodegeeks.com\/?p=24945"},"modified":"2020-06-23T15:00:36","modified_gmt":"2020-06-23T12:00:36","slug":"how-to-performance-test-python-code-timeit-cprofile-and-more","status":"publish","type":"post","link":"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/","title":{"rendered":"How to Performance Test Python Code: timeit, cProfile, and More"},"content":{"rendered":"\n<p>A lot of the articles in this series take advantage of a feature of Python which allows us to performance test our code, and I finally wanted to get around to explaining how it works and how to use it.<\/p>\n\n\n\n<p><strong>In this article, I cover three main techniques: brute force, <code>timeit<\/code>, and <code>cProfile<\/code>. Personally, I performance test my code with <code>timeit<\/code> because I find it easy to understand, but you may find the various profiling tools helpful. At the end, I\u2019ll ask you to demonstrate your newfound skills with a challenge.<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Problem Introduction<\/h2>\n\n\n\n<p>In order to start talking about how to performance test Python code, we need to define it. At a high level, a performance test is anything that verifies the speed, reliability, scalability, and\/or stability of software. For our purposes, we\u2019ll be looking at speed. In particular, we\u2019ll be looking at different ways to compare the speed of two programs using their relative execution times.<\/p>\n\n\n\n<p>When it comes to performance testing software, the process isn\u2019t always easy or obvious. In particular, there are a lot of pitfalls. For example, performance tests can be influenced by all sorts of factors like background processes (i.e. Spotify, Eclipse, GitHub Desktop, etc.).<\/p>\n\n\n\n<p>In addition, performance tests aren\u2019t always written in a way that fairly accounts for differences in implementation. For example, I might have two snippets of code that have the same behavior except one requires a library to be imported. When I run my test, I don\u2019t want the import to affect the test outcome. As a result, I should write my tests such that I don\u2019t start timing until after the library is imported.<\/p>\n\n\n\n<p>On top of all that, it\u2019s important to take into account different types of scenarios when performance testing. For instance, if we have two similar snippets, one might have better performance for larger data sets. It\u2019s important to test a range of data sets for that reason.<\/p>\n\n\n\n<p>At any rate, the goal of this article is to look at a few different ways we can performance test code in Python. Let\u2019s dig in!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Solutions<\/h2>\n\n\n\n<p>As always, I like to share a few ways to accomplish our task. Of course, if you\u2019ve been following along in this series, you know that I prefer to use the <code>timeit<\/code> library to test snippets. Luckily, there are more options if <code>timeit<\/code> isn\u2019t for you.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Testing by Brute Force<\/h3>\n\n\n\n<p>If you\u2019ve never done any performance testing before, you probably have a gist of how to get started. Typically, we want to take a timestamp before and after we run our code snippet. Then, we can calculate the difference between those times and use the result in our comparison with other snippets.<\/p>\n\n\n\n<p>To do this in Python, we can take advantage of the <code>datetime<\/code> library:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_205904\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<div class=\"line number3 index2 alt2\">3<\/div>\n<div class=\"line number4 index3 alt1\">4<\/div>\n<div class=\"line number5 index4 alt2\">5<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import datetime<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">start_time = datetime.datetime.now()<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"php plain\"># insert code snippet here<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"php plain\">end_time = datetime.datetime.now()<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"php functions\">print<\/code> <code class=\"php plain\">end_time - start_time<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>Of course, this solution leaves a lot to be desired. For example, it only gives us a single data point. Ideally, we\u2019d want to run this a few times to collect an average or at least a lower bound, but this can do in a pinch.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Testing Using the <code>timeit<\/code> Library<\/h3>\n\n\n\n<p>If you\u2019d prefer to have all this timestamp garbage abstracted away with the addition of a few perks, check out the <code>timeit<\/code> library. With the <code>timeit<\/code> library, there are basically two main ways to test code: command line or inline. For our purposes, we\u2019ll take a look at the inline version since that\u2019s what I use for all my testing.<\/p>\n\n\n\n<p>To test code using the <code>timeit<\/code> library, you\u2019ll need to call either the <code>timeit<\/code> function or the <code>repeat<\/code> function. Either one is fine, but the <code>repeat<\/code> function gives a bit more control.<\/p>\n\n\n\n<p>As an example, we\u2019ll test the following code snippet from <a href=\"https:\/\/therenegadecoder.com\/code\/how-to-write-a-list-comprehension-in-python\/\">an earlier article on list comprehensions<\/a>:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_383861\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">[(a, b) <\/code><code class=\"php keyword\">for<\/code> <code class=\"php plain\">a in (1, 3, 5) <\/code><code class=\"php keyword\">for<\/code> <code class=\"php plain\">b in (2, 4, 6)]<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>In this snippet, we\u2019re generating a list of pairs from two tuples. To test it, we could use the <code>timeit<\/code> function:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_548646\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import timeit<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">timeit.timeit(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">)<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>If done correctly, this will run the snippet a million times and return an average execution time as a result. Of course, you\u2019re welcome to change the number of iterations using the <code>number<\/code> keyword argument:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_262091\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import timeit<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">timeit.timeit(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">, number=1000)<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>Naturally, we can take this test a step further by running it multiple times using the repeat function:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_852944\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import timeit<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">timeit.repeat(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">)<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>Instead of returning an execution time, this function returns a list of execution times. In this case, the list will contain three separate execution times. Of course, we don\u2019t need all those times. Instead, we can return the smallest execution time, so we can get an idea of the lower bound of the snippet:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_706655\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import timeit<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">min(timeit.repeat(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">))<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>If you\u2019ve been around a bit, you\u2019ve probably seen this exact syntax in my performance tests in other articles or videos. Of course, I go the extra mile and increase the number of repetitions, but it\u2019s probably overkill. In any case, this is a great way of performance testing Python snippets.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Testing Using the cProfile Library<\/h3>\n\n\n\n<p>Outside of <code>timeit<\/code> and outright brute force, you can always leverage other profiling tools like <a href=\"https:\/\/docs.python.org\/2\/library\/profile.html\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"cProfile (opens in a new tab)\">cProfile<\/a>. Like <code>timeit<\/code>, we can leverage <code>cProfile<\/code> to get runtime statistics from a section of code. Of course, cProfile is quite a bit more detailed. For example, we can run the same list comprehension from above as follows:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_846355\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">import cProfile<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">cProfile.run(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">)<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>As a result, you get a nice report that looks like this:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_831221\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">1<\/div>\n<div class=\"line number2 index1 alt1\">2<\/div>\n<div class=\"line number3 index2 alt2\">3<\/div>\n<div class=\"line number4 index3 alt1\">4<\/div>\n<div class=\"line number5 index4 alt2\">5<\/div>\n<div class=\"line number6 index5 alt1\">6<\/div>\n<div class=\"line number7 index6 alt2\">7<\/div>\n<div class=\"line number8 index7 alt1\">8<\/div>\n<div class=\"line number9 index8 alt2\">9<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\">4 <\/code><code class=\"php keyword\">function<\/code> <code class=\"php plain\">calls in 0.000 seconds<\/code><\/div>\n<div class=\"line number2 index1 alt1\">&nbsp;<\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">Ordered by: standard name<\/code><\/div>\n<div class=\"line number4 index3 alt1\">&nbsp;<\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">ncalls&nbsp; tottime&nbsp; percall&nbsp; cumtime&nbsp; percall filename:lineno(<\/code><code class=\"php keyword\">function<\/code><code class=\"php plain\">)<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">1&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000 &lt;string&gt;:1(&lt;listcomp&gt;)<\/code><\/div>\n<div class=\"line number7 index6 alt2\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">1&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000 &lt;string&gt;:1(&lt;module&gt;)<\/code><\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">1&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000 {built-in method builtins.<\/code><code class=\"php functions\">exec<\/code><code class=\"php plain\">}<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"php spaces\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<\/code><code class=\"php plain\">1&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000&nbsp;&nbsp;&nbsp; 0.000 {method <\/code><code class=\"php string\">'disable'<\/code> <code class=\"php plain\">of <\/code><code class=\"php string\">'_lsprof.Profiler'<\/code> <code class=\"php plain\">objects}<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>Here, we get a nice table which includes a lot of helpful information. Specifically, each row indicates a function that was executed, and each column breaks down a different runtime segment. For example, the <code>&lt;listcomp&gt;<\/code> function was called once (<code>ncalls<\/code>) and took 0.000 seconds (<code>tottime<\/code>) excluding calls to subfunctions. To understand everything else in this table, check out the following breakdown of all six columns:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>ncalls<\/strong>: the number of times that particular function was called\n<ul>\n<li>This number may actually be written as a fraction (e.g. <code>3\/1<\/code>) where the first value is the number of total calls and the second value is the number of primitive calls (not recursive).<\/li>\n<\/ul>\n<\/li><li><strong>tottime<\/strong>: the total amount of time the function spent executing <em>not<\/em> including calls to subfunctions<\/li><li><strong>percall<\/strong> (first): the ratio of tottime to ncalls (i.e. the average amount of time spent in this function excluding subfunctions)<\/li><li><strong>cumtime<\/strong>: the total amount of time the function spent executing including calls to subfunctions<\/li><li><strong>percall<\/strong> (second): the ratio of cumtime to primitive calls (i.e. the average amount of time spent in this function)<\/li><li><strong>filename:lineno(function)<\/strong>: the filename, line number, and function in question<\/li><\/ul>\n\n\n\n<p>As you can see, <code>cProfile<\/code> helps you peek at the internal workings of a code snippet. Of course, you don\u2019t get fine grained timings, so this works better as a compliment to <code>timeit<\/code> rather than a replacement. That said, I think <code>cProfile<\/code> would be excellent for profiling large scripts. That way, you can determine which functions need optimization.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Performance Testing With External Libraries<\/h3>\n\n\n\n<p>While Python provides plenty of ways to benchmark your own code, there are also other libraries we can leverage as well. For instance:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/github.com\/rkern\/line_profiler\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"line_profiler (opens in a new tab)\">line_profiler<\/a><\/li><li><a href=\"https:\/\/pypi.org\/project\/memory-profiler\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"memory_profiler (opens in a new tab)\">memory_profiler<\/a><\/li><li><a href=\"https:\/\/github.com\/mgedmin\/profilehooks\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"profilehooks (opens in a new tab)\">profilehooks<\/a><\/li><\/ul>\n\n\n\n<p>Personally, I\u2019ve never used any of these tools, but I felt I should share them for the sake of completeness. Feel free to follow those links to learn more.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Challenge<\/h2>\n\n\n\n<p>At this point, I\u2019d usually share some performance metrics for each of the solutions above, but that doesn\u2019t really make sense in this context. Instead, it\u2019s time to jump straight to the challenge!<\/p>\n\n\n\n<p>Pick one of the articles in this series and run your own performance metrics on each of the solutions. Since I typically run <code>timeit<\/code>, maybe you could try using one of the other tools from this article. For example, try running cProfile on all <a href=\"https:\/\/www.webcodegeeks.com\/python\/how-to-format-a-string-in-python-interpolation-concatenation-and-more\/\">the string formatting solutions<\/a>.<\/p>\n\n\n\n<p>When you\u2019re done, share the best results in the comments. I\u2019m interested to see what you learn! While you\u2019re at it, check my work. I\u2019d love to know if there are other solutions I\u2019m missing.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">A Little Recap<\/h2>\n\n\n\n<p>As always, I like to finish things out with a list of options. Keep in mind that each solution leverages an example code snippet. In this case, I chose a list comprehension, but you can use any snippet:<\/p>\n\n\n\n<div>\n<div id=\"highlighter_936392\" class=\"syntaxhighlighter  php\">\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td class=\"gutter\">\n<div class=\"line number1 index0 alt2\">01<\/div>\n<div class=\"line number2 index1 alt1\">02<\/div>\n<div class=\"line number3 index2 alt2\">03<\/div>\n<div class=\"line number4 index3 alt1\">04<\/div>\n<div class=\"line number5 index4 alt2\">05<\/div>\n<div class=\"line number6 index5 alt1\">06<\/div>\n<div class=\"line number7 index6 alt2\">07<\/div>\n<div class=\"line number8 index7 alt1\">08<\/div>\n<div class=\"line number9 index8 alt2\">09<\/div>\n<div class=\"line number10 index9 alt1\">10<\/div>\n<div class=\"line number11 index10 alt2\">11<\/div>\n<div class=\"line number12 index11 alt1\">12<\/div>\n<div class=\"line number13 index12 alt2\">13<\/div>\n<div class=\"line number14 index13 alt1\">14<\/div>\n<\/td>\n<td class=\"code\">\n<div class=\"container\">\n<div class=\"line number1 index0 alt2\"><code class=\"php plain\"># Brute force solution<\/code><\/div>\n<div class=\"line number2 index1 alt1\"><code class=\"php plain\">import datetime<\/code><\/div>\n<div class=\"line number3 index2 alt2\"><code class=\"php plain\">start_time = datetime.datetime.now()<\/code><\/div>\n<div class=\"line number4 index3 alt1\"><code class=\"php plain\">[(a, b) <\/code><code class=\"php keyword\">for<\/code> <code class=\"php plain\">a in (1, 3, 5) <\/code><code class=\"php keyword\">for<\/code> <code class=\"php plain\">b in (2, 4, 6)] # example snippet<\/code><\/div>\n<div class=\"line number5 index4 alt2\"><code class=\"php plain\">end_time = datetime.datetime.now()<\/code><\/div>\n<div class=\"line number6 index5 alt1\"><code class=\"php functions\">print<\/code> <code class=\"php plain\">end_time - start_time<\/code><\/div>\n<div class=\"line number7 index6 alt2\">&nbsp;<\/div>\n<div class=\"line number8 index7 alt1\"><code class=\"php plain\"># timeit solution<\/code><\/div>\n<div class=\"line number9 index8 alt2\"><code class=\"php plain\">import timeit<\/code><\/div>\n<div class=\"line number10 index9 alt1\"><code class=\"php plain\">min(timeit.repeat(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">))<\/code><\/div>\n<div class=\"line number11 index10 alt2\">&nbsp;<\/div>\n<div class=\"line number12 index11 alt1\"><code class=\"php plain\"># cProfile solution<\/code><\/div>\n<div class=\"line number13 index12 alt2\"><code class=\"php plain\">import cProfile<\/code><\/div>\n<div class=\"line number14 index13 alt1\"><code class=\"php plain\">cProfile.run(<\/code><code class=\"php string\">\"[(a, b) for a in (1, 3, 5) for b in (2, 4, 6)]\"<\/code><code class=\"php plain\">)<\/code><\/div>\n<\/div>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n\n\n\n<p>Well, that\u2019s all I\u2019ve got! If you have any performance tools of your own to add to the list, feel free to share them in the comments.<\/p>\n\n\n\n<p>In the meantime, I have plenty of How to Python articles you might be interested in:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/therenegadecoder.com\/code\/how-to-sort-a-list-of-strings-in-python\/\">How to Sort a List of Strings in Python<\/a><\/li><li><a href=\"https:\/\/therenegadecoder.com\/code\/how-to-get-the-last-item-of-a-list-in-python\/\">How to Get the Last Item of a List in Python<\/a><\/li><li><a href=\"https:\/\/therenegadecoder.com\/code\/how-to-check-if-a-file-exists-in-python\/\">How to Check If a File Exists in Python<\/a><\/li><\/ul>\n\n\n\n<p>If you prefer visual media, <a href=\"https:\/\/www.youtube.com\/channel\/UCpyoVwOqYRlSAEUPEn7P9hw\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"I have a YouTube channel (opens in a new tab)\">I have a YouTube channel<\/a> which is currently focused on explaining content from this series. Head on over there and throw me a subscribe to help me build up my channel.<\/p>\n\n\n\n<p>Also, feel to leverage some of the following related resources provided by Amazon:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><a href=\"https:\/\/amzn.to\/2pzve86\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\" (opens in a new tab)\">Serious Python: Black-Belt Advice on Deployment, Scalability, Testing, and More<\/a><\/li><li><a href=\"https:\/\/amzn.to\/2qeEwXv\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"Testing Python: Applying Unit Testing, TDD, BDD and Acceptance Testing 1st Edition (opens in a new tab)\">Testing Python: Applying Unit Testing, TDD, BDD and Acceptance Testing 1st Edition<\/a><\/li><\/ul>\n\n\n\n<p>Finally, you can always get the latest The Renegade Coder content sent to your inbox through <a href=\"https:\/\/newsletter.therenegadecoder.com\/\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"the email list (opens in a new tab)\">the email list<\/a>. If you want to go the extra mile, <a href=\"https:\/\/www.patreon.com\/TheRenegadeCoder\" target=\"_blank\" rel=\"noreferrer noopener\" aria-label=\"toss me a couple bucks on Patreon (opens in a new tab)\">toss me a couple bucks on Patreon<\/a>. You won\u2019t regret it!<\/p>\n\n\n\n<p>At any rate, until next time!<\/p>\n\n\n\n<div class=\"attribution\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>Published on Web Code Geeks with permission by Jeremy Grifski, partner at our <a href=\"\/\/www.webcodegeeks.com\/join-us\/wcg\/\" target=\"_blank\" rel=\"noopener noreferrer\">WCG program<\/a>. See the original article here: <a href=\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/\" target=\"_blank\" rel=\"noopener noreferrer\">How to Performance Test Python Code: timeit, cProfile, and More<\/a><\/p>\n<p>Opinions expressed by Web Code Geeks contributors are their own.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>A lot of the articles in this series take advantage of a feature of Python which allows us to performance test our code, and I finally wanted to get around to explaining how it works and how to use it. In this article, I cover three main techniques: brute force, timeit, and cProfile. Personally, I &hellip;<\/p>\n","protected":false},"author":14722,"featured_media":1651,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[53],"tags":[121],"class_list":["post-24945","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python","tag-testing"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v26.5 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026<\/title>\n<meta name=\"description\" content=\"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026\" \/>\n<meta property=\"og:description\" content=\"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile\" \/>\n<meta property=\"og:url\" content=\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/webcodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2019-12-10T10:15:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-06-23T12:00:36+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Jeremy Grifski\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@RenegadeCoder94\" \/>\n<meta name=\"twitter:site\" content=\"@webcodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeremy Grifski\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/\"},\"author\":{\"name\":\"Jeremy Grifski\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7eaa8e89cf23a5de82a048beb4c59aa1\"},\"headline\":\"How to Performance Test Python Code: timeit, cProfile, and More\",\"datePublished\":\"2019-12-10T10:15:06+00:00\",\"dateModified\":\"2020-06-23T12:00:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/\"},\"wordCount\":1596,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"image\":{\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"keywords\":[\"Testing\"],\"articleSection\":[\"Python\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/\",\"url\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/\",\"name\":\"How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026\",\"isPartOf\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"datePublished\":\"2019-12-10T10:15:06+00:00\",\"dateModified\":\"2020-06-23T12:00:36+00:00\",\"description\":\"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile\",\"breadcrumb\":{\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg\",\"width\":150,\"height\":150},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.webcodegeeks.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Python\",\"item\":\"https:\/\/www.webcodegeeks.com\/category\/python\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"How to Performance Test Python Code: timeit, cProfile, and More\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#website\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"name\":\"Web Code Geeks\",\"description\":\"Web Developers Resource Center\",\"publisher\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.webcodegeeks.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\/\/www.webcodegeeks.com\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"contentUrl\":\"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/webcodegeeks\",\"https:\/\/x.com\/webcodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7eaa8e89cf23a5de82a048beb4c59aa1\",\"name\":\"Jeremy Grifski\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/9d50311a27dff0a54d775b6106b8f804d5d11d0b5182ed537f325046a020c6f5?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/9d50311a27dff0a54d775b6106b8f804d5d11d0b5182ed537f325046a020c6f5?s=96&d=mm&r=g\",\"caption\":\"Jeremy Grifski\"},\"description\":\"Jeremy is the founder of The Renegade Coder, a software curriculum website launched in 2017. In addition, he is a PhD student with an interest in education and data visualization.\",\"sameAs\":[\"https:\/\/therenegadecoder.com\/\",\"https:\/\/www.linkedin.com\/in\/jeremy-grifski-22240552\/\",\"https:\/\/x.com\/RenegadeCoder94\"],\"url\":\"https:\/\/www.webcodegeeks.com\/author\/jeremy-grifski\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026","description":"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/","og_locale":"en_US","og_type":"article","og_title":"How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026","og_description":"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile","og_url":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/","og_site_name":"Web Code Geeks","article_publisher":"https:\/\/www.facebook.com\/webcodegeeks","article_published_time":"2019-12-10T10:15:06+00:00","article_modified_time":"2020-06-23T12:00:36+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","type":"image\/jpeg"}],"author":"Jeremy Grifski","twitter_card":"summary_large_image","twitter_creator":"@RenegadeCoder94","twitter_site":"@webcodegeeks","twitter_misc":{"Written by":"Jeremy Grifski","Est. reading time":"9 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#article","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/"},"author":{"name":"Jeremy Grifski","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7eaa8e89cf23a5de82a048beb4c59aa1"},"headline":"How to Performance Test Python Code: timeit, cProfile, and More","datePublished":"2019-12-10T10:15:06+00:00","dateModified":"2020-06-23T12:00:36+00:00","mainEntityOfPage":{"@id":"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/"},"wordCount":1596,"commentCount":0,"publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"image":{"@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","keywords":["Testing"],"articleSection":["Python"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.webcodegeeks.com\/python\/how-to-performance-test-python-code-timeit-cprofile-and-more\/","url":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/","name":"How to Performance Test Python Code: timeit, cProfile, and More - Web Code Geeks - 2026","isPartOf":{"@id":"https:\/\/www.webcodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage"},"image":{"@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage"},"thumbnailUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","datePublished":"2019-12-10T10:15:06+00:00","dateModified":"2020-06-23T12:00:36+00:00","description":"Interested to learn about Test Python Code? Check our article covering three main techniques: brute force, timeit, and cProfile","breadcrumb":{"@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#primaryimage","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2014\/11\/python-logo.jpg","width":150,"height":150},{"@type":"BreadcrumbList","@id":"https:\/\/therenegadecoder.com\/code\/how-to-performance-test-python-code\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.webcodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Python","item":"https:\/\/www.webcodegeeks.com\/category\/python\/"},{"@type":"ListItem","position":3,"name":"How to Performance Test Python Code: timeit, cProfile, and More"}]},{"@type":"WebSite","@id":"https:\/\/www.webcodegeeks.com\/#website","url":"https:\/\/www.webcodegeeks.com\/","name":"Web Code Geeks","description":"Web Developers Resource Center","publisher":{"@id":"https:\/\/www.webcodegeeks.com\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.webcodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.webcodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.webcodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.webcodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/webcodegeeks","https:\/\/x.com\/webcodegeeks"]},{"@type":"Person","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/7eaa8e89cf23a5de82a048beb4c59aa1","name":"Jeremy Grifski","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.webcodegeeks.com\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/9d50311a27dff0a54d775b6106b8f804d5d11d0b5182ed537f325046a020c6f5?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/9d50311a27dff0a54d775b6106b8f804d5d11d0b5182ed537f325046a020c6f5?s=96&d=mm&r=g","caption":"Jeremy Grifski"},"description":"Jeremy is the founder of The Renegade Coder, a software curriculum website launched in 2017. In addition, he is a PhD student with an interest in education and data visualization.","sameAs":["https:\/\/therenegadecoder.com\/","https:\/\/www.linkedin.com\/in\/jeremy-grifski-22240552\/","https:\/\/x.com\/RenegadeCoder94"],"url":"https:\/\/www.webcodegeeks.com\/author\/jeremy-grifski\/"}]}},"_links":{"self":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/24945","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/users\/14722"}],"replies":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/comments?post=24945"}],"version-history":[{"count":0,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/posts\/24945\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media\/1651"}],"wp:attachment":[{"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/media?parent=24945"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/categories?post=24945"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.webcodegeeks.com\/wp-json\/wp\/v2\/tags?post=24945"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}