Using timeit in Cell Magic Mode (%%timeit) in Python 2026 with Efficient Code

Efficient Code Mar 15, 2026

Using timeit in Cell Magic Mode (%%timeit) in Python 2026 with Efficient Code

The %%timeit cell magic is the most convenient way to benchmark multi-line code blocks in Jupyter Notebooks and IPython. In 2026, with improved notebook kernels and free-threading support, %%timeit remains an essential tool for quick and reliable performance testing during development.

This March 15, 2026 guide shows how to use %%timeit effectively for multi-line code and interpret its results correctly.

TL;DR — Key Takeaways 2026

  • %%timeit is used at the top of a cell to time the entire block of code
  • It automatically runs the cell multiple times and reports the best time per loop
  • Use -n and -r to control loops and repeats
  • Perfect for comparing multi-line functions or algorithms
  • Free-threading safe and highly accurate in modern Python

1. Basic Usage of %%timeit


%%timeit
total = 0
for i in range(10000):
    total += i ** 2

2. Advanced Usage with Options (2026 Recommended)


%%timeit -n 500 -r 7
# Multi-line code block
import numpy as np
arr = np.random.randn(1000, 1000)
result = np.sum(arr**2, axis=1)
mean_val = result.mean()

3. Real-World Comparison Example


%%timeit -n 100 -r 5
# Version 1: Pure Python
total = 0
for i in range(50000):
    total += i ** 2

%%timeit -n 100 -r 5
# Version 2: NumPy (much faster)
import numpy as np
arr = np.arange(50000)
result = np.sum(arr**2)

4. Best Practices for %%timeit in 2026

  • Place %%timeit at the very top of the cell
  • Use -n and -r for consistent results (e.g., -n 200 -r 7)
  • Target 0.2 – 2 seconds total runtime per test
  • Compare multiple versions by running them in separate cells
  • Avoid print statements inside the timed cell (they add overhead)
  • Include all necessary imports inside the cell or use setup with -s

Line Magic versus Cell Magic

%timeit times a single line, while %%timeit times a whole cell. The double-percent form must be the first line of the cell, and everything below it is the code being timed.

Anything in the cell runs in every loop, including imports and data creation. To exclude setup, put it on the %%timeit line itself, as in %%timeit -n 100 data = list(range(1000)), or run it in a separate cell first.

Only one %%timeit can appear per cell, so compare alternatives in separate cells.

Worked Example: The Same Cell as a Script

This plain Python version times a multi-line block with separate setup, like %%timeit with a setup line.

import timeit

setup = "import numpy as np; arr = np.arange(50_000)"
python_block = """
total = 0
for i in range(50_000):
    total += i ** 2
"""
numpy_block = "result = int(np.sum(arr ** 2))"

for name, stmt in [("pure Python", python_block), ("NumPy", numpy_block)]:
    best = min(timeit.repeat(stmt, setup=setup, number=50, repeat=5)) / 50
    print(f"{name:12} {best * 1000:.3f} ms per loop")

The setup string creates the array once, so only the computation is timed. In a notebook, the equivalent is two separate %%timeit cells with the array created beforehand.

Practical Tips

Variables created inside a %%timeit cell are not kept after the cell finishes, so run the code once normally when you also need its result. If the timed code modifies data, such as sorting a list in place, later loops work on already sorted data; build a fresh copy inside the cell to keep each loop identical.

Use -n and -r on the %%timeit line when the defaults take too long.

Common Mistakes

  • Placing anything before %%timeit in the cell.
  • Including imports and data creation in the timed body.
  • Putting two %%timeit commands in one cell.
  • Expecting variables defined inside %%timeit to persist.

Quick Summary

  • %%timeit times a whole cell.
  • It must be the first line.
  • Keep setup out of the timed body.
  • Use one cell per alternative.

Conclusion — Using %%timeit in Cell Magic Mode (2026)

%%timeit is the fastest and most convenient way to benchmark multi-line code blocks directly in your notebook. In 2026, combining it with proper -n and -r options gives you reliable performance insights that help you write significantly more efficient Python code.

Next steps:

  • Use %%timeit -n 200 -r 7 for all your multi-line performance tests

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