跟踪功能要求记录时间

时间:2019-01-11 01:36:35

标签: python decorator python-decorators

不确定在Python中是否可行,但是我试图剖析大型函数并指出其处理/ I / O的哪些部分运行缓慢。我试图编写几个装饰器函数。顶级函数,用于包装正在分析的函数。如果某些嵌套函数的装饰器超出了顶层装饰器的阈值,则该装饰器将报告其时序。我不确定如何在装饰器之间共享此上下文。

顶级装饰器

def time_stack(name, threshold=60000):
    def wrapper(f):
        def wrapped(*args, **kwargs):
            start = time_millis()
            f(*args, **kwargs)
            end = time_millis()
            if end - start > threshold:
                # Log out frame timings here
        return wrapped
    return wrapper

对于嵌套函数

def time_frame(name):
    def wrapper(f):
        def wrapped(*args, **kwargs):
            start = time_millis()
            f(*args, **kwargs)
            end = time_millis()
            t = end - start
            # Somehow remember this value for the outer time_stack to use if needed
        return wrapped
    return wrapper

示例

@time_frame(name="do_some_io")
def do_some_io(string):
    # do some io

@time_frame(name="do_a_transform")
def do_a_transform(result):
    # do some transforming

@time_frame(name="do_some_caching")
def do_some_caching(stuff):
    # do some caching

@time_stack(name="search", threshold=100000):
def search(string):
    result = do_some_io(string)
    transformed = do_a_transform(result)
    return do_some_caching(transformed)

在这里,如果搜索的执行时间超过100000ms,它将打印出类似的内容

search took 123456ms
    do_some_io: 23000ms
    do_a_transform: 13678ms
    do_some_caching: 86778ms

我虽然要通过kwargs传递对象以跟踪时间,但是调用堆栈中的所有函数的签名中都必须带有** kwargs,并且如果有一种方法可以实现这一目标而不必这样做会更好。

1 个答案:

答案 0 :(得分:0)

您可以定义一个全局堆栈,该堆栈保留每个time_frame的数据。它将在调用该函数之前在time_stack上设置,并将在其末尾重置。如果时间已超过阈值,则可以使用其数据。 但是,应该只有一个time_stack。对于多个time_stack函数,应该有一个包含堆栈的堆栈。 这个想法的草图如下:

const webpack = require('webpack');
const dotenv = require('dotenv');

module.exports = () => {
  // call dotenv and it will return an Object with a parsed key 
  const env = dotenv.config().parsed;

  // reduce it to a nice object, the same as before
  const envKeys = Object.keys(env).reduce((prev, next) => {
    prev[`process.env.${next}`] = JSON.stringify(env[next]);
    return prev;
  }, {});

  return {
    plugins: [
      new webpack.DefinePlugin(envKeys)
    ]
  };

PROFILE_STACK = []
STACK_IS_SET = False
def time_stack(name, threshold=60000):
    def wrapper(f):
        def wrapped(*args, **kwargs):
            PROFILE_IS_SET = True
            start = time_millis()
            f(*args, **kwargs)
            end = time_millis()
            if end - start > threshold:
                # use PROFILE_STACK
            PROFILE_STACK.clear()
            STACK_IS_SET = False
        return wrapped
    return wrapper