[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
デコレータで実行時間を測る例のやつ (笑) を色々試してて気になった点や欲しい機能とかをいじってたらなんか後々使えそうな代物ができたので、docstring の書き方の練習も兼ねて公開してみることに。
sp = SimpleProfiler() とかして、
with sp:
pass
とするか、
@sp.profile
def foo():
pass
とすれば sp に測った実行時間やらカウントやらが記録されます。sp の各プロパティを読んで下さい。reset() で測った記録をリセットできます。使いたいという奇特な方は下記をコピペして simpleprofiler.py とかで各自保管して下さい。MITライセンスで扱って貰えば特に連絡などは要りません。
#!/usr/bin/env python3
# simpleprofiler.py - Simple profiler
#
# Copyright (c) 2019 Takayuki 'January June' Suwa
#
# This software is released under the MIT License.
# https://opensource.org/licenses/mit-license.php
# PEP 8 (for lexical)
#000000001111111111222222222233333333334444444444555555555566666666667777777777
#234567890123456789012345678901234567890123456789012345678901234567890123456789
# PEP 8 (for text)
#00000000111111111122222222223333333333444444444455555555556666666666777
#23456789012345678901234567890123456789012345678901234567890123456789012
"""Simple profiler."""
try:
from time import perf_counter_ns as _perf_counter_ns
_clock = lambda: _perf_counter_ns() * 1e-9
except ImportError:
try:
from time import perf_counter as _clock
except ImportError:
from time import clock as _clock
class SimpleProfiler(object):
"""Simple profiler implementation, as context mananger."""
__slots__ = "__started", "__elapsed_time", "__nested_level", \
"__entered_count", "__checked_count", "__raised_count", \
"__clicked_count"
def __init__(self):
self.__started, self.__elapsed_time, self.__nested_level, \
self.__entered_count, self.__checked_count, \
self.__raised_count, self.__clicked_count = 0.0, 0.0, 0, 0, 0,\
0, 0
def __repr__(self):
return "%s(%fsec, %d, %d, %d, %d)" % (self.__class__.__name__,
self.__elapsed_time, self.__entered_count, self.__checked_count,
self.__raised_count, self.__clicked_count)
@property
def elapsed_time(self):
"""Return the accumulated value of the elapsed time in second
around the region of the code, inside of this context.
"""
return self.__elapsed_time
@property
def entered_count(self):
"""Return the accumulated value of the counter which is
incremented by 1 when this context is entered.
"""
return self.__entered_count
@property
def checked_count(self):
"""Return the accumulated value of the counter which is
incremented by 1 when each time check has finished.
"""
return self.__checked_count
@property
def raised_count(self):
"""Return the accumulated value of the counter which is
incremented by 1 when each uncaught exception has been raised.
"""
return self.__raised_count
@property
def clicked_count(self):
"""Return the accumulated value of the counter which is
incremented by 1 when each 'click()' method has been called.
"""
return self.__clicked_count
def click(self):
"""Increment the number of times this method was called, by 1.
"""
self.__clicked_count += 1
def reset(self):
"""Reset the elapsed time and each counters, to the initial
state.
"""
self.__elapsed_time, self.__nested_level, self.__entered_count, \
self.__checked_count, self.__raised_count, \
self.__clicked_count = 0.0, 0, 0, 0, 0, 0
def __enter__(self):
"""Enter this context.
When re-entered an identical context, results of that time check
and counting are ignored.
"""
self.__entered_count += 1
self.__nested_level += 1
if self.__nested_level == 1:
self.__started = _clock()
def __exit__(self, exc_type, exc_val, exc_tb):
"""Exit from this context."""
if self.__nested_level == 1:
self.__elapsed_time += _clock() - self.__started
self.__checked_count += 1
if exc_type:
self.__raised_count += 1
self.__nested_level -= 1
def profile(self, func):
"""Decorate the below function as inside of this context."""
def wrapper(*args, **kwargs):
with self:
return func(*args, **kwargs)
return wrapper
if __name__ == "__main__":
print("\n[ SimpleProfiler demo ] Profiles the Fibonacci function!\n")
p = SimpleProfiler()
@p.profile
def fib(x):
return x if x < 2 else fib(x - 1) + fib(x - 2)
def fib_demo():
p.reset()
try:
for n in range(40):
p.reset()
print(" profiling fib(%d) in progress..."
% n, end="", flush=True)
print("\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b=%d, %f seconds elapsed\n"
" %d entered, %d checked, %d raised"
% (fib(n), p.elapsed_time, p.entered_count, \
p.checked_count, p.raised_count))
except KeyboardInterrupt:
print("\n***** aborted by user *****\n"
" %f seconds elapsed (until abort)\n"
" %d entered, %d checked, %d raised"
% (p.elapsed_time, p.entered_count, p.checked_count,
p.raised_count))
print("[normal (uncached) version]")
fib_demo()
from functools import lru_cache
@p.profile
@lru_cache()
def fib(x):
return x if x < 2 else fib(x - 1) + fib(x - 2)
print("\n[cached version]")
fib_demo()カレンダー
フリーエリア
最新コメント
最新記事
プロフィール
ブログ内検索
最古記事
P R