Skip to content

The @profile decorator will profile another decorator when chaining multiple decorators into a function. #373

Description

@stenbein

Stacking multiple decorators together will result in unexpected behavior. A trivial example:

from functools import wraps
from random import random
import time

from memory_profiler import profile

def timeit(f):
    @wraps(wrapped=f)
    def wrapper(*args, **kw):
        ts = time.time()
        result = f(*args, **kw)
        te = time.time()
        print(f'func: {f.__name__} took: {te-ts:2.4f} sec')
        return result

    return wrapper


@profile
@timeit
def to_profile(n):
    arr = [random() for i in range(n)]
    return sum(arr)


to_profile(1_000)

What I expect to see:

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
    20     48.8 MiB     48.8 MiB           1   @timeit
    21                                         @profile
    22                                         def to_profile(n):
    23     48.8 MiB      0.0 MiB        1003       arr = [random() for i in range(n)]
    24     48.8 MiB      0.0 MiB           1       return sum(arr)

What we actually get:

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
     9     49.0 MiB     49.0 MiB           1       @wraps(wrapped=f)
    10                                             def wrapper(*args, **kw):
    11     49.0 MiB      0.0 MiB           1           ts = time.time()
    12     49.0 MiB      0.0 MiB           1           result = f(*args, **kw)
    13     49.0 MiB      0.0 MiB           1           te = time.time()
    14     49.0 MiB      0.0 MiB           1           print(f'func: {f.__name__} took: {te-ts:2.4f} sec')
    15     49.0 MiB      0.0 MiB           1           return result

I realized while checking this that the sample timeit decorator has the same issue and is timing the @profile rather than the underlying to_profile.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions