PetrochukM / HParams

Configure Python functions explicitly and safely
MIT License
126 stars 8 forks source link

Further improve `HParam` performance by 18x #4

Closed PetrochukM closed 4 years ago

PetrochukM commented 4 years ago

This uses traceback.extract_stack(limit=2)[-2] instead of inspect.stack(0)[1] because it's faster. This is the benchmark:

import inspect
import sys
import time
import timeit
import traceback

def deeper(func, depth):
    if depth > 0:
        return deeper(func, depth - 1)
    else:
        return func()

def no_stack():
    pass

def bench_stack():
    return inspect.stack()[1].filename, inspect.stack()[1].lineno

def bench_stack_limit():
    return inspect.stack(0)[1].filename, inspect.stack(0)[1].lineno

def bench_trace():
    return traceback.extract_stack()[-2].filename, traceback.extract_stack()[-2].lineno

def bench_trace_limit():
    return (traceback.extract_stack(limit=2)[-2].filename,
            traceback.extract_stack(limit=2)[-2].lineno)

assert deeper(bench_trace_limit, depth=5) == deeper(bench_stack, depth=5)
assert deeper(bench_trace, depth=5) == deeper(bench_stack, depth=5)
assert deeper(bench_stack_limit, depth=5) == deeper(bench_stack, depth=5)

samples = 10000
print('baseline:', timeit.timeit(lambda: deeper(no_stack, depth=5), number=samples))
print('bench_stack:', timeit.timeit(lambda: deeper(bench_stack, depth=5), number=samples))
print('bench_stack_limit:',
      timeit.timeit(lambda: deeper(bench_stack_limit, depth=5), number=samples))
print('bench_trace:', timeit.timeit(lambda: deeper(bench_trace, depth=5), number=samples))
print('bench_trace_limit:',
      timeit.timeit(lambda: deeper(bench_trace_limit, depth=5), number=samples))

The benchmark was inspired by: https://gist.github.com/JettJones/c236494013f22723c1822126df944b12

These were the results:

baseline: 0.008920529999999996
bench_stack: 17.366878454000002
bench_stack_limit: 4.497257854999997
bench_trace: 0.9375153429999976
bench_trace_limit: 0.2445523019999989
codecov-io commented 4 years ago

Codecov Report

Merging #4 into master will not change coverage. The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master     #4   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files           2      2           
  Lines         247    248    +1     
=====================================
+ Hits          247    248    +1
Impacted Files Coverage Δ
hparams/hparams.py 100% <100%> (ø) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 40166a8...6594417. Read the comment docs.