22 from typing
import List, Dict
23 from graphviz
import Digraph
24 from req_utils
import *
27 def graph_build(relations, ext_graph: Digraph=
None, is_cob: bool=
False):
33 graph = ext_graph
if ext_graph
is not None else Digraph(
34 strict=
True, format=
'png', node_attr = {
'shape':
'plaintext'})
38 schema = [(
"client_id",
"client_id", f
"{t}_id" , f
"client_to_{t}",
"C"),
39 (f
"{t}_id" , f
"{t}_id" ,
"rpc_id" , f
"{t}_to_rpc" ,
"C"),
40 (
"crpc_id" ,
"crpc_id" ,
"srpc_id" ,
"" ,
"C1"),
41 (
"crpc_id" ,
"rpc_id" ,
"bulk_id" ,
"bulk_to_rpc" ,
"Cs"),
42 (
"srpc_id" ,
"srpc_id" ,
"fom_id" ,
"" ,
"S1"),
43 (
"fom_id" ,
"fom_id" ,
"stio_id" ,
"fom_to_stio" ,
"S"),
44 (
"stio_id" ,
"" ,
"" ,
"" ,
"Sl"),
45 (
"fom_id" ,
"fom_id" ,
"tx_id" ,
"" ,
"S1"),
46 (
"tx_id" ,
"" ,
"" ,
"" ,
"Sl")]
52 graph.render(filename=
"{}_graph_{}".
format(t, relations[0][
'client_id']))
62 DISTINCT({io_req_type}_to_rpc.rpc_id), 63 client_to_{io_req_type}.client_id, 64 client_to_{io_req_type}.{io_req_type}_id, 66 rpc_to_sxid.xid, rpc_to_sxid.session_id, 67 sxid_to_rpc.xid, sxid_to_rpc.session_id, 68 fom_desc.rpc_sm_id, fom_desc.fom_sm_id, fom_desc.fom_state_sm_id, 72 client_to_{io_req_type}.pid, 75 FROM client_to_{io_req_type} 76 JOIN {io_req_type}_to_rpc on client_to_{io_req_type}.{io_req_type}_id={io_req_type}_to_rpc.{io_req_type}_id 77 JOIN rpc_to_sxid on rpc_to_sxid.id={io_req_type}_to_rpc.rpc_id 78 JOIN sxid_to_rpc on rpc_to_sxid.xid=sxid_to_rpc.xid AND rpc_to_sxid.session_id=sxid_to_rpc.session_id 79 JOIN fom_desc on sxid_to_rpc.id=fom_desc.rpc_sm_id 80 LEFT JOIN fom_to_tx on fom_desc.fom_sm_id=fom_to_tx.fom_id 81 LEFT JOIN fom_to_stio on fom_desc.fom_sm_id=fom_to_stio.fom_id 82 LEFT JOIN tx_to_gr on fom_to_tx.tx_id=tx_to_gr.tx_id 84 WHERE sxid_to_rpc.opcode in {opcodes} and rpc_to_sxid.opcode in {opcodes} 85 AND rpc_to_sxid.xid > 0 86 AND rpc_to_sxid.session_id > 0 88 AND client_to_{io_req_type}.pid={io_req_type}_to_rpc.pid AND client_to_{io_req_type}.pid=rpc_to_sxid.pid 90 AND sxid_to_rpc.pid=fom_desc.pid 91 AND (fom_to_stio.stio_id is NULL OR fom_desc.pid=fom_to_stio.pid) 92 AND (fom_to_tx.tx_id is NULL OR fom_desc.pid=fom_to_tx.pid) 93 AND (tx_to_gr.gr_id is NULL OR fom_desc.pid=tx_to_gr.pid) 95 AND client_to_{io_req_type}.client_id={client_id}; 98 def get_timelines(client_id: str, grange: int, client_pid: int=
None, create_attr_graph: bool=
False,
99 export_only: bool=
False, ext_graph: Digraph=
None, is_cob: bool=
False):
102 queue_start_time = []
103 client_start_time = 0
108 opcodes =
"(45,46,47,128,130)" 109 io_req_table = cob_req
112 opcodes =
"(41,42,45,46,47)" 113 io_req_table = ioo_req
115 pid_filter = f
"AND client_to_{io_req_type}.pid={client_pid}" if client_pid
is not None else "" 116 query = query_template.format(io_req_type=io_req_type, opcodes=opcodes,
117 client_id=client_id, pid_filter=pid_filter)
120 cursor = DB.execute_sql(query)
121 fields =
list(cursor.fetchall())
122 labels = (
"crpc_id",
"client_id", f
"{io_req_type}_id",
"opcode",
"cxid",
123 "csess",
"sxid",
"ssess",
"srpc_id",
"fom_id",
124 "fom_state_id",
"tx_id",
"stio_id",
"gr_id",
125 "cli_pid",
"srv_pid")
126 relations = [dict(zip(labels, f))
for f
in fields]
130 client_id = set([o[
'client_id']
for o
in relations]).pop()
131 io_req_id = set([o[f
'{io_req_type}_id']
for o
in relations]).pop()
132 rpc_fom_s = set([(o[
'opcode'],
141 o[
'gr_id'])
for o
in relations])
144 client_req.select().where(client_req.id==client_id)
if client_pid
is None else 145 client_req.select().where((client_req.id==client_id)&(client_req.pid==client_pid)))
147 time_table.append(client_req_d)
148 client_start_time=
min([t[
'time']
for t
in client_req_d])
152 io_req_table.select().where(io_req_table.id==io_req_id)
if client_pid
is None else 153 io_req_table.select().where((io_req_table.id==io_req_id)&(io_req_table.pid==client_pid)))
155 time_table.append(io_req_d)
158 for opcode, cli_pid, srv_pid, crpc_id, srpc_id, fom_id, fom_state_id, tx_id, stio_id, gr_id
in rpc_fom_s:
159 for tag,(rpc_id,pid)
in {
"c": (crpc_id, cli_pid),
160 "s": (srpc_id, srv_pid)}.items():
161 rpc_req_d =
query2dlist(rpc_req.select().where((rpc_req.id==rpc_id)&
164 time_table.append(rpc_req_d)
166 fom_req_st_d =
query2dlist(fom_req_state.select().where((fom_req_state.id==fom_state_id)&
167 (fom_req_state.pid==srv_pid)))
169 time_table.append(fom_req_st_d)
171 fom_req_d =
query2dlist(fom_req.select().where((fom_req.id==fom_id)&
172 (fom_req.pid==srv_pid)))
174 time_table.append(fom_req_d)
177 stio_d =
query2dlist(stio_req.select().where((stio_req.id==stio_id)&
178 (stio_req.pid==srv_pid)))
180 time_table.append(stio_d)
183 be_tx_d =
query2dlist(be_tx.select().where((be_tx.id==tx_id)&
184 (be_tx.pid==srv_pid)))
186 time_table.append(be_tx_d)
191 left =
query2dlist(fom_req.select().where((fom_req.id==gr_id)&
192 (fom_req.pid==srv_pid)&
193 (fom_req.time<client_start_time)).limit(grange[0]))
195 right =
query2dlist(fom_req.select().where((fom_req.id==gr_id)&
196 (fom_req.pid==srv_pid)&
197 (fom_req.time>=client_start_time)).limit(grange[1]))
198 if grange[0]>0
or grange[1]>0:
199 gr_d = [*left, *right]
201 time_table.append(gr_d)
210 if create_attr_graph:
211 print(
"Building attributes graph...")
212 attr_graph =
graph_build(relations, ext_graph, is_cob)
214 return time_table, queue_table, queue_start_time, client_start_time, attr_graph
218 parser = argparse.ArgumentParser(prog=sys.argv[0], description=
""" 219 io_req.py: Display significant performance counters for Motr stack. 221 parser.add_argument(
"-p",
"--pid", type=int, default=
None,
222 help=
"Client pid to get requests for")
223 parser.add_argument(
"-c",
"--cob", action=
'store_true',
224 help=
"Whether client request relates to COB")
225 parser.add_argument(
"-m",
"--maximize", action=
'store_true', help=
"Display in maximised window")
226 parser.add_argument(
"-q",
"--queues", action=
'store_true', help=
"Display queues also")
227 parser.add_argument(
"-r",
"--qrange", type=int, default=10,
228 help=
"Limit quantity of queue-related samples")
229 parser.add_argument(
"-g",
"--grange", default=[0, 0],
230 nargs=2, metavar=(
'left',
'right'), type=int,
231 help=
"Limit quantity of tx group-related samples")
232 parser.add_argument(
"-a",
"--attr", action=
'store_true', help=
"Create attributes graph")
233 parser.add_argument(
"-v",
"--verbose", action=
'count', default=0)
234 parser.add_argument(
"-u",
"--time-unit", choices=[
'ms',
'us'], default=
'us',
235 help=
"Default time unit")
236 parser.add_argument(
"-d",
"--db", type=str, default=
"m0play.db",
237 help=
"Performance database (m0play.db)")
238 parser.add_argument(
"client_id", type=str, help=
"Client request id")
240 return parser.parse_args()
242 if __name__ ==
'__main__':
248 print(
"Getting timelines...")
250 time_table, queue_table, queue_start_time, client_start_time, _ = \
251 get_timelines(args.client_id, args.grange, args.pid, args.attr,
False,
None, args.cob)
258 print(
"Plotting timelines...")
260 draw_timelines(time_table, queue_table, client_start_time, queue_start_time,
261 args.time_unit, args.queues, args.maximize)
static struct m0_list list
def prepare_time_table(time_table)
static M0_UNUSED void print(struct m0_be_list *list)
static long long min(long long a, long long b)