Usage Guide

eprofiler provides a tiered approach to performance measurement, allowing you to choose the level of detail you need—from lightweight timing to deep-dive CPU and memory forensics.

Note

The “Smart” Decorator Pattern: All decorators in eprofiler are designed to be intuitive. You can use them in two ways:

  1. Simple: @profile (no parentheses, uses default settings)

  2. Configured: @profile(label=”API”, callback=my_func) (with parentheses for custom options)

Basic Timing (@timeit)

Use the @timeit decorator for high-performance wall-clock timing with minimal overhead.

from eprofiler import timeit

# Simple usage
@timeit
def simple_task():
    pass

# Custom label
@timeit(label="Heavy Computation")
def heavy_task():
    return [x**2 for x in range(10000)]

Full Health Check (@profile)

The @profile decorator is your “all-in-one” tool. It measures wall-clock duration, CPU time, and memory usage (current and peak) in a single pass.

from eprofiler import profile

@profile(label="System Audit")
def audit_function():
    data = [i for i in range(1000000)]
    return sum(data)

The result is a dictionary-like object containing: {‘label’: ‘System Audit’, ‘duration’: 0.12, ‘cpu_time’: 0.11, ‘peak_mb’: 32.4, …}

Dynamic usage:

from eprofiler import profile

def audit_function():
    data = [i for i in range(1000000)]
    return sum(data)

profiled_test = profile(audit_function, label="System Audit")

profiled_test()  # this will print the stats

CPU Forensic Profiling (@profile_cpu)

When you need to understand how much of the “Wall Time” was actually spent using the processor versus waiting for I/O or sleep, use @profile_cpu.

On Unix-like systems, this provides a breakdown of User vs System time and calculates Efficiency ($Efficiency = frac{CPUTime}{Duration} times 100$).

from eprofiler import profile_cpu

@profile_cpu(label="I/O vs CPU Test")
def io_bound_task():
    import time
    time.sleep(1) # This increases 'duration' but not 'cpu_time'
    return sum(range(1000000))

Memory Tracking (@memit)

If you are only concerned about memory leaks or peak allocation, use @memit. It uses Python’s tracemalloc to provide high-precision memory delta tracking.

from eprofiler import memit

@memit
def allocate_memory():
    return [0] * (10**6)

The Timer Class (and Context Manager)

The Timer class is the engine behind @timeit. It is particularly useful as a Context Manager for timing specific blocks of code inside a larger function.

from eprofiler import Timer

def complex_workflow():
    setup_logic()

    with Timer("Database Push") as t:
        # Only this block is timed
        push_to_db()

    print(f"DB Push took: {t.duration}s")
    teardown_logic()

Callbacks and Redirection

By default, eprofiler prints results to stdout. You can redirect results to a logger, a file, or a monitoring service by passing a callback function.

import logging

def log_stats(stats):
    # 'stats' is a dictionary containing all measured metrics
    logging.info(f"{stats['function']} ran in {stats['duration']}s")

@profile(callback=log_stats)
def production_service():
    pass

Using the Auditor (@audit)

To monitor function inputs and outputs for debugging data-processing pipelines:

from eprofiler import audit

@audit()
def process_data(user_id, mode="fast"):
    return {"status": "ok"}