Open justdoit0823 opened 7 years ago
At least for me, it just depends on the complexity of the intermedia expressions.
For complex expressions, the use of intermedia variables makes logic simple and clear.
Yes, there may be another situation we may refer function arguments in later program. This can generate more LOAD_ATTR
instructions which is a bit more expensive operation. And I will use indirect reference in this situation. Can anyone give a detailed test?
According to masklinn, there are some jitters in the aboving test program, and I should write the test program with perf. The following are the details.
import perf
class A:
x = 1231
def direct_call(a_obj):
return a_obj.x * 2
def main():
runner = perf.Runner()
runner.bench_func('run direct benchmark', direct_call, A)
if __name__ == '__main__':
main()
import perf
class A:
x = 1231
def indirect_call(a_obj):
x = a_obj.x
return x * 2
def main():
runner = perf.Runner()
runner.bench_func('run indirect benchmark', indirect_call, A)
if __name__ == '__main__':
main()
Here are the perf stats on the same machine.
Total duration: 12.4 sec
Start date: 2017-08-06 07:44:31
End date: 2017-08-06 07:44:45
Raw value minimum: 124 ms
Raw value maximum: 182 ms
Number of calibration run: 1
Number of run with values: 20
Total number of run: 21
Number of warmup per run: 1
Number of value per run: 3
Loop iterations per value: 2^19
Total number of values: 60
Minimum: 236 ns
Median +- MAD: 266 ns +- 26 ns
Mean +- std dev: 264 ns +- 26 ns
Maximum: 347 ns
0th percentile: 236 ns (-11% of the mean) -- minimum
5th percentile: 236 ns (-11% of the mean)
25th percentile: 238 ns (-10% of the mean) -- Q1
50th percentile: 266 ns (+0% of the mean) -- median
75th percentile: 279 ns (+5% of the mean) -- Q3
95th percentile: 310 ns (+17% of the mean)
100th percentile: 347 ns (+31% of the mean) -- maximum
Number of outlier (out of 177 ns..339 ns): 1
Total duration: 13.0 sec
Start date: 2017-08-06 07:45:30
End date: 2017-08-06 07:45:45
Raw value minimum: 128 ms
Raw value maximum: 182 ms
Number of calibration run: 1
Number of run with values: 20
Total number of run: 21
Number of warmup per run: 1
Number of value per run: 3
Loop iterations per value: 2^19
Total number of values: 60
Minimum: 244 ns
Median +- MAD: 281 ns +- 18 ns
Mean +- std dev: 278 ns +- 28 ns
Maximum: 347 ns
0th percentile: 244 ns (-12% of the mean) -- minimum
5th percentile: 245 ns (-12% of the mean)
25th percentile: 246 ns (-11% of the mean) -- Q1
50th percentile: 281 ns (+1% of the mean) -- median
75th percentile: 293 ns (+5% of the mean) -- Q3
95th percentile: 328 ns (+18% of the mean)
100th percentile: 347 ns (+25% of the mean) -- maximum
Number of outlier (out of 176 ns..363 ns): 0
From the stats, we can get a more exact result about the bytecode's running speed difference., and direct reference is much faster at nano second level.
Always we may call a lot of functions in Python programs, and there may be a simple hesitate whether we should pass object's attribute value as function argument or pass a local variable which refers to the original value. It's not only about program performance, but the coding style as well. So I want to make a test on this situation.
The following is a simple test program.
And here are the results.
I run this test on an idle linode machine with environment
Linux localhost 4.9.15-x86_64-linode81 #1 SMP Fri Mar 17 09:47:36 EDT 2017 x86_64 x86_64 x86_64 GNU/Linux
. Their running duration are almost the same.When I dig into this two conditions, the direct reference should run a bit faster in theory. However it's not clear to see.
Here is the bytecode of direct reference call.
And here is the bytecode of indirect reference call.
There are two instructions
4 STORE_FAST 1 (x)
and6 LOAD_FAST 1 (x)
than direct reference call. An additional variable should be temporarily used and loaded as function's argument.From the test result, we may see that it doesn't matter which way you use to write the code if you care about performance. But I think it's more readable with an additional variable and pass by as indirect reference.
Oh, a coding style war is coming.