Last active
December 24, 2015 15:29
-
-
Save jamesls/6820952 to your computer and use it in GitHub Desktop.
thread stack traces make it hard to see CPU bound problems. Run the script with no args, and read the bottom comment in each stack trace (there are three threads so you'll see three stack traces). Note that despite taking almost 100% CPU, the stack traces show the worker thread sleeping.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime | |
import time | |
import sys | |
import threading | |
import traceback | |
import subprocess | |
import random | |
def clear_screen(): | |
sys.stdout.write(chr(27) + "[2J") | |
sys.stdout.flush() | |
def _dump_thread_stacks(): | |
clear_screen() | |
sys.stdout.write("\n*** STACKTRACE - START %s ***\n\n" % datetime.datetime.now()) | |
code = [] | |
for thread_id, stack in sys._current_frames().items(): | |
code.append("\n# ThreadID: %s" % thread_id) | |
for filename, lineno, name, line in traceback.extract_stack(stack): # THIS IS THE MONITORING THREAD | |
code.append('File: "%s", line %d, in %s' % (filename, | |
lineno, name)) | |
if line: | |
code.append(" %s" % (line.strip())) | |
for line in code: | |
sys.stdout.write(line) | |
sys.stdout.write("\n") | |
sys.stdout.write("\n*** STACKTRACE - END ***\n\n") | |
def monitor(): | |
while True: | |
time.sleep(1) | |
_dump_thread_stacks() | |
def misbehave(): | |
while True: | |
# Release the gil, so this is all you'll see. | |
time.sleep(0.0001) # THIS IS WHAT YOU'LL PROBABLY SEE IN THE THREAD STACK TRACE | |
# Thousands of lines later, many function | |
# calls away... | |
_waste_cpu() # THIS IS WHAT YOU'D LIKE TO SEE | |
def _waste_cpu(): | |
for i in xrange(50000): | |
'the' + 'real' + 'problem' + 'here' | |
def start(): | |
bad_thread = threading.Thread(target=misbehave) | |
bad_thread.daemon = True | |
monitor_thread = threading.Thread(target=monitor) | |
monitor_thread.daemon = True | |
bad_thread.start() | |
monitor_thread.start() | |
while True: | |
time.sleep(1) # THIS IS THE MAIN THREAD | |
start() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment