My question is this: when it call comes down to machine code, to 1s
and 0s, to assembly instructions, should I be at all concerned that my
class-separated code with variety of small-to-tiny functions generates
too much extra overhead?
MY answer is yes, you should. Not because you have lots of little functions (once upon a time the overhead of calling functions was reasonably significant and you could slow your program down by making a million little calls in loops, but today compilers will inline them for you and what's left is taken care of by the CPU fancy prediction algorithms, so don't worry about that) but because you will introduce the concept of layering too much into your programs when the functionality is too small to sensibly grok in your head. If you have larger components you can be reasonably sure they are not performing the same work over and over, but you can make your program so minutely granular that you may find yourself unable to really understand the call paths, and in that end up with something that barely works (and is barely maintainable).
For example, I worked at a place that showed me a reference project for a web service with 1 method. The project comprised 32 .cs files - for a single web service! I figured this was way too much complexity, even though each part was tiny and easily understood by itself, when it came to describing the overall system, I quickly found myself having to trace through calls just to see what the hell it was doing (there were also too many abstractions involved,as you'd expect). My replacement webservice was 4 .cs files.
i didn't measure performance as I figure it would have been roughly the same all in all, but I can guarantee mine was significantly cheaper to maintain. When everyone talks of programmer time being more important than CPU time, then create complex monsters that cost lots of programmer time in both dev and maintenance you have to wonder that they are making excuses for bad behaviour.
It was said somewhere (quote TBD) that up to 70% of all code is made
up of ASM's MOV instruction - loading CPU registers with proper
variables, not the actual computation being done.
That is what CPUs do though, they move bits from memory to registers, add or subtract them, and then put them back into memory. All computing boils down to pretty much that. Mind you, I once had a very multi-threaded program that spent most of its time context switching (ie saving and restoring register state of threads) than it did working on the thread code. A simple lock in the wrong place truly screwed performance there, and it was such an innocuous bit of code too.
So my advice is : find a sensible middle ground between either extreme that make your code look good to other humans, and test the system to see if it performs well. Use the OS features to make sure its running as you'd expect with CPU, memory, disk and network IO.
is Python simply poor at handling code breakdown altogether?
Unfortunately yes, Python is slow and there are many anecdotes about people drastically increasing performance by inlining functions and making their code ugly.
There is a work around, Cython, which is a compiled version of Python and much faster.
--Edit
I just wanted to address some of the comments and other answers. Although the thrust of them isnt perhaps python specific. but more general optimisation.
Don't optimise untill you have a problem and then look for bottlenecks
Generally good advice. But the assumption is that 'normal' code is usually performant. This isn't always the case. Individual languages and frameworks each have their own idiosyncracies. In this case function calls.
Its only a few milliseconds, other things will be slower
If you are running your code on a powerful desktop computer you probably don't care as long as your single user code executes in a few seconds.
But business code tends to run for multiple users and require more than one machine to support the load. If your code runs twice as fast it means you can have twice the number of users or half the number of machines.
If you own your machines and data centre then you generally have a big chunk of overhead in CPU power. If your code runs a bit slow, you can absorb it, at least until you need to buy a second machine.
In these days of cloud computing where you only use exactly the compute power you require and no more, there is a direct cost for non performant code.
Improving performance can drastically cut the main expense for a cloud based business and performance really should be front and centre.
Best Answer
Maybe. The compiler might decide "hey, this function is only called a few times, and I'm supposed to optimize for speed, so I'll just inline this function". Essentially, the compiler will replace the function call with the body of the function. For example, the source code would look like this.
The compiler decides to inline
DoSomethingElse
, and the code becomesWhen functions are not inlined, yes there is a performance hit to make a function call. However, it's such a minuscule hit that only extremely high performance code is going to worry about function calls. And on those kinds of projects, the code is typically written in assembly.
Function calls (depending on the platform) typically involve a few 10s of instructions, and that's including saving / restoring the stack. Some function calls consist a jump and return instruction.
But there's other things that might impact function call performance. The function being called may not be loaded into the processor's cache, causing a cache miss and forcing the memory controller to grab the function from main RAM. This can cause a big hit for performance.
In a nutshell: function calls may or may not impact performance. The only way to tell is to profile your code. Don't try to guess where the slow code spots are, because the compiler and hardware have some incredible tricks up their sleeves. Profile the code to get the location of the slow spots.