Upload
emptysquare
View
2.501
Download
4
Embed Size (px)
DESCRIPTION
A smatter of performance tips for Python programs.
Citation preview
What I Know About Python Performance
A. Jesse Jiryu Davishttp://emptysqua.re
MongoDB
Agenda
• Single-threaded
• Multi-threaded
• Gevent
Single-Threaded
Why is Python slow? • Everything’s an object • Lookup
Everything’s an object
def f():! i = 2000! i += 1!
Everything’s an object
import dis!dis.dis(f)!
Everything’s an object
0 LOAD_CONST 1 (2000)! 3 STORE_FAST 0 (i)! 6 LOAD_FAST 0 (i)! 9 LOAD_CONST 2 (1)!12 INPLACE_ADD!13 STORE_FAST 0 (i)!
def f():! i = 2000! i += 1
Everything’s an object
0 LOAD_CONST 1 (2000)! 3 STORE_FAST 0 (i)! 6 LOAD_FAST 0 (i)! 9 LOAD_CONST 2 (1)!12 INPLACE_ADD!13 STORE_FAST 0 (i)!
malloc!
malloc!
def f():! i = 2000! i += 1
Everything’s an object
12 seconds for 100M numbers:
total = 0!for i in longs:! total += i!print float(total) / len(longs)
Everything’s an object
1 second for 100M numbers:
print float(sum(longs)) / len(longs)
Everything’s an object
0.2 seconds for 100M numbers:
print numpy.mean(array)
Lookup
n = 1!!
def f():! print n!
0 LOAD_GLOBAL 0 (n)! 3 PRINT_ITEM! 4 PRINT_NEWLINE
hashtable lookup
n = 1!!
def f():! print n!
array offset
n = 1!!
def f(n=n):! print n!
0 LOAD_FAST 0 (n)! 3 PRINT_ITEM! 4 PRINT_NEWLINE
Profiling
Profiling
import yappi!!yappi.start(builtins=True)!my_function()!yappi.stop()!stats = yappi.get_func_stats()!stats.save('yappi.callgrind', type='callgrind')!
KCacheGrind
KCacheGrind
Multi-threaded
Multi-threaded
When is the GIL released?• Every 100 bytecodes• Acquiring other locks • Network or file operations
Multi-threadedBecause:
socketmodule.c
Py_BEGIN_ALLOW_THREADS!outlen = recv(s->sock_fd, cbuf, len);!Py_END_ALLOW_THREADS!
Multi-threadedBecause:
socketmodule.c
Py_BEGIN_ALLOW_THREADS!outlen = recv(s->sock_fd, cbuf, len);!Py_END_ALLOW_THREADS!
release the GIL!
Multi-threadedThis makes sense:
threads = [! threading.Thread(target=download_a_url())! for _ in range(10)]!!for t in threads:! t.start()!!for t in threads:! t.join()!
Multi-threadedThis makes no sense:
threads = [! threading.Thread(target=do_calculations())! for _ in range(10)]!!for t in threads:! t.start()!!for t in threads:! t.join()!
Geventfrom gevent import monkey!monkey.patch_all()!!threads = [! threading.Thread(target=download_a_url())]!!for t in threads:! t.start()!!for t in threads:! t.join()! actually a greenlet
GreenletProfiler
Links
http://bit.ly/pythonperformance