6 import matplotlib.pyplot as plt
8 parser = argparse.ArgumentParser()
9 parser.add_argument('log_file')
10 parser.add_argument('-q', '--queue', help='plot queue size', action='store_true')
11 parser.add_argument('-e', '--encoder-threads', help='plot encoder thread activity', action='store_true')
12 parser.add_argument('-f', '--plot-first-encoder', help='plot more detailed activity of the first encoder thread', action='store_true')
13 parser.add_argument('--dump-first-encoder', help='dump activity of the first encoder thread', action='store_true')
14 parser.add_argument('--from', help='time in seconds to start at', type=int, dest='from_time')
15 parser.add_argument('--to', help='time in seconds to stop at', type=int, dest='to_time')
16 args = parser.parse_args()
18 def find_nth(haystack, needle, n):
19 start = haystack.find(needle)
20 while start >= 0 and n > 1:
21 start = haystack.find(needle, start+len(needle))
26 def __init__(self, s, m = 0):
31 return '%d:%d' % (self.seconds, self.microseconds)
33 def float_seconds(self):
34 return self.seconds + self.microseconds / 1000000.0
37 m = self.microseconds - x.microseconds
39 return Time(self.seconds - x.seconds - 1, m + 1000000)
41 return Time(self.seconds - x.seconds, m)
44 encoder_thread_events = dict()
46 def add_encoder_thread_event(thread, time, event):
47 global encoder_thread_events
48 if thread in encoder_thread_events:
49 encoder_thread_events[thread].append((time, event))
51 encoder_thread_events[thread] = [(time, event)]
53 f = open(args.log_file)
66 if len(p[0].split(':')) == 2:
69 T = Time(int(x[0]), int(x[1]))
70 message = l[l.find(' ')+1:]
73 s = find_nth(l, ':', 3)
74 T = Time(time.mktime(time.strptime(l[:s])))
83 if message.startswith('['):
84 thread = message.split()[0][1:-1]
85 message = message[message.find(' ')+1:]
87 if message.startswith('adding to queue of '):
88 queue_size.append((T, int(message.split()[4])))
89 elif message.startswith('encoder thread sleeps'):
90 add_encoder_thread_event(thread, T, 'sleep')
91 elif message.startswith('encoder thread wakes'):
92 add_encoder_thread_event(thread, T, 'wake')
93 elif message.startswith('encoder thread begins local encode'):
94 add_encoder_thread_event(thread, T, 'begin_encode')
95 elif message.startswith('MagickImageProxy begins decode and convert') or message.startswith('MagickImageProxy begins read and decode'):
96 add_encoder_thread_event(thread, T, 'magick_begin_decode')
97 elif message.startswith('MagickImageProxy decode finished'):
98 add_encoder_thread_event(thread, T, 'magick_end_decode')
99 elif message.startswith('MagickImageProxy completes decode and convert'):
100 add_encoder_thread_event(thread, T, 'magick_end_unpack')
101 elif message.startswith('encoder thread finishes local encode'):
102 add_encoder_thread_event(thread, T, 'end_encode')
109 x.append(q[0].seconds)
114 elif args.encoder_threads:
116 N = len(encoder_thread_events)
118 for thread, events in encoder_thread_events.iteritems():
124 if args.from_time is not None and e[0].float_seconds() <= args.from_time:
126 if args.to_time is not None and e[0].float_seconds() >= args.to_time:
128 x.append(e[0].float_seconds())
129 x.append(e[0].float_seconds())
135 elif e[1] == 'begin_encode':
137 elif e[1] == 'end_encode':
139 elif e[1] == 'magick_begin_decode':
141 elif e[1] == 'magick_end_decode':
150 elif args.plot_first_encoder:
152 N = len(encoder_thread_events)
154 events = encoder_thread_events.itervalues().next()
158 for t in ['sleep', 'wake', 'begin_encode', 'magick_begin_decode', 'magick_end_decode', 'end_encode']:
163 if args.from_time is not None and e[0].float_seconds() <= args.from_time:
165 if args.to_time is not None and e[0].float_seconds() >= args.to_time:
168 x.append(e[0].float_seconds())
169 x.append(e[0].float_seconds())
170 x.append(e[0].float_seconds())
180 elif args.dump_first_encoder:
181 events = encoder_thread_events.itervalues().next()
184 print e[0].float_seconds(), (e[0].float_seconds() - last), e[1]
185 last = e[0].float_seconds()