2 import matplotlib.pyplot as plt
3 from matplotlib.dates import DateFormatter, MinuteLocator, SecondLocator
5 from StringIO import StringIO
9 from optparse import OptionParser
12 parser = OptionParser (usage = "Usage: %prog [options] BINARY-PROTOCOL")
13 parser.add_option ('--histogram', action = 'store_true', dest = 'histogram', help = "pause time histogram")
14 parser.add_option ('--minor', action = 'store_true', dest = 'minor', help = "only show minor collections in histogram")
15 parser.add_option ('--major', action = 'store_true', dest = 'major', help = "only show major collections in histogram")
16 (options, files) = parser.parse_args ()
18 show_histogram = False
30 script_path = os.path.realpath (__file__)
31 sgen_grep_path = os.path.join (os.path.dirname (script_path), 'sgen-grep-binprot')
33 if not os.path.isfile (sgen_grep_path):
34 sys.stderr.write ('Error: `%s` does not exist.\n' % sgen_grep_path)
44 def __init__(self, **kwargs):
45 self.minor_work = kwargs['minor_work']
46 self.major_work = kwargs['major_work']
47 self.start = kwargs['start']
48 self.stop = kwargs['stop']
49 self.gc_type = kwargs['gc_type']
51 return 'Event(minor_work={}, major_work={}, start={}, stop={}, gc_type={})'.format(
59 grep_input = open (files [0])
60 proc = subprocess.Popen ([sgen_grep_path, '--pause-times'], stdin = grep_input, stdout = subprocess.PIPE)
61 for line in iter (proc.stdout.readline, ''):
62 m = re.match ('^pause-time (\d+) (\d+) (\d+) (\d+) (\d+)', line)
64 minor_work = major_work = False
65 generation = int (m.group (1))
66 concurrent = int (m.group (2)) != 0
67 finish = int (m.group (3)) != 0
68 msecs = int (m.group (4)) / 10.0 / 1000.0
69 start = int (m.group (5)) / 10.0 / 1000.0
80 gc_type = "nursery+update"
88 gc_type = "nursery+finish"
95 minor_work=minor_work,
96 major_work=major_work,
105 class MajorGCEventGroup:
108 class FullMajorGCEventGroup(MajorGCEventGroup):
109 def __init__(self, event):
112 return 'FullMajorGCEventGroup({})'.format(
116 class ConcurrentMajorGCEventGroup(MajorGCEventGroup):
117 def __init__(self, start, updates, finish):
119 self.updates = updates
122 return 'ConcurrentMajorEventGroup({}, {}, {})'.format(
128 # ([Event], int) -> (MajorGCEventGroup, int) | None
129 def parse_next_major_gc(data, i):
131 # Find start or full event.
132 while i < len(data) and data[i].gc_type not in ['start', 'full']:
136 # If full event, done.
137 if data[i].gc_type == 'full':
138 return (FullMajorGCEventGroup(data[i]), i + 1)
139 start_event = data[i]
141 # Filter update events and find finish event.
142 while i < len(data) and data[i].gc_type != 'nursery+finish':
143 if data[i].gc_type == 'nursery+update':
144 update_events.append(data[i])
148 finish_event = data[i]
150 return (ConcurrentMajorGCEventGroup(start_event, update_events, finish_event), i)
152 # [Event] -> [MajorGCEventGroup]
153 def parse_major_gcs(data):
157 maybe_event_group = parse_next_major_gc(data, i)
158 if maybe_event_group is None:
159 return major_gc_events
160 event_group, i = maybe_event_group
161 major_gc_events.append(event_group)
164 minor_pausetimes = []
165 major_pausetimes = []
168 pause = rec.stop - rec.start
169 if rec.minor_work and rec.major_work and show_minor and show_major:
170 major_pausetimes.append (pause)
173 minor_pausetimes.append (pause)
175 major_pausetimes.append (pause)
180 pausetimes.append(minor_pausetimes)
181 colors.append('blue')
183 pausetimes.append(major_pausetimes)
186 plt.hist (pausetimes, 100, stacked=True, log=True, color=colors)
187 plt.xlabel ('Pause time in msec')
189 major_gc_event_groups = parse_major_gcs(data)
192 indices = kwargs['indices']
193 pauses = kwargs['pauses']
194 color = kwargs['color']
195 if 'bottom' in kwargs:
196 bottom = kwargs['bottom']
200 [index for index in indices if pauses[index] is not None],
201 np.array([pause for pause in pauses if pause is not None]),
206 indices = np.arange(len(major_gc_event_groups))
208 event_group.start.stop - event_group.start.start
209 if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
210 for event_group in major_gc_event_groups
219 update_event.stop - update_event.start
220 for update_event in event_group.updates
221 ]) if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
222 for event_group in major_gc_event_groups
226 pauses=update_pauses,
228 bottom=[pause for pause in start_pauses if pause is not None],
231 event_group.finish.stop - event_group.finish.start
232 if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
233 for event_group in major_gc_event_groups
235 start_update_pauses = [
237 for a, b in zip(start_pauses, update_pauses)
238 if a is not None and b is not None
242 pauses=finish_pauses,
244 bottom=start_update_pauses,
247 event_group.event.stop - event_group.event.start
248 if isinstance(event_group, FullMajorGCEventGroup) else None
249 for event_group in major_gc_event_groups
257 plt.ylabel("Pause Time (ms)")
258 plt.xlabel("Collection")