Posted on 2021-10-08 10:45
魔のkyo 阅读(128)
评论(0) 编辑 收藏 引用
import time
class PerfCounter():
def get_time(self):
return time.perf_counter()
class Node:
clock = None
def __init__(self, name, parent):
# 带父节点的孩子兄弟树结构字段
self.parent = parent
self.child = None
self.sibling = None
self.name = name
self.total_calls = 0
self.recursion_counter = 0
self.total_ticks = 0
def __del__(self):
if self.child:
del self.child
self.child = None
if self.sibling:
del self.sibling
self.sibling = None
def get_child(self, name):
child = self.child
while child:
if child.name == name:
return child
child = child.sibling
# 如果没有找到就新建结点,并插入作为第一个孩子
node = Node(name=name, parent=self)
node.sibling = self.child
self.child = node
return node
def reset(self):
self.total_calls = 0
self.total_ticks = 0
if self.child:
self.child.reset()
if self.sibling:
self.sibling.reset()
def enter(self):
self.total_calls += 1
self.recursion_counter += 1
if self.recursion_counter == 1:
self.start_tick = self.clock.get_time()
def exit(self):
self.recursion_counter -= 1
if self.recursion_counter == 0 and self.total_calls != 0:
tick = self.clock.get_time() - self.start_tick;
self.total_ticks += tick;
return (self.recursion_counter == 0)
class Profiler:
def __init__(self, clock=None):
Node.clock = clock or PerfCounter()
self.root = Node("", None)
self.current_node = self.root
self.root.enter()
def __del__(self):
if self.root:
del self.root
def set_clock(self, clock):
Node.clock = clock
def reset(self):
self.root.reset()
self.root.enter()
def enter(self, name):
if name != self.current_node.name:
self.current_node = self.current_node.get_child(name)
self.current_node.enter()
def exit(self):
if self.current_node.exit():
self.current_node = self.current_node.parent
profiler = Profiler()
def time_me(fn, profiler=profiler):
def wrapper(*args, **kw):
profiler.enter(fn.__name__)
ret = fn(*args, **kw)
profiler.exit()
return ret
return wrapper
def enter_region(name, profiler=profiler):
profiler.enter(name)
def exit_region(profiler=profiler):
profiler.exit()
def dfs(node, depth, cb):
cb(node, depth)
node = node.child
while node:
dfs(node, depth+1, cb)
node = node.sibling
def travel(cb, profiler=profiler):
if profiler.root:
profiler.root.exit()
dfs(profiler.root, 0, cb)
def view(node, depth):
print("{space}[{name}] {calls} times {ticks:.3f} seconds {rate:.2f}%".format(
space=" "*depth, name=node.name, calls=node.total_calls, ticks=node.total_ticks, rate=node.total_ticks*100/(node.parent and node.parent.total_ticks or node.total_ticks) ))
if __name__ == '__main__':
@time_me
def func1():
time.sleep(0.5)
func3()
@time_me
def func2(n):
if n <= 2:
func3()
return 1
else:
return func2(n-1) + func2(n-2)
@time_me
def func3():
enter_region("func3 sleep")
time.sleep(0.1)
exit_region()
func1()
for i in range(1, 5):
print(func2(i))
func1()
travel(view)