尝试在循环中调用 None 上的方法对性能的影响
Performance impact on trying to call methods on None in a loop
让我们想象一下下面的代码
from pymaybe import maybe
def compute_something():
return np.sin(2)
def foo(observer=None):
observer = maybe(observer)
for i in range(0, int(1e3)):
something = compute_something()
observer.observe(something) # Comment this line for comparison
所以基本上我正在尝试某种控制反转,我传递一个实现接口的对象(这里是一个方法 observe
),但我想保留用户什么都不传递的可能性(因此默认参数值被定义为 maybe(None)
.
问题是:我应该期待一些性能影响吗?
我使用 timeit
来比较两者(调用和不调用 observe
):
Without a call to observe
:
1.77 ms ± 5.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
With a call to observe
:
3.27 ms ± 22.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
影响似乎很小,我假设 pymaybe
只是一个 try 块,所以我也与以下代码进行了比较:
def foo(observer=None):
observer = None
for i in range(0, int(1e3)):
something = compute_something()
try:
observer.observe(something)
except:
pass
foo()
结果如下:
With a call to observe
:
2.73 ms ± 66.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
所以我得出以下结论(不足为奇):
- pymaybe
通过在 try
块周围增加一层来增加一些开销
- try
块本身对性能有不可忽略的影响
如果我上面的 assumptions/conclusions 是正确的,有什么方法可以进一步提高性能?
我可以复制代码吗?
有没有办法 "remove" 在运行时调用 None
上的方法(在循环执行期间值不会改变的循环中)?
第一种方法是使用 if
语句,正如 Scott Hunter 所建议的那样 :
def foo(observer=None):
for i in range(0, int(1e3)):
something = compute_something()
if observer:
observer.observe(something)
您还可以在 observer.observe
周围使用默认不执行任何操作的包装器:
def foo(observer=None):
try:
observe = observer.observe
except AttributeError:
def observe(x):
pass
for i in range(0, int(1e3)):
something = compute_something()
observe(something)
在我的实验中,两种方法的 运行 次相似。
让我们想象一下下面的代码
from pymaybe import maybe
def compute_something():
return np.sin(2)
def foo(observer=None):
observer = maybe(observer)
for i in range(0, int(1e3)):
something = compute_something()
observer.observe(something) # Comment this line for comparison
所以基本上我正在尝试某种控制反转,我传递一个实现接口的对象(这里是一个方法 observe
),但我想保留用户什么都不传递的可能性(因此默认参数值被定义为 maybe(None)
.
问题是:我应该期待一些性能影响吗?
我使用 timeit
来比较两者(调用和不调用 observe
):
Without a call to
observe
:1.77 ms ± 5.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
With a call to
observe
:3.27 ms ± 22.6 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
影响似乎很小,我假设 pymaybe
只是一个 try 块,所以我也与以下代码进行了比较:
def foo(observer=None):
observer = None
for i in range(0, int(1e3)):
something = compute_something()
try:
observer.observe(something)
except:
pass
foo()
结果如下:
With a call to
observe
:2.73 ms ± 66.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
所以我得出以下结论(不足为奇):
- pymaybe
通过在 try
块周围增加一层来增加一些开销
- try
块本身对性能有不可忽略的影响
如果我上面的 assumptions/conclusions 是正确的,有什么方法可以进一步提高性能?
我可以复制代码吗?
有没有办法 "remove" 在运行时调用 None
上的方法(在循环执行期间值不会改变的循环中)?
第一种方法是使用 if
语句,正如 Scott Hunter 所建议的那样
def foo(observer=None):
for i in range(0, int(1e3)):
something = compute_something()
if observer:
observer.observe(something)
您还可以在 observer.observe
周围使用默认不执行任何操作的包装器:
def foo(observer=None):
try:
observe = observer.observe
except AttributeError:
def observe(x):
pass
for i in range(0, int(1e3)):
something = compute_something()
observe(something)
在我的实验中,两种方法的 运行 次相似。