Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorMark Probst <mark.probst@gmail.com>2014-10-08 23:28:57 +0400
committerMark Probst <mark.probst@gmail.com>2014-11-26 21:38:46 +0300
commita3e7d28caa7704b45bddc2c3c647078844a2a62e (patch)
tree68cfde5d7d77cfa3437482184f24357964880419 /tools
parent4318dac63c3ae2b2d1ab8ad9989a706420ace9e2 (diff)
[sgen] Nicer visualization of concurrent collector pauses in gcpausevis.py.
Diffstat (limited to 'tools')
-rwxr-xr-xtools/sgen/gcpausevis.py223
1 files changed, 168 insertions, 55 deletions
diff --git a/tools/sgen/gcpausevis.py b/tools/sgen/gcpausevis.py
index a309e02093d..52f0ab26ee3 100755
--- a/tools/sgen/gcpausevis.py
+++ b/tools/sgen/gcpausevis.py
@@ -40,6 +40,22 @@ if len (files) != 1:
data = []
+class Event:
+ def __init__(self, **kwargs):
+ self.minor_work = kwargs['minor_work']
+ self.major_work = kwargs['major_work']
+ self.start = kwargs['start']
+ self.stop = kwargs['stop']
+ self.gc_type = kwargs['gc_type']
+ def __repr__(self):
+ return 'Event(minor_work={}, major_work={}, start={}, stop={}, gc_type={})'.format(
+ self.minor_work,
+ self.major_work,
+ self.start,
+ self.stop,
+ self.gc_type,
+ )
+
grep_input = open (files [0])
proc = subprocess.Popen ([sgen_grep_path, '--pause-times'], stdin = grep_input, stdout = subprocess.PIPE)
for line in iter (proc.stdout.readline, ''):
@@ -61,87 +77,184 @@ for line in iter (proc.stdout.readline, ''):
minor_work = True
if concurrent:
major_work = True
- gctype = "nursery+update"
+ gc_type = "nursery+update"
else:
- gctype = "nursery"
+ gc_type = "nursery"
else:
major_work = True
if concurrent:
if finish:
minor_work = True
- gctype = "nursery+finish"
+ gc_type = "nursery+finish"
else:
- gctype = "start"
+ gc_type = "start"
else:
- gctype = "full"
+ gc_type = "full"
- rec = (minor_work, major_work, start, start + msecs, kind, gctype)
+ rec = Event(
+ minor_work=minor_work,
+ major_work=major_work,
+ start=start,
+ stop=start + msecs,
+ kind=kind,
+ gc_type=gc_type,
+ )
print rec
data.append (rec)
+class MajorGCEventGroup:
+ pass
+
+class FullMajorGCEventGroup(MajorGCEventGroup):
+ def __init__(self, event):
+ self.event = event
+ def __repr__(self):
+ return 'FullMajorGCEventGroup({})'.format(
+ self.event,
+ )
+
+class ConcurrentMajorGCEventGroup(MajorGCEventGroup):
+ def __init__(self, start, updates, finish):
+ self.start = start
+ self.updates = updates
+ self.finish = finish
+ def __repr__(self):
+ return 'ConcurrentMajorEventGroup({}, {}, {})'.format(
+ self.start,
+ self.updates,
+ self.finish,
+ )
+
+# ([Event], int) -> (MajorGCEventGroup, int) | None
+def parse_next_major_gc(data, i):
+ assert i >= 0
+ # Find start or full event.
+ while i < len(data) and data[i].gc_type not in ['start', 'full']:
+ i += 1
+ if i == len(data):
+ return None
+ # If full event, done.
+ if data[i].gc_type == 'full':
+ return (FullMajorGCEventGroup(data[i]), i + 1)
+ start_event = data[i]
+ update_events = []
+ # Filter update events and find finish event.
+ while i < len(data) and data[i].gc_type != 'nursery+finish':
+ if data[i].gc_type == 'nursery+update':
+ update_events.append(data[i])
+ i += 1
+ if i == len(data):
+ return None
+ finish_event = data[i]
+ i += 1
+ return (ConcurrentMajorGCEventGroup(start_event, update_events, finish_event), i)
+
+# [Event] -> [MajorGCEventGroup]
+def parse_major_gcs(data):
+ major_gc_events = []
+ i = 0
+ while True:
+ maybe_event_group = parse_next_major_gc(data, i)
+ if maybe_event_group is None:
+ return major_gc_events
+ event_group, i = maybe_event_group
+ major_gc_events.append(event_group)
+
if show_histogram:
minor_pausetimes = []
major_pausetimes = []
for rec in data:
- (minor_work, major_work, start_ts, finish_ts, kind, gctype) = rec
- pause = finish_ts - start_ts
- if minor_work and major_work and show_minor and show_major:
+ pause = rec.stop - rec.start
+ if rec.minor_work and rec.major_work and show_minor and show_major:
major_pausetimes.append (pause)
else:
- if minor_work:
+ if rec.minor_work:
minor_pausetimes.append (pause)
- if major_work:
+ if rec.major_work:
major_pausetimes.append (pause)
pausetimes = []
+ colors = []
if show_minor:
- pausetimes += minor_pausetimes
+ pausetimes.append(minor_pausetimes)
+ colors.append('blue')
if show_major:
- pausetimes += major_pausetimes
- plt.hist (pausetimes, 100)
+ pausetimes.append(major_pausetimes)
+ colors.append('red')
+
+ plt.hist (pausetimes, 100, stacked=True, log=True, color=colors)
plt.xlabel ('Pause time in msec')
else:
- data = np.array (data, dtype = [('caption', '|S20'), ('start', int), ('stop', int), ('kind', '|S20')])
- cap, start, stop=data['caption'], data['start'], data['stop']
-
- #Check the status, because we paint all lines with the same color
- #together
- is_sync= (data['kind']=='SYNC')
- not_sync=np.logical_not(is_sync)
-
- #Get unique captions and there indices and the inverse mapping
- captions, unique_idx, caption_inv=np.unique(cap, 1,1)
- print captions
-
- #Build y values from the number of unique captions.
- y=(caption_inv+1)/float(len(captions)+1)
-
- #Plot function
- def timelines(y, xstart, xstop,color='b'):
- """Plot timelines at y from xstart to xstop with given color."""
- plt.hlines(y,xstart,xstop,color,lw=4)
- plt.vlines(xstart, y+0.03,y-0.03,color,lw=2)
- plt.vlines(xstop, y+0.03,y-0.03,color,lw=2)
-
- #Plot ok tl black
- timelines(y[is_sync],start[is_sync],stop[is_sync],'r')
- #Plot fail tl red
- timelines(y[not_sync],start[not_sync],stop[not_sync],'k')
-
- #Setup the plot
- ax=plt.gca()
- #ax.xaxis_date()
- #myFmt = DateFormatter('%H:%M:%S')
- #ax.xaxis.set_major_formatter(myFmt)
- #ax.xaxis.set_major_locator(SecondLocator(0,interval=20))
-
- #To adjust the xlimits a timedelta is needed.
- delta=(stop.max()-start.min())/10
-
- plt.yticks(y[unique_idx],captions)
- plt.ylim(0,1)
- plt.xlim(start.min()-delta, stop.max()+delta)
- plt.xlabel('Time')
+ major_gc_event_groups = parse_major_gcs(data)
+
+ def bar(**kwargs):
+ indices = kwargs['indices']
+ pauses = kwargs['pauses']
+ color = kwargs['color']
+ if 'bottom' in kwargs:
+ bottom = kwargs['bottom']
+ else:
+ bottom = 0
+ plt.bar(
+ [index for index in indices if pauses[index] is not None],
+ np.array([pause for pause in pauses if pause is not None]),
+ color=color,
+ bottom=bottom,
+ )
+
+ indices = np.arange(len(major_gc_event_groups))
+ start_pauses = [
+ event_group.start.stop - event_group.start.start
+ if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
+ for event_group in major_gc_event_groups
+ ]
+ bar(
+ indices=indices,
+ pauses=start_pauses,
+ color='red',
+ )
+ update_pauses = [
+ sum([
+ update_event.stop - update_event.start
+ for update_event in event_group.updates
+ ]) if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
+ for event_group in major_gc_event_groups
+ ]
+ bar(
+ indices=indices,
+ pauses=update_pauses,
+ color='green',
+ bottom=[pause for pause in start_pauses if pause is not None],
+ )
+ finish_pauses = [
+ event_group.finish.stop - event_group.finish.start
+ if isinstance(event_group, ConcurrentMajorGCEventGroup) else None
+ for event_group in major_gc_event_groups
+ ]
+ start_update_pauses = [
+ a + b
+ for a, b in zip(start_pauses, update_pauses)
+ if a is not None and b is not None
+ ]
+ bar(
+ indices=indices,
+ pauses=finish_pauses,
+ color='blue',
+ bottom=start_update_pauses,
+ )
+ full_pauses = [
+ event_group.event.stop - event_group.event.start
+ if isinstance(event_group, FullMajorGCEventGroup) else None
+ for event_group in major_gc_event_groups
+ ]
+ bar(
+ indices=indices,
+ pauses=full_pauses,
+ color='black',
+ )
+
+ plt.ylabel("Pause Time (ms)")
+ plt.xlabel("Collection")
plt.show()