1974bd5b3SMilanka Ringwald#!/usr/bin/env python3 2974bd5b3SMilanka Ringwald 3974bd5b3SMilanka Ringwald# requires https://github.com/bright-tools/ccsm 4974bd5b3SMilanka Ringwald 5974bd5b3SMilanka Ringwaldimport os 6974bd5b3SMilanka Ringwaldimport sys 7974bd5b3SMilanka Ringwaldimport csv 8974bd5b3SMilanka Ringwald 9974bd5b3SMilanka Ringwaldfolders = [ 10974bd5b3SMilanka Ringwald'src', 11974bd5b3SMilanka Ringwald'src/ble', 12974bd5b3SMilanka Ringwald'src/ble/gatt-service', 13974bd5b3SMilanka Ringwald'src/classic', 14974bd5b3SMilanka Ringwald] 15974bd5b3SMilanka Ringwald 16974bd5b3SMilanka Ringwaldmetrics = {} 17974bd5b3SMilanka Ringwaldtargets = {} 1834114554SMilanka Ringwaldhistogram_data = {} 19974bd5b3SMilanka Ringwald 20974bd5b3SMilanka Ringwaldtargets['PATH'] = 1000 21974bd5b3SMilanka Ringwaldtargets['GOTO'] = 0 22974bd5b3SMilanka Ringwaldtargets['CCN'] = 20 23974bd5b3SMilanka Ringwaldtargets['CALLS'] = 12 24974bd5b3SMilanka Ringwaldtargets['PARAM'] = 7 25974bd5b3SMilanka Ringwaldtargets['STMT'] = 100 26974bd5b3SMilanka Ringwaldtargets['LEVEL'] = 6 27974bd5b3SMilanka Ringwaldtargets['RETURN'] = 1 28974bd5b3SMilanka Ringwald 29974bd5b3SMilanka Ringwaldexcluded_functions = [ 30974bd5b3SMilanka Ringwald # deprecated functions 31974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_register_service', 32974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_unregister_service', 33974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_accept_connection', 34974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_decline_connection', 35974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_provide_credits', 36974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_create_channel', 37974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_can_send_now', 38974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_request_can_send_now_event', 39974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_send_data', 40974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_le_disconnect', 41974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_cbm_can_send_now', 42974bd5b3SMilanka Ringwald 'src/l2cap.c:l2cap_cbm_request_can_send_now_even' 43974bd5b3SMilanka Ringwald] 44974bd5b3SMilanka Ringwald 4534114554SMilanka Ringwalddef histogram_add_data(key, value): 4634114554SMilanka Ringwald global histogram_data 4734114554SMilanka Ringwald if key not in histogram_data.keys(): 4834114554SMilanka Ringwald histogram_data[key] = [] 4934114554SMilanka Ringwald histogram_data[key].append(value) 5034114554SMilanka Ringwald 5134114554SMilanka Ringwald 52974bd5b3SMilanka Ringwalddef metric_sum(name, value): 53974bd5b3SMilanka Ringwald global metrics 54974bd5b3SMilanka Ringwald old = 0 55974bd5b3SMilanka Ringwald if name in metrics: 56974bd5b3SMilanka Ringwald old = metrics[name] 57974bd5b3SMilanka Ringwald metrics[name] = old + value 58974bd5b3SMilanka Ringwald 59974bd5b3SMilanka Ringwald 60974bd5b3SMilanka Ringwalddef metric_list(name, item): 61974bd5b3SMilanka Ringwald global metrics 62974bd5b3SMilanka Ringwald value = [] 63974bd5b3SMilanka Ringwald if name in metrics: 64974bd5b3SMilanka Ringwald value = metrics[name] 65974bd5b3SMilanka Ringwald value.append(item) 66974bd5b3SMilanka Ringwald metrics[name] = value 67974bd5b3SMilanka Ringwald 68974bd5b3SMilanka Ringwalddef metric_max(name, max): 69974bd5b3SMilanka Ringwald global metrics 70974bd5b3SMilanka Ringwald if name in metrics: 71974bd5b3SMilanka Ringwald if metrics[name] > max: 72974bd5b3SMilanka Ringwald return 73974bd5b3SMilanka Ringwald metrics[name] = max 74974bd5b3SMilanka Ringwald 75974bd5b3SMilanka Ringwalddef metric_measure(metric_name, function_name, actual): 76974bd5b3SMilanka Ringwald metric_max(metric_name + '_MAX', actual) 77974bd5b3SMilanka Ringwald if metric_name in targets: 78974bd5b3SMilanka Ringwald metric_sum(metric_name + '_SUM', actual) 79974bd5b3SMilanka Ringwald if actual > targets[metric_name]: 80974bd5b3SMilanka Ringwald metric_sum(metric_name + '_DEVIATIONS', 1) 81*39127754SMatthias Ringwald metric_list(metric_name + '_LIST', function_name + ' - %u' % actual) 82974bd5b3SMilanka Ringwald 83974bd5b3SMilanka Ringwald 849aec9f02SMilanka Ringwalddef analyze_folders(btstack_root, folders, metrics_file): 85974bd5b3SMilanka Ringwald global excluded_functions 86974bd5b3SMilanka Ringwald 87974bd5b3SMilanka Ringwald # File,Name,"'goto' keyword count (raw source)","Return points","Statement count (raw source)(local)", 88974bd5b3SMilanka Ringwald # "Statement count (raw source)(cumulative)","Comment density","McCabe complexity (raw source)", 89974bd5b3SMilanka Ringwald # "Number of paths through the function","No. different functions called","Function Parameters", 90974bd5b3SMilanka Ringwald # "Nesting Level","VOCF","Number of functions which call this function", 91974bd5b3SMilanka Ringwald fields = [ 'file','function','GOTO','RETURN','_','STMT' ,'_','CCN','PATH','CALLS','PARAM','LEVEL','_','_','_'] 92974bd5b3SMilanka Ringwald 93974bd5b3SMilanka Ringwald # init deviations 94974bd5b3SMilanka Ringwald for key in fields: 95974bd5b3SMilanka Ringwald metrics[key + '_DEVIATIONS'] = 0 96974bd5b3SMilanka Ringwald 97974bd5b3SMilanka Ringwald # for now, just read the file 989aec9f02SMilanka Ringwald with open(metrics_file) as fd: 99974bd5b3SMilanka Ringwald rd = csv.reader(fd, delimiter="\t") 100974bd5b3SMilanka Ringwald last_function_name = '' 101974bd5b3SMilanka Ringwald for row in rd: 102974bd5b3SMilanka Ringwald file = '' 103974bd5b3SMilanka Ringwald function_metrics = {} 104cfc3484eSMatthias Ringwald # skip optional header 105cfc3484eSMatthias Ringwald if row[0].startswith('#'): 106cfc3484eSMatthias Ringwald continue 107cfc3484eSMatthias Ringwald 108974bd5b3SMilanka Ringwald for key, value in zip(fields, row): 109974bd5b3SMilanka Ringwald if key == 'file': 110974bd5b3SMilanka Ringwald # get rid of directory traversal on buildbot 111974bd5b3SMilanka Ringwald pos_metrics_folder = value.find('tool/metrics/') 112974bd5b3SMilanka Ringwald if pos_metrics_folder > 0: 113974bd5b3SMilanka Ringwald value = value[pos_metrics_folder+13:] 114974bd5b3SMilanka Ringwald # streamline path 115974bd5b3SMilanka Ringwald file = value.replace('../../','') 116974bd5b3SMilanka Ringwald continue 117974bd5b3SMilanka Ringwald if key == 'function': 118974bd5b3SMilanka Ringwald function_name = value 119974bd5b3SMilanka Ringwald continue 120974bd5b3SMilanka Ringwald if key == '_': 121974bd5b3SMilanka Ringwald continue 122974bd5b3SMilanka Ringwald function_metrics[key] = value 12334114554SMilanka Ringwald histogram_add_data(key,int(value)) 12434114554SMilanka Ringwald 125974bd5b3SMilanka Ringwald if file.endswith('.h'): 126974bd5b3SMilanka Ringwald continue 127974bd5b3SMilanka Ringwald qualified_function_name = file+':'+function_name 128974bd5b3SMilanka Ringwald # excluded functions 129974bd5b3SMilanka Ringwald if qualified_function_name in excluded_functions: 130974bd5b3SMilanka Ringwald continue 131974bd5b3SMilanka Ringwald metric_sum('FUNC', 1) 132974bd5b3SMilanka Ringwald for key,value in function_metrics.items(): 133974bd5b3SMilanka Ringwald metric_measure(key, qualified_function_name, int(function_metrics[key])) 134974bd5b3SMilanka Ringwald 1359aec9f02SMilanka Ringwalddef analyze(folders, metrics_file): 136974bd5b3SMilanka Ringwald # print ("\nAnalyzing:") 137974bd5b3SMilanka Ringwald # for path in folders: 138974bd5b3SMilanka Ringwald # print('- %s' % path) 139974bd5b3SMilanka Ringwald # analyze_folder(btstack_root + "/" + path) 140974bd5b3SMilanka Ringwald btstack_root = os.path.abspath(os.path.dirname(sys.argv[0]) + '/../..') 1419aec9f02SMilanka Ringwald analyze_folders(btstack_root, folders, metrics_file) 142974bd5b3SMilanka Ringwald 143974bd5b3SMilanka Ringwalddef list_targets(): 144974bd5b3SMilanka Ringwald print ("Targets:") 145974bd5b3SMilanka Ringwald for key,value in sorted(targets.items()): 146974bd5b3SMilanka Ringwald print ('- %-20s: %u' % (key, value)) 147974bd5b3SMilanka Ringwald 148974bd5b3SMilanka Ringwalddef list_metrics(): 149974bd5b3SMilanka Ringwald print ("\nResult:") 150974bd5b3SMilanka Ringwald num_funcs = metrics['FUNC'] 151974bd5b3SMilanka Ringwald for key,value in sorted(metrics.items()): 152974bd5b3SMilanka Ringwald if key.endswith('LIST'): 153974bd5b3SMilanka Ringwald continue 154974bd5b3SMilanka Ringwald if key.endswith('_SUM'): 155974bd5b3SMilanka Ringwald average = 1.0 * value / num_funcs 156974bd5b3SMilanka Ringwald metric = key.replace('_SUM','_AVERAGE') 157974bd5b3SMilanka Ringwald print ('- %-20s: %4.3f' % (metric, average)) 158974bd5b3SMilanka Ringwald else: 159974bd5b3SMilanka Ringwald print ('- %-20s: %5u' % (key, value)) 160974bd5b3SMilanka Ringwald 161974bd5b3SMilanka Ringwalddef list_metrics_table(): 162974bd5b3SMilanka Ringwald row = "%-11s |%11s |%11s |%11s" 163974bd5b3SMilanka Ringwald 164974bd5b3SMilanka Ringwald print( row % ('Name', 'Target', 'Deviations', 'Max value')) 165974bd5b3SMilanka Ringwald print("------------|------------|------------|------------") 166974bd5b3SMilanka Ringwald 167974bd5b3SMilanka Ringwald ordered_metrics = [ 'PATH', 'GOTO', 'CCN', 'CALLS', 'PARAM', 'STMT', 'LEVEL', 'RETURN', 'FUNC']; 168974bd5b3SMilanka Ringwald for metric_name in ordered_metrics: 169974bd5b3SMilanka Ringwald if metric_name in targets: 170974bd5b3SMilanka Ringwald target = targets[metric_name] 171974bd5b3SMilanka Ringwald deviations = metrics[metric_name + '_DEVIATIONS'] 172974bd5b3SMilanka Ringwald max = metrics[metric_name + '_MAX'] 173974bd5b3SMilanka Ringwald print ( row % ( metric_name, target, deviations, max)) 174974bd5b3SMilanka Ringwald else: 175974bd5b3SMilanka Ringwald max = metrics[metric_name] 176974bd5b3SMilanka Ringwald print ( row % ( metric_name, '', '', max)) 177974bd5b3SMilanka Ringwald 178974bd5b3SMilanka Ringwalddef list_deviations(): 179974bd5b3SMilanka Ringwald global metrics 180974bd5b3SMilanka Ringwald for key,value in sorted(metrics.items()): 181974bd5b3SMilanka Ringwald if not key.endswith('LIST'): 182974bd5b3SMilanka Ringwald continue 183974bd5b3SMilanka Ringwald print ("\n%s" % key) 184974bd5b3SMilanka Ringwald print ('\n'.join(value)) 185974bd5b3SMilanka Ringwald 186e174300aSMilanka Ringwalddef main(argv): 1879aec9f02SMilanka Ringwald analyze(folders, "metrics.tsv") 188974bd5b3SMilanka Ringwald list_metrics_table() 189974bd5b3SMilanka Ringwald # list_targets() 190974bd5b3SMilanka Ringwald # list_metrics() 191974bd5b3SMilanka Ringwald # list_deviations() 192e174300aSMilanka Ringwald 193e174300aSMilanka Ringwaldif __name__ == "__main__": 194e174300aSMilanka Ringwald main(sys.argv[1:]) 195