@@ -685,32 +685,33 @@ def rsp_qXfer(options, cmd, cmd_args, rsp):
685
685
if extension == '.xml' :
686
686
response = Packet (rsp )
687
687
xml_string = response .get_hex_ascii_str ()
688
- ch = xml_string [0 ]
689
- if ch == 'l' :
690
- xml_string = xml_string [1 :]
691
- xml_root = ET .fromstring (xml_string )
692
- for reg_element in xml_root .findall ("./feature/reg" ):
693
- if not 'value_regnums' in reg_element .attrib :
694
- reg_info = RegisterInfo ([])
695
- if 'name' in reg_element .attrib :
696
- reg_info .info [
697
- 'name' ] = reg_element .attrib ['name' ]
698
- else :
699
- reg_info .info ['name' ] = 'unspecified'
700
- if 'encoding' in reg_element .attrib :
701
- reg_info .info ['encoding' ] = reg_element .attrib [
702
- 'encoding' ]
703
- else :
704
- reg_info .info ['encoding' ] = 'uint'
705
- if 'offset' in reg_element .attrib :
706
- reg_info .info [
707
- 'offset' ] = reg_element .attrib ['offset' ]
708
- if 'bitsize' in reg_element .attrib :
709
- reg_info .info [
710
- 'bitsize' ] = reg_element .attrib ['bitsize' ]
711
- g_register_infos .append (reg_info )
712
- print 'XML for "%s":' % (data [2 ])
713
- ET .dump (xml_root )
688
+ if xml_string :
689
+ ch = xml_string [0 ]
690
+ if ch == 'l' :
691
+ xml_string = xml_string [1 :]
692
+ xml_root = ET .fromstring (xml_string )
693
+ for reg_element in xml_root .findall ("./feature/reg" ):
694
+ if not 'value_regnums' in reg_element .attrib :
695
+ reg_info = RegisterInfo ([])
696
+ if 'name' in reg_element .attrib :
697
+ reg_info .info [
698
+ 'name' ] = reg_element .attrib ['name' ]
699
+ else :
700
+ reg_info .info ['name' ] = 'unspecified'
701
+ if 'encoding' in reg_element .attrib :
702
+ reg_info .info ['encoding' ] = reg_element .attrib [
703
+ 'encoding' ]
704
+ else :
705
+ reg_info .info ['encoding' ] = 'uint'
706
+ if 'offset' in reg_element .attrib :
707
+ reg_info .info [
708
+ 'offset' ] = reg_element .attrib ['offset' ]
709
+ if 'bitsize' in reg_element .attrib :
710
+ reg_info .info [
711
+ 'bitsize' ] = reg_element .attrib ['bitsize' ]
712
+ g_register_infos .append (reg_info )
713
+ print 'XML for "%s":' % (data [2 ])
714
+ ET .dump (xml_root )
714
715
715
716
716
717
def cmd_A (options , cmd , args ):
@@ -810,6 +811,14 @@ def cmd_s(options, cmd, args):
810
811
return False
811
812
812
813
814
+ def cmd_qSpeedTest (options , cmd , args ):
815
+ print ("qSpeedTest: cmd='%s', args='%s'" % (cmd , args ))
816
+
817
+
818
+ def rsp_qSpeedTest (options , cmd , cmd_args , rsp ):
819
+ print ("qSpeedTest: rsp='%s' cmd='%s', args='%s'" % (rsp , cmd , args ))
820
+
821
+
813
822
def cmd_vCont (options , cmd , args ):
814
823
if args == '?' :
815
824
print "%s: get supported extended continue modes" % (cmd )
@@ -861,8 +870,10 @@ def rsp_vCont(options, cmd, cmd_args, rsp):
861
870
s += 'step'
862
871
elif mode == 'S' :
863
872
s += 'step with signal'
864
- else :
865
- s += 'unrecognized vCont mode: ' , mode
873
+ elif mode == 't' :
874
+ s += 'stop'
875
+ # else:
876
+ # s += 'unrecognized vCont mode: ', str(mode)
866
877
print s
867
878
elif rsp :
868
879
if rsp [0 ] == 'T' or rsp [0 ] == 'S' or rsp [0 ] == 'W' or rsp [0 ] == 'X' :
@@ -933,7 +944,7 @@ def rsp_qThreadInfo(options, cmd, cmd_args, rsp):
933
944
def rsp_hex_big_endian (options , cmd , cmd_args , rsp ):
934
945
if rsp == '' :
935
946
print "%s%s is not supported" % (cmd , cmd_args )
936
- else :
947
+ else :
937
948
packet = Packet (rsp )
938
949
uval = packet .get_hex_uint ('big' )
939
950
print '%s: 0x%x' % (cmd , uval )
@@ -1225,6 +1236,7 @@ def rsp_jGetLoadedDynamicLibrariesInfos(options, cmd, cmd_args, rsp):
1225
1236
'qHostInfo' : {'cmd' : cmd_query_packet , 'rsp' : rsp_dump_key_value_pairs , 'name' : "get host information" },
1226
1237
'qC' : {'cmd' : cmd_qC , 'rsp' : rsp_qC , 'name' : "return the current thread ID" },
1227
1238
'vCont' : {'cmd' : cmd_vCont , 'rsp' : rsp_vCont , 'name' : "extended continue command" },
1239
+ 'qSpeedTest' : {'cmd' :cmd_qSpeedTest , 'rsp' : rsp_qSpeedTest , 'name' : 'speed test packdet' },
1228
1240
'vAttach' : {'cmd' : cmd_vAttach , 'rsp' : rsp_stop_reply , 'name' : "attach to process" },
1229
1241
'c' : {'cmd' : cmd_c , 'rsp' : rsp_stop_reply , 'name' : "continue" },
1230
1242
's' : {'cmd' : cmd_s , 'rsp' : rsp_stop_reply , 'name' : "step" },
@@ -1283,6 +1295,49 @@ def parse_gdb_log_file(path, options):
1283
1295
f .close ()
1284
1296
1285
1297
1298
+ def round_up (n , incr ):
1299
+ return float (((int (n ) + incr ) / incr ) * incr )
1300
+
1301
+
1302
+ def plot_latencies (sec_times ):
1303
+ # import numpy as np
1304
+ import matplotlib .pyplot as plt
1305
+
1306
+ for (i , name ) in enumerate (sec_times .keys ()):
1307
+ times = sec_times [name ]
1308
+ if len (times ) <= 1 :
1309
+ continue
1310
+ plt .subplot (2 , 1 , 1 )
1311
+ plt .title ('Packet "%s" Times' % (name ))
1312
+ plt .xlabel ('Packet' )
1313
+ units = 'ms'
1314
+ adj_times = []
1315
+ max_time = 0.0
1316
+ for time in times :
1317
+ time = time * 1000.0
1318
+ adj_times .append (time )
1319
+ if time > max_time :
1320
+ max_time = time
1321
+ if max_time < 1.0 :
1322
+ units = 'us'
1323
+ max_time = 0.0
1324
+ for i in range (len (adj_times )):
1325
+ adj_times [i ] *= 1000.0
1326
+ if adj_times [i ] > max_time :
1327
+ max_time = adj_times [i ]
1328
+ plt .ylabel ('Time (%s)' % (units ))
1329
+ max_y = None
1330
+ for i in [5.0 , 10.0 , 25.0 , 50.0 ]:
1331
+ if max_time < i :
1332
+ max_y = round_up (max_time , i )
1333
+ break
1334
+ if max_y is None :
1335
+ max_y = round_up (max_time , 100.0 )
1336
+ plt .ylim (0.0 , max_y )
1337
+ plt .plot (adj_times , 'o-' )
1338
+ plt .show ()
1339
+
1340
+
1286
1341
def parse_gdb_log (file , options ):
1287
1342
'''Parse a GDB log file that was generated by enabling logging with:
1288
1343
(lldb) log enable --threadsafe --timestamp --file <FILE> gdb-remote packets
@@ -1306,10 +1361,11 @@ def parse_gdb_log(file, options):
1306
1361
1307
1362
base_time = 0.0
1308
1363
last_time = 0.0
1309
- packet_send_time = 0 .0
1364
+ min_time = 100000000 .0
1310
1365
packet_total_times = {}
1311
- packet_times = []
1312
- packet_count = {}
1366
+ all_packet_times = []
1367
+ packet_times = {}
1368
+ packet_counts = {}
1313
1369
lines = file .read ().splitlines ()
1314
1370
last_command = None
1315
1371
last_command_args = None
@@ -1412,32 +1468,39 @@ def parse_gdb_log(file, options):
1412
1468
curr_time = float (match .group (2 ))
1413
1469
if last_time and not is_command :
1414
1470
delta = curr_time - last_time
1415
- packet_times .append (delta )
1471
+ all_packet_times .append (delta )
1416
1472
delta = 0.0
1417
1473
if base_time :
1418
1474
delta = curr_time - last_time
1419
1475
else :
1420
1476
base_time = curr_time
1421
1477
1422
- if is_command :
1423
- packet_send_time = curr_time
1424
- elif line .find ('read packet: $' ) >= 0 and packet_name :
1425
- if packet_name in packet_total_times :
1426
- packet_total_times [packet_name ] += delta
1427
- packet_count [packet_name ] += 1
1428
- else :
1429
- packet_total_times [packet_name ] = delta
1430
- packet_count [packet_name ] = 1
1431
- packet_name = None
1478
+ if not is_command :
1479
+ if line .find ('read packet: $' ) >= 0 and packet_name :
1480
+ if packet_name in packet_total_times :
1481
+ packet_total_times [packet_name ] += delta
1482
+ packet_counts [packet_name ] += 1
1483
+ else :
1484
+ packet_total_times [packet_name ] = delta
1485
+ packet_counts [packet_name ] = 1
1486
+ if packet_name not in packet_times :
1487
+ packet_times [packet_name ] = []
1488
+ packet_times [packet_name ].append (delta )
1489
+ packet_name = None
1490
+ if min_time > delta :
1491
+ min_time = delta
1432
1492
1433
1493
if not options or not options .quiet :
1434
- print '%s%.6f %+.6f%s' % (match .group (1 ), curr_time - base_time , delta , match .group (3 ))
1494
+ print '%s%.6f %+.6f%s' % (match .group (1 ),
1495
+ curr_time - base_time ,
1496
+ delta ,
1497
+ match .group (3 ))
1435
1498
last_time = curr_time
1436
1499
# else:
1437
1500
# print line
1438
- (average , std_dev ) = calculate_mean_and_standard_deviation (packet_times )
1501
+ (average , std_dev ) = calculate_mean_and_standard_deviation (all_packet_times )
1439
1502
if average and std_dev :
1440
- print '%u packets with average packet time of %f and standard deviation of %f' % (len (packet_times ), average , std_dev )
1503
+ print '%u packets with average packet time of %f and standard deviation of %f' % (len (all_packet_times ), average , std_dev )
1441
1504
if packet_total_times :
1442
1505
total_packet_time = 0.0
1443
1506
total_packet_count = 0
@@ -1446,19 +1509,21 @@ def parse_gdb_log(file, options):
1446
1509
# print 'value = (%s) %s' % (type(vvv), vvv)
1447
1510
# if type(vvv) == 'float':
1448
1511
total_packet_time += vvv
1449
- for key , vvv in packet_count .items ():
1512
+ for key , vvv in packet_counts .items ():
1450
1513
total_packet_count += vvv
1451
1514
1452
- print '#---------------------------------------------------'
1515
+ print '#------------------------------------------------------------ '
1453
1516
print '# Packet timing summary:'
1454
- print '# Totals: time = %6f, count = %6d' % (total_packet_time , total_packet_count )
1455
- print '#---------------------------------------------------'
1456
- print '# Packet Time (sec) Percent Count '
1457
- print '#------------------------- ---------- ------- ------'
1517
+ print '# Totals: time = %6f, count = %6d' % (total_packet_time ,
1518
+ total_packet_count )
1519
+ print '# Min packet time: time = %6f' % (min_time )
1520
+ print '#------------------------------------------------------------'
1521
+ print '# Packet Time (sec) Percent Count Latency'
1522
+ print '#------------------------- ----------- ------- ------ -------'
1458
1523
if options and options .sort_count :
1459
1524
res = sorted (
1460
- packet_count ,
1461
- key = packet_count .__getitem__ ,
1525
+ packet_counts ,
1526
+ key = packet_counts .__getitem__ ,
1462
1527
reverse = True )
1463
1528
else :
1464
1529
res = sorted (
@@ -1471,11 +1536,12 @@ def parse_gdb_log(file, options):
1471
1536
packet_total_time = packet_total_times [item ]
1472
1537
packet_percent = (
1473
1538
packet_total_time / total_packet_time ) * 100.0
1474
- if packet_percent >= 10.0 :
1475
- print " %24s %.6f %.2f%% %6d" % (item , packet_total_time , packet_percent , packet_count [item ])
1476
- else :
1477
- print " %24s %.6f %.2f%% %6d" % (item , packet_total_time , packet_percent , packet_count [item ])
1478
-
1539
+ packet_count = packet_counts [item ]
1540
+ print " %24s %11.6f %5.2f%% %6d %9.6f" % (
1541
+ item , packet_total_time , packet_percent , packet_count ,
1542
+ float (packet_total_time ) / float (packet_count ))
1543
+ if options .plot :
1544
+ plot_latencies (packet_times )
1479
1545
1480
1546
if __name__ == '__main__' :
1481
1547
usage = "usage: gdbremote [options]"
@@ -1491,6 +1557,12 @@ def parse_gdb_log(file, options):
1491
1557
dest = 'verbose' ,
1492
1558
help = 'display verbose debug info' ,
1493
1559
default = False )
1560
+ parser .add_option (
1561
+ '--plot' ,
1562
+ action = 'store_true' ,
1563
+ dest = 'plot' ,
1564
+ help = 'plot packet latencies by packet type' ,
1565
+ default = False )
1494
1566
parser .add_option (
1495
1567
'-q' ,
1496
1568
'--quiet' ,
0 commit comments