Use the optimizer to improve the execution efficiency of Python programs.
It would be unwise to start optimization without first thinking about the famous saying of Knuth. However, you can quickly write code that adds some features, which may be ugly. You need to pay attention to it. This article is prepared for this time.
Then there are some useful tools and modes to quickly optimize Python. Its main goal is to quickly identify bottlenecks, fix them, and confirm that you have fixed them.
Write a test
Before you begin optimization, write an advanced test to prove that the original code is slow. It is slow enough to reproduce a dataset with a minimum value. Generally, one or two programs that display runtime seconds are enough to handle some improvements.
Some basic tests are also necessary to ensure that your optimization does not change the original code. You can also slightly modify the benchmarks of these tests when you run many tests to optimize the code.
Now let's take a look at the optimization tool.
Simple Timer
The timer is simple. This is the most flexible way to record the execution time. You can place it anywhere with little side effects. Running your timer is very simple, and you can customize it to make it work as expected. For example, a simple timer is as follows:
import time def timefunc(f): def f_timer(*args, **kwargs): start = time.time() result = f(*args, **kwargs) end = time.time() print f.__name__, 'took', end - start, 'time' return result return f_timer def get_number(): for x in xrange(5000000): yield x @timefuncdef expensive_function(): for x in get_number(): i = x ^ x ^ x return 'some result!' # prints "expensive_function took 0.72583088875 seconds"result = expensive_function()
Of course, you can use context management to make it more powerful. You can add some checkpoints or other features:
import time class timewith(): def __init__(self, name=''): self.name = name self.start = time.time() @property def elapsed(self): return time.time() - self.start def checkpoint(self, name=''): print '{timer} {checkpoint} took {elapsed} seconds'.format( timer=self.name, checkpoint=name, elapsed=self.elapsed, ).strip() def __enter__(self): return self def __exit__(self, type, value, traceback): self.checkpoint('finished') pass def get_number(): for x in xrange(5000000): yield x def expensive_function(): for x in get_number(): i = x ^ x ^ x return 'some result!' # prints something like:# fancy thing done with something took 0.582462072372 seconds# fancy thing done with something else took 1.75355315208 seconds# fancy thing finished took 1.7535982132 secondswith timewith('fancy thing') as timer: expensive_function() timer.checkpoint('done with something') expensive_function() expensive_function() timer.checkpoint('done with something else') # or directlytimer = timewith('fancy thing')expensive_function()timer.checkpoint('done with something')
Timer also requires you to do some digging. Wrap some more advanced functions, determine the bottleneck, and then go deep into the functions for continuous reproduction. When you find some inappropriate code, fix it, and test it again to confirm that it has been fixed.
TIPS: Don't forget the useful timeit module! It is more useful for benchmarking small pieces of code than for actual surveys.
- Advantages of Timer: it is easy to understand and implement. It is also very easy to compare after modification. Applicable to many languages.
- Timer disadvantages: sometimes it is too simple for very complex code. You may spend more time placing or moving the referenced code instead of fixing the problem!
Built-in Optimizer
Enabling the built-in optimizer is like using a cannon. It is very powerful, but not very easy to use. It is complicated to use and explain.
You can understand