Python Forum
Looking for clarification related to performance
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Looking for clarification related to performance
#1
I have come across statements saying that one should be careful about calling functions too frequently because of the performance overhead. Is this truly something that I need to be concerned about? I will assume for now that it is.

I have also come across statements warning about the use of "for" loops, also because of performance reasons, and that instead one ought to use the map feature.

However, almost all map examples call out to functions. While there are some examples with lambdas, this is probably not the best option when dealing larger and more complicated functions.

So, on the one hand, I can do a for loop and not repeatedly call function, therefore saving the function call overhead.

Or, I can use the allegedly more performant map feature in which I may have to do a function call and accept less than optimal performance.

What really are the things that I need to consider?

Thank you.
Reply
#2
You should only worry about performance when you have a performance issue, not before.
ndc85430 and Larz60+ like this post
Reply
#3
(Apr-02-2022, 06:50 PM)deanhystad Wrote: You should only worry about performance when you have a performance issue, not before.

While true, that is a very flippant answer to someone seeking a deeper knowledge of the language and, as a newcomer to this forum, I must say that it is these kinds of replies that make a community toxic and unwelcoming.
casevh likes this post
Reply
#4
I am being sincere. I think it is good advice. Write code to be correct and easy to maintain. If there are performance issues, fix those when they occur. Often this will involve not writing code in Python at all, but instead using Python packages like numpy or pandas that are highly optimized and do much of their work in linked libraries. You are not going to see big changes in performance using a comprehension or map instead of a loop. They are good tools, but they don't turn Python into C. At least that is not my experience.

I use comprehensions and map and other functools because I can write a lot of function in a few lines of code. Potential performance benefits don't cross my mind. I often find a nice comprehension easier to read than a stretched out for loop.

As always, the best way to speed up code is run less code. Optimize the algorithm to get real speed gains.
ndc85430, ibreeden, Larz60+ like this post
Reply
#5
It is difficult to provide a complete answer without understanding the context - both of the person making the statement "function calls are slow" and what your program does. So let's look at adding two numbers that are stored in the variables a and b. The easiest way is just t = a + b.

It is relatively fast.

$ python3.9 -m timeit -s "a=1;b=2" "t=a+b"
10000000 loops, best of 5: 20.7 nsec per loop
Now create a function and save it in a file called examples.py

def f_1(x, y):
    return x + y
Now measure the running time.

$ python3.9 -m timeit -s "import examples;a=1;b=1" "examples.f_1(a,b)"
5000000 loops, best of 5: 94.8 nsec per loop
Why is it so much slower? One reason is that Python uses dictionaries to store the names of functions. There are two additional dictionary lookups required to evaluate examples.f_1(a,b). Python first must find examples in the local namespace. Then it must find f_1 in the local namespace belonging to examples. A common trick is to lookup examples.f_1 once and cache the result. For example f=examples.f_1. That is faster.

$ python3.9 -m timeit -s "import examples;f=examples.f_1;a=1;b=1" "f(a,b)"
5000000 loops, best of 5: 70.2 nsec per loop
So there is an overhead for calling a function. So does that imply we minimize the use of functions? Nope. Surprisingly, code inside a function can run faster. Here is a contrived example. The code:

import time

big_list = [(i,i) for i in range(500)]

start = time.time()
total = 0
for a,b in big_list:
    total = total + a * b
end = time.time()
print("Elapsed time:", end - start)

def f_2(big_list):
    start = time.time()
    total = 0
    for a,b in big_list:
        total = total + a * b
    end = time.time()
    print("Elapsed time:", end - start)

f_2(big_list)
and the results:

$ python3.9 example2.py 
Elapsed time: 6.580352783203125e-05
Elapsed time: 3.337860107421875e-05
Why the difference? Name lookups that are in a function's own local namespace are faster than a dictionary lookup.



So what to do? Organize code as functions just because it is easier to write, understand, and maintain. If the program is running too slow, look carefully at "how" you are solving your problem. Better algorithms are, well, better. Identify what code is slow and understand why it slow. Learn itertools (see next section for why).



I added the following function to example2.

import itertools
import operator
def f_3(big_list):
    start = time.time()
    sum((itertools.starmap(operator.mul,big_list)))
    end = time.time()
    print("Elapsed time:", end - start)

f_3(big_list)
and the results:

$ python3.9 example2.py 
Elapsed time: 6.222724914550781e-05
Elapsed time: 3.314018249511719e-05
Elapsed time: 1.9311904907226562e-05


Lastly, there are many performance recommendations on the Internet. Don't trust their recommendations unless you measure it on _your_ code. (Don't trust me either. I chose my examples to illustrate specific behaviors.)

p.s. The fastest way to compute the sum of squares is the formula (n(n+1)(2n+1)) / 6. A better algorithm is, well, better. Smile

casevh
ibreeden and snippsat like this post
Reply
#6
Look at the times and think about how that affects your program. If something takes 95 nanoseconds to do, doing it one million times takes 95 milliseconds. For most purposes 95 milliseconds is the same as 21 milliseconds; no time at all. If you do something billions of times the difference is significant, but if you are doing billions of operations you are better off using a package that is optimized for the work you are trying to do.

I think the advice to do your own timing is excellent. Your results may vary is really true.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Can I get some clarification on importing functions from external files. wh33t 3 919 Feb-25-2023, 08:07 PM
Last Post: deanhystad
  Read Tensorflow Documentation - Clarification IoannisDem 0 1,174 Aug-20-2021, 10:36 AM
Last Post: IoannisDem
  *args implementation and clarification about tuple status amjass12 10 4,078 Jul-07-2021, 10:29 AM
Last Post: amjass12
  Although this is a talib related Q it's mostly related to python module installing.. Evalias123 4 5,707 Jan-10-2021, 11:39 PM
Last Post: Evalias123
  Just need some clarification Tonje 3 2,074 Oct-01-2020, 03:52 PM
Last Post: deanhystad
  Performance enhancement fimmu 0 1,631 Feb-12-2020, 02:42 PM
Last Post: fimmu
  Global Variables - Some Points Needing Clarification. adt 4 2,973 Nov-30-2019, 01:23 PM
Last Post: adt
  performance kerzol81 1 1,922 Oct-07-2019, 10:19 AM
Last Post: buran
  How I can do performance testing on my API a21250450 0 1,405 Jul-18-2019, 09:29 AM
Last Post: a21250450
  Python performance rvkstudent 4 3,006 Apr-25-2019, 09:29 AM
Last Post: rvkstudent

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020