Here is a lightweight way that you can use in a doctest or directly in your script and without any extra dependency, inspired from a question on how to limit execution time for a function
import signal
from contextlib import contextmanager
@contextmanager
def time_limit(seconds):
    def signal_handler(signum, frame):
        raise TimeoutError
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)
def efficiency_test(function, *args, **kwargs):
    try:
        with time_limit(2):
            return (True, function(*args, **kwargs))
    except TimeoutError as e:
        return (False, None)
With example usage:
import signal
from contextlib import contextmanager
@contextmanager
def time_limit(seconds):
    def signal_handler(signum, frame):
        raise TimeoutError
    signal.signal(signal.SIGALRM, signal_handler)
    signal.alarm(seconds)
    try:
        yield
    finally:
        signal.alarm(0)
def simple(a, b):
    return a + b
def complex_(a, b):
    for i in range(100000000):
        a += b
    return a
def efficiency_test(function, *args, **kwargs):
    try:
        with time_limit(2):
            return (True, function(*args, **kwargs))
    except TimeoutError as e:
        return (False, None)
if __name__ == "__main__":
    print(efficiency_test(simple, 1, 2))
    print(efficiency_test(complex_, 1, 2))
With output:
(True, 3)
(False, None)