Understanding %lprun Output in Python 2026 with Efficient Code

Efficient Code Mar 15, 2026

Understanding %lprun Output in Python 2026 with Efficient Code

The %lprun magic from line_profiler is one of the most powerful tools for line-by-line performance analysis. In 2026, understanding its output correctly is essential for identifying exact bottlenecks and making targeted optimizations in your Python code.

This March 15, 2026 guide explains how to read and interpret %lprun output effectively.

TL;DR — Key Takeaways 2026

  • %lprun shows execution time per line of code
  • Focus on Time and Per Hit columns
  • High % Time indicates the real hotspots
  • Use it after cProfile to zoom into slow functions
  • Free-threading safe and highly accurate in modern Python

1. How to Use %lprun


%load_ext line_profiler

def slow_function(n=10000):
    total = 0
    for i in range(n):
        total += i ** 2
    return total

# Run line profiler
%lprun -f slow_function slow_function()

2. Understanding %lprun Output

Typical Output (illustrative; your timings will differ):


Timer unit: 1e-06 s

Total time: 0.012345 s
File: example.py
Function: slow_function at line 1

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     1                                           def slow_function(n=10000):
     2         1          5.0      5.0      0.0      total = 0
     3     10001       8234.0      0.8     66.7      for i in range(n):
     4     10000       4106.0      0.4     33.3          total += i ** 2
     5         1          0.0      0.0      0.0      return total

Key Columns:

  • Hits — How many times the line ran
  • Time — Total time spent on that line, in the timer unit shown on the first line of the output
  • Per Hit — Average time per execution
  • % Time — Percentage of total function time (most important!)

3. Best Practices for Reading %lprun Output

  • Focus on lines with highest % Time
  • High Hits + low Per Hit = many cheap operations (good candidate for vectorization)
  • Low Hits + high Per Hit = expensive operations (look for I/O or heavy calculations)
  • Always compare before and after optimization

Interpreting Line Profiles

line_profiler measures each line of selected functions. The Hits column shows how many times a line ran, Time shows total time in the timer unit printed at the top, Per Hit is the average, and % Time is that line's share of the function's total.

Start with % Time: the lines with the largest share are the only ones worth optimising. A high Hits count with a small Per Hit usually points to a loop that could be vectorised.

Because timings vary between runs and machines, compare percentages within one profile rather than absolute numbers across profiles.

Worked Example: Profiling Without IPython

line_profiler can also be used from a plain script through its LineProfiler class.

from line_profiler import LineProfiler

def slow_function(n=10_000):
    total = 0
    for i in range(n):
        total += i ** 2
    return total

def fast_function(n=10_000):
    return sum(i * i for i in range(n))

lp = LineProfiler()
profiled = lp(slow_function)
print(profiled() == fast_function())
lp.print_stats()

The printed table has the same columns as %lprun. In a run like this, the loop line and the accumulation line together take almost all of the time, which is exactly the part replaced by a single expression in fast_function.

Practical Tips

In IPython, the same report comes from %load_ext line_profiler followed by %lprun -f function_name function_name(), which profiles only the functions passed with -f. Profile one suspected hotspot at a time, because each profiled line adds overhead and makes the whole run slower.

After changing the code, profile it again with the same input and compare the percentages to confirm the improvement.

Common Mistakes

  • Optimising lines with a tiny % Time.
  • Comparing absolute times across machines.
  • Profiling every function instead of the suspected hotspot.
  • Forgetting that profiling adds overhead to each line.

Quick Summary

  • Hits, Time, Per Hit and % Time are the key columns.
  • Focus on lines with the largest % Time.
  • Many hits with small per-hit time suggest vectorising.
  • Use LineProfiler in plain scripts.

Conclusion — Understanding %lprun Output in 2026

%lprun gives you line-level visibility into your code’s performance. In 2026, mastering this tool allows you to find and fix bottlenecks with surgical precision, leading to much faster and more efficient Python applications.

Next steps:

  • Install line_profiler and start using %lprun on your slowest functions

Related Tutorials

Share:
Last updated: March 2026
Built-in Functions in Python 2026 str() in Python 2026: String Conversion + Modern Formatting & Best Practices memoryview with JAX in Python 2026: Zero-Copy NumPy → JAX Array Interop + Efficient ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + GPU Pinning & ML Examples memoryview with TensorFlow in Python 2026: Zero-Copy NumPy → Tensor Interop + ML Examples memoryview with NumPy & PyTorch in Python 2026: Zero-Copy Views, Efficient Slicing & ML Interop Examples memoryview with NumPy in Python 2026: Zero-Copy Views, Efficient Slicing & Real ML Examples memoryview() in Python 2026: Zero-Copy Magic for Large Binary Data + Real Examples import() in Python 2026: How It Works, Security Risks & Modern Alternatives (importlib) zip() in Python 2026: How to Use It, strict=True Behavior & Real-World Examples vars() in Python 2026: Accessing Object Namespace + Modern Introspection Patterns type() in Python 2026: Dynamic Type Inspection & Object Creation + Modern Patterns tuple() in Python 2026: Immutable Sequences + Modern Patterns & Best Practices super() in Python 2026: Method Resolution & Modern Inheritance Patterns sum() in Python 2026: Summing Iterables + Modern Numeric Patterns & Best Practices staticmethod() in Python 2026: Static Methods, Utility Functions & Modern Best Practices sorted() in Python 2026: Sorting Iterables + Modern Patterns & Best Practices slice() in Python 2026: Creating Slice Objects + Modern Patterns & Best Practices setattr() in Python 2026: Dynamic Attribute Setting + Modern Patterns & Safety set() in Python 2026: Mutable Sets Creation + Modern Patterns & Best Practices