我正在考虑将一些可选的日志记录代码添加到我的软件中。我预计大多数时候它会被禁用,所以我对快速路径非常感兴趣。
通常的先编写再优化的方法在这种情况下并不理想,因为代码的目的是使日志记录足够便宜,以便使用我的软件的开发人员愿意将其放入用户可以使用的一些紧密循环中发布后不妨一探究竟。因此,首先花一些时间进行优化对我来说实际上是有意义的。
我一直在使用 timeit 模块来确定最佳前进路径。我发现最优化的方法是使用一个带有标志的局部变量来指示是否运行代码。代码如下:
flag = logger.shouldLog # loookup the variable once
while True:
... do some operations in a tight loop
if flag:
logger.log(x, y, z)
我将其称为我的引用时间,因此它在 1.0 时间执行。
问题 1:有没有比编写两个函数(一个有日志记录一个没有)更快的条件日志记录方法?
我看过的替代方案涉及查找变量,例如
while True:
... do some operations
if logger.shouldLog:
logger.log(x, y, z)
运行时间约为 32.5 次....由于查找而慢得多
我还查看了一个函数调用有多糟糕:
while True:
... do some operations
if logger.shouldLog(): # simply returns False in my test case
logger.log(x, y, z)
这运行了 135 次,比简单的查找慢了大约 4 倍
问题 2:有什么方法可以加快我在这里的查找速度,以便我可以为用户提供更多选择?
我希望有更多的粒度,这样那些只想要一个快速而肮脏的日志记录解决方案的用户可以像我展示的后两种情况那样编写一些简单的东西(或者甚至更慢,只需在快速路径),但对于性能很重要的关键代码部分,我希望有一些执行速度介于第一种情况和第二种情况之间的东西。
最佳答案
使用 __debug__
变量并在日志记录不重要时优化 python 执行:
def log(x, y):
print(x, y)
def doit():
a = range(100)
sum_ = 0
for item1 in a:
for item2 in a:
if __debug__:
log(item1, item2)
sum_ += item1 + item2
return sum_
if __name__ == '__main__':
doit()
如果您将此脚本作为 python testscript.py
运行,那么它会打印
所有这些内容。如果你将它称为 python -O testscripy.py
那么它不会打印任何东西,因为 -O
删除所有 __debug__
部分。
时间:
$ python -O -m timeit "from testscript1 import doit" "doit()"
100 loops, best of 3: 2.6 msec per loop
如果我从文件中删除 if __debug__: log(item1, item2)
时间为:
$ python -O -m timeit "from testscript2 import doit" "doit()"
100 loops, best of 3: 2.61 msec per loop
如果我用一些自定义变量替换 __debug__
这肯定会更慢:
$ python -O -m timeit "from testscript3 import doit" "doit()"
100 loops, best of 3: 3.41 msec per loop
关于python - 在 Python 中查找最快的条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39836750/