[scriptindex] Drop fallback if replace_document fails
[xapian.git] / xapian-maintainer-tools / perftest / draw_positions.py
blob9723373faa20ab253e05e50278d7811fdffd1aa2
1 #!/usr/bin/env python
3 import math
4 import re
5 import sys
6 import wx
8 class FileAccesses(object):
9 def __init__(self):
10 self.max_offset = 0
11 self.data = []
13 def append(self, start_time, elapsed, offset, count, optype):
14 self.data.append((start_time, elapsed, offset, count, optype))
15 if self.max_offset < offset + count:
16 self.max_offset = offset + count
18 def __iter__(self):
19 return iter(self.data)
21 class AllAccesses(object):
22 def __init__(self):
23 self.data = {}
24 self.total_io_time = 0
25 self.start_time = None
26 self.total_time = 0
28 def append(self, filename, start_time, elapsed, offset, count, optype):
29 if self.start_time is None:
30 self.start_time = start_time
31 start_time -= self.start_time
33 fileaccesses = self.data.get(filename, None)
34 if fileaccesses is None:
35 fileaccesses = FileAccesses()
36 self.data[filename] = fileaccesses
38 fileaccesses.append(start_time, elapsed, offset, count, optype)
39 self.total_time = max(self.total_time, start_time + elapsed)
40 self.total_io_time += elapsed
42 def files_count(self):
43 return len(self.data)
45 def sum_max_offset(self):
46 return sum(x.max_offset for x in self.data.itervalues())
48 def __iter__(self):
49 keys = self.data.keys()
50 keys.sort()
51 for key in keys:
52 yield key, self.data[key]
54 def __len__(self):
55 return len(self.data)
57 class DrawPanel(wx.Panel):
58 """draw a line on a panel's wx.PaintDC surface/canvas"""
59 def __init__(self, parent, data):
60 wx.Panel.__init__(self, parent, -1)
61 # bind the panel to the paint event
62 wx.EVT_PAINT(self, self.onPaint)
64 self.data = data
66 def onPaint(self, event=None):
67 # this is the wx drawing surface/canvas
68 dc = wx.PaintDC(self)
69 dc.Clear()
71 wid, hgt = self.GetClientSizeTuple()
72 left = 10
73 bot = 10
74 top = 10
75 right = 10
77 titlehgt = 20
79 xscale = float(wid - left - right) / self.data.total_time
80 yscale = float(hgt - top - bot - titlehgt * len(self.data)) / self.data.sum_max_offset()
82 pointwid = 1
83 print "Drawing: green=read<1ms, red=read>1ms, blue=write, lightblue=sync"
84 dc.SetPen(wx.Pen("grey", 1))
85 dc.SetBrush(wx.Brush("#eeeeee"))
86 dc.DrawRectangle(0, 0, wid, hgt)
88 counts = [0, 0, 0]
89 maxoffset_sum = 0
90 for num, (filename, data) in enumerate(self.data):
91 base_y = int(math.floor(num * titlehgt + (bot + yscale * maxoffset_sum)))
92 top_y = int(math.ceil(base_y + (yscale * data.max_offset)))
94 dc.SetPen(wx.Pen("grey", 1))
95 dc.SetBrush(wx.Brush("white"))
96 dc.DrawRectangle(left - 1, hgt - (top_y + 1), wid + 2 - right - left, top_y - base_y + 2)
97 twid, thgt = dc.GetTextExtent(filename)
98 dc.DrawText(filename, 0, hgt - (top_y + thgt))
100 maxoffset_sum += data.max_offset
102 for starttime, elapsed, offset, count, optype in data:
103 xpos = left + xscale * starttime
104 pointwid = xscale * elapsed
105 if pointwid < 1: pointwid = 1
107 if optype == 'w':
108 dc.SetPen(wx.Pen("blue", 1))
109 counts[2] += 1
110 y = base_y + (yscale * offset)
111 dc.DrawLine(xpos, hgt - y, xpos + pointwid, hgt - y)
113 elif optype == 'r':
114 if elapsed < 1000:
115 dc.SetPen(wx.Pen("dark green", 1))
116 counts[0] += 1
117 else:
118 dc.SetPen(wx.Pen("red", 1))
119 counts[1] += 1
120 y = base_y + (yscale * offset)
121 dc.DrawLine(xpos, hgt - y, xpos + pointwid, hgt - y)
123 elif optype == 's':
124 dc.SetPen(wx.Pen("light blue", 1))
125 dc.DrawLine(xpos, hgt - base_y, xpos, hgt - top_y)
127 print "Drawn: [green, red, blue] =", counts
128 if counts[1] > 0:
129 print "blue/red =", float(counts[0]) / counts[1]
131 def show_data(app, data, title):
132 frame = wx.Frame(None, -1, title, size=(1500, 1000))
133 dp = DrawPanel(frame, data)
134 frame.Show(True)
136 def read_data(filename):
137 fd = open(filename)
138 fds = {}
139 try:
140 data = AllAccesses()
141 just_seeked = None
142 for line in fd:
143 line = line.strip()
144 optype = line[0]
145 fdnum, start, elapsed, line = line[1:].split(',', 3)
146 fdnum = int(fdnum)
147 start = int(start)
148 elapsed = int(elapsed)
150 if optype == 'o':
151 filename = line
152 fds[fdnum] = filename
153 continue
155 filename = fds.get(fdnum, str(fdnum))
157 if optype == 'r':
158 offset, count = map(int, line.split(',', 1))
159 data.append(filename, start, elapsed, offset, count, optype)
160 continue
162 if optype == 'w':
163 offset, count = map(int, line.split(',', 1))
164 data.append(filename, start, elapsed, offset, count, optype)
165 continue
167 if optype == 's':
168 data.append(filename, start, elapsed, 0, 0, optype)
169 continue
171 return data
172 finally:
173 fd.close()
175 if __name__ == '__main__':
176 app = wx.App()
177 # data file should be produced by strace -T
178 filename = sys.argv[1]
179 data = read_data(filename)
180 print "Total IO time = %fs" % (float(data.total_io_time) / 1000000.0)
181 print "Total time = %fs" % (float(data.total_time) / 1000000.0)
182 show_data(app, data, "%d io calls, from %s" % (len(data), filename))
183 app.MainLoop()