23 import matplotlib.pyplot
as plt
25 from playhouse.shortcuts
import model_to_dict
26 from typing
import List, Dict
27 from graphviz
import Digraph
30 CONV={
"us": 1000,
"ms": 1000*1000}
33 for i
in range(len(timeline)-1):
34 color = [
'red',
'green',
'blue',
'yellow',
'cyan'][i%5]
35 start = timeline[i][
'time']
36 end = timeline[i+1][
'time']
37 label = timeline[i][
'state']
39 plt.hlines(offset, start, end, colors=color, lw=5)
40 plt.text(start, offset, label, rotation=90)
42 start = timeline[0][
'time']
43 end = timeline[-1][
'time']
44 label = timeline[-1][
'state']
45 plt.text(end, offset, label, rotation=90)
47 center = (end-start)/2
48 label = timeline[0][
'op'] +
": " + str(round((end-start)/1000000,3)) +
"ms" 49 plt.text(start+center, offset+0.01, label)
54 for times
in time_table:
55 times.sort(key=
lambda time: time[
'time'])
58 ref_time = times[0][
'time']
60 ref_time =
min(times[0][
'time'], ref_time)
62 for times
in time_table:
64 time[
'time']=time[
'time']-ref_time
71 out.append(model_to_dict(m))
76 t[tag_name] = tag_value
77 queues_tag_append=times_tag_append
80 mx=
max([q[
'max']
for q
in queue])
81 mx=0.0000001
if mx == 0
else mx
83 qnr =[q[
'nr']
for q
in queue]
84 xdata=[q[
'time']
for q
in queue]
85 ydata=[q[
'avg']
for q
in queue]
86 _min =[q[
'min']
for q
in queue]
87 _max =[q[
'max']
for q
in queue]
88 dev =[math.sqrt(q[
'dev'])
for q
in queue]
89 avi =[q[
'avg']-math.sqrt(q[
'dev'])
for q
in queue]
90 ava =[q[
'avg']+math.sqrt(q[
'dev'])
for q
in queue]
92 plt.plot(xdata, [offset+y/mx
for y
in ydata],
'or')
93 plt.plot(xdata, [offset+y/mx
for y
in ydata],
'-', color=
'gray')
94 plt.fill_between(xdata,
95 [offset+y/mx
for y
in avi],
96 [offset+y/mx
for y
in ava], color=
'gray', alpha=0.2)
97 plt.fill_between(xdata,
98 [offset+y/mx
for y
in _min],
99 [offset+y/mx
for y
in _max], color=
'green', alpha=0.2)
101 for x,y,nr,i,a,d
in zip(xdata, ydata, qnr, _min, _max, dev ):
102 plt.text(x,offset+y/mx, f
"{round(y,2)} |{round(a,2)}|")
104 def draw_timelines(time_table, queue_table, client_start_time, queue_start_time,
105 time_unit: str, show_queues: bool, maximize: bool):
106 cursor={
"x0":0,
"y0":0,
"x1": 0,
"y1": 0,
"on":
False}
110 cursor.update({
"on":
True })
111 elif event.key ==
'd':
113 for an
in undo.pop():
117 def onrelease(event):
120 cursor.update({
"x1": event.xdata,
"y1": event.ydata })
121 cursor.update({
"on":
False })
123 an1=event.inaxes.axvspan(cursor[
"x0"], cursor[
"x1"], facecolor=
'0.9', alpha=.5)
124 an2=event.inaxes.annotate(
'', xy=(cursor[
"x0"], cursor[
"y0"]),
125 xytext=(cursor[
"x1"], cursor[
"y0"]),
126 xycoords=
'data', textcoords=
'data',
127 arrowprops={
'arrowstyle':
'|-|'})
128 an3=event.inaxes.annotate(str(round((cursor[
"x1"]-cursor[
"x0"])/CONV[time_unit],2))+f
" {time_unit}",
129 xy=(
min(cursor[
"x1"], cursor[
"x0"])+
130 abs(cursor[
"x1"]-cursor[
"x0"])/2, 0.5+cursor[
"y0"]),
131 ha=
'center', va=
'center')
132 undo.append([an1, an2, an3])
138 cursor.update({
"x0": event.xdata,
"y0": event.ydata })
141 fig.canvas.mpl_connect(
'key_press_event', onpress)
142 fig.canvas.mpl_connect(
'button_press_event', onclick)
143 fig.canvas.mpl_connect(
'button_release_event', onrelease)
146 plt.subplot({
True:211,
False:111}[show_queues])
148 for times
in time_table:
152 plt.yticks(np.arange(0.0, offset, -2), [t[0][
'op']
for t
in time_table])
157 for qt,subp,qstt
in zip(queue_table, [223,224], queue_start_time):
164 plt.axvline(x=(client_start_time-qstt))
165 plt.yticks(np.arange(0.0, offset, -2), [t[0][
'op']
for t
in qt])
170 mng = plt.get_current_fig_manager()
171 mng.window.maximize()
175 for q_conf
in [[
"runq",
"wail",
"fom-active"],
176 [
"stob-ioq-inflight",
"stob-ioq-queued"]]:
177 queue_table.append([])
178 loc_nr = queues.select(fn.MAX(queues.locality)).where(queues.type==q_conf[0]).scalar()
179 for nr
in range(loc_nr+1):
180 for queuei
in q_conf:
181 left = queues.select().where((queues.min>-1)
182 &(queues.locality==nr)
183 &(queues.type==queuei)
184 &(queues.time<client_start_time)).limit(qrange)
185 right = queues.select().where((queues.min>-1)
186 &(queues.locality==nr)
187 &(queues.type==queuei)
188 &(queues.time>=client_start_time)).limit(qrange)
189 stmt = [*left, *right]
192 _min = queues.select(fn.MIN(queues.min)).where((queues.min>-1)
193 &(queues.locality==nr)
194 &(queues.type==queuei)).scalar()
195 _max = queues.select(fn.MAX(queues.max)).where((queues.min>-1)
196 &(queues.locality==nr)
197 &(queues.type==queuei)).scalar()
198 queues_tag_append(q_d,
'op', f
"{queuei}#{nr}[{_min}..{_max}]")
199 queue_table[-1].append(q_d)
208 <TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4"> 217 label =
"<BR/>".join([f
"{k}={v}" for (k,v)
in attrs.items()])
218 g.node(name, node_template.format(header, label))
221 c =
lambda attr: re.sub(
"M0_AVI_.*_ATTR_",
"", attr)
222 attrd =
query2dlist(attr.select().where( (attr.entity_id==lid)
224 attrs = dict([(
c(a[
'name']), a[
'val'])
for a
in attrd])
228 def pid_get(lid_rec, flags: str):
230 return {
'C' : lid_rec[1],
231 'S' : lid_rec[2] }[pidt]
234 # relation | from | to | table or direct| flags 235 # | table/mapping | table/mapping | mapping | 236 schema = [("client_id" , "client_id" , "dix_id" , "" , "C1"), 237 ("cas_id" , "cas_id" , "rpc_id" , "cas_to_rpc" , "C" ), 238 ("crpc_id" , "crpc_id" , "srpc_id" , "" , "C1"), 239 ("crpc_id" , "rpc_id" , "bulk_id" , "bulk_to_rpc" , "Cs"), 240 ("srpc_id" , "srpc_id" , "fom_id" , "" , "S1"), 241 ("fom_id" , "fom_id" , "tx_id" , "" , "S1"), 242 ("tx_id" , "" , "" , "" , "Sl"), 243 ("fom_id" , "fom_id" , "crow_fom_id" , "" , "S1"), 244 ("crow_fom_id", "crow_fom_id", "crow_tx_id" , "" , "S1"), 245 ("crow_tx_id" , "" , "" , "" , "Sl")] 246 # flags: '1' - one to one mapping, 's' - stash samples, 'l' - leaf element 250 for rel,fr,to,map,flags
in schema:
251 layer_ids=set([(r[rel], r[
'cli_pid'], r[
'srv_pid'])
for r
in relations
if r[rel]
is not None])
252 for lid_rec
in layer_ids:
254 pid = pid_get(lid_rec, flags)
260 tid =
next(r[to]
for r
in relations
if r[fr]==lid)
262 graph.edge(f
"{lid}", f
"{tid}")
265 cursor = DB.execute_sql(f
"SELECT {to} FROM {map} WHERE {fr}={lid} and pid={pid}")
266 for (tid,)
in cursor:
267 graph.edge(f
"{lid}", f
"{tid}")
269 stash.append((tid,to,pid))
271 for lid,rel,pid
in stash:
def draw_queue_line(queue, offset)
def prepare_time_table(time_table)
static struct m0_addb2_callback c
static long long max(long long a, long long b)
static long long min(long long a, long long b)
def draw_timeline(timeline, offset)