Profiling
High-performance Python isn't about writing "faster code" — it's about finding bottlenecks and eliminating them with scientific precision. You cannot optimise what you do not measure.
Learn Python, JavaScript, Java and more with free interactive lessons, real projects and AI-powered help. Beginner-friendly.
Part of the free Python course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
What You'll Learn in This Lesson
Beginners try to "guess" what's slow. Advanced developers measure what's slow.
Optimizing the wrong 80% gives no improvement!
But for full programs, we need real profilers.
Run a script with profiling from command line:
⚠️ Requires local Python installation • Download Python
Pure Python loops are slow. NumPy performs operations in C — often 50–200× faster.
Transforms slow recursive functions → instant.
⚠️ Requires: pip install orjson • Download Python
orjson is 5–20× faster than Python's JSON parser.
By mastering profiling and optimisation, you gain the ability to:
Performance comes from measure → diagnose → optimise, not guessing.
📋 Quick Reference — Profiling & Performance
You now know how to measure, diagnose, and fix performance bottlenecks — the professional workflow every senior engineer uses.
Up next: Memory Management — understand how Python's garbage collector works and prevent memory leaks.
Practice quiz
What is the core idea behind profiling before optimising?
- Always optimise the longest function first
- Rewrite everything in C
- Measure what's slow instead of guessing
- Add more print statements
Answer: Measure what's slow instead of guessing. You cannot optimise what you do not measure — profiling replaces guessing with data.
Which standard-library tool profiles function call counts and time?
- cProfile
- tracemalloc
- asyncio
- logging
Answer: cProfile. cProfile records every call, how long each takes, and how many times it runs.
In cProfile output, what does 'tottime' measure?
- Total time including all sub-calls
- Number of times the function was called
- Total program runtime
- Time in the function itself, excluding sub-calls
Answer: Time in the function itself, excluding sub-calls. tottime is time spent in the function body alone; cumtime includes time in sub-calls.
Which sort key best reveals the actually-slow functions?
- "ncalls"
- "tottime"
- "cumtime"
- "name"
Answer: "tottime". Sort by tottime to find where time is really spent; then use cumtime to trace callers.
What does functools.lru_cache do to a recursive fib function?
- Caches results so repeated calls are instant
- Slows it down by caching
- Runs it on multiple cores
- Converts it to a loop
Answer: Caches results so repeated calls are instant. lru_cache memoizes results, turning exponential recursion into near-instant lookups.
What does timeit.timeit('expr', number=1000) return?
- The result of the expression
- A profile report object
- The total time (a float) to run it that many times
- The number of calls
Answer: The total time (a float) to run it that many times. timeit returns the total elapsed time as a float for the given number of executions.
Why use a generator expression (x*x for x in nums) over a list for large data?
- It is always faster to build
- It saves memory by yielding items lazily
- It sorts the data
- It runs in parallel
Answer: It saves memory by yielding items lazily. Generators produce items one at a time instead of building the whole list in memory.
What is the recommended fix for slow string concatenation in a loop?
- Use s = s + x each time
- Use a global string
- Use print() to build it
- Use ''.join(list_of_strings)
Answer: Use ''.join(list_of_strings). ''.join builds the result in one pass; repeated + creates a new string object every iteration.
What does the 80/20 rule say about performance?
- 80% of code runs in 20% of the time
- Roughly 20% of code accounts for ~80% of runtime
- Optimise 80% of functions
- 20% of bugs cause 80% of crashes
Answer: Roughly 20% of code accounts for ~80% of runtime. A small fraction of code dominates runtime, so optimising the wrong 80% gives no improvement.
Which tool tracks memory usage line-by-line?
- cProfile
- timeit
- memory_profiler
- pstats
Answer: memory_profiler. memory_profiler shows memory growth per line; cProfile and timeit measure time, not memory.