Loading scripts/mem_analysis_malloc.py 0 → 100644 +114 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 import os import argparse import csv import sys import struct import numpy as np import pandas as pd import matplotlib import tkinter matplotlib.use('TkAgg') # Qt4Agg TkAgg Gtk3Agg import matplotlib.pyplot as plt # set matplotlib in interactive mode (plots figure and return control) plt.ion() plt.close('all') parser = argparse.ArgumentParser(description='Analyze memory output file') parser.add_argument('input',type=str,help='Memory analysis file (e.g. mem_analysis.csv)') args = parser.parse_args() fileIn = args.input # read input .csv file df = pd.read_csv(fileIn, header=None, names=['action_type', 'frame', 'name', 'line_no', 'mem_size']) Nframes = max(df['frame']) # merge identical memory blocks -> create new column 'count' df = df.groupby(df.columns.tolist(),as_index=False).size() df = df.rename(columns={'size': 'count'}) # df.loc[df['action_type'] == 'D', 'frame'] += 0.9 # remove column 'action_type' df.drop(columns = ['action_type']) # merge records with the same signature but different frame number -> create list of frames (sort in ascending order) df = df.groupby(['name', 'line_no', 'mem_size', 'count'],as_index=False).agg({'frame': list}) df['frame'] = df['frame'].apply(np.sort) df['list_len'] = df['frame'].apply(len) # auxiliary column -> length of the list # merge records with the same name and frame but different line number -> sum memory sizes and counts df = df.groupby(['name', 'list_len'],as_index=False).agg({'line_no': list, 'mem_size': sum, 'count':sum, 'frame':'first'}) # sort by memory size (put inter-frame memory blocks to the bottom) select_inter = (df['list_len'] == 2) & (df.apply(lambda row : row['frame'][-1] - row['frame'][0], axis = 1) >= Nframes) df_inter = df[select_inter] df_inter = df_inter.sort_values(by=['mem_size'], ascending=False) df_intra = df[~select_inter] df_intra = df_intra.sort_values(by=['list_len'], ascending=True) # plot inter-frame memory blocks in horizontal bar graph (use .broken_barh method) fig, ax = plt.subplots() colors = iter(plt.cm.rainbow(np.linspace(0, 1, len(df.index)))) y_ticks = [] y_tick_labels = [] y_low = 1 for index, row in df_inter.iterrows(): l = f"{row['name']} on lines: {row['line_no']}, total memory size: {row['count']}x{row['mem_size']}" fms = row['frame'].reshape((-1,2)) # convert frame numbers to two-column format fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count']), label=l, color=c) y_ticks.append(y_low + 0.5 * row['count']) y_tick_labels.append(row['name']) y_low += row['count'] + 0.5 print(l + f", {row['count'] * fms.shape[0]/Nframes:.3f} mallocs per frame") # plot intra-frame memory blocks in horizontal bar graph (use .broken_barh method) df_intra = df_intra.groupby(['name'],as_index=False).agg({'list_len': list, 'line_no': list, 'mem_size': list, 'count': list, 'frame': list}) for index, row in df_intra.iterrows(): # repeat for all grouped memory records in the row for j in range(len(row['list_len'])): l = f"{row['name']} on lines: {row['line_no'][j]}, total memory size: {row['count'][j]}x{row['mem_size'][j]}" fms = row['frame'][j].astype(float).reshape((-1,2)) # convert frame numbers to two-column format fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment idx_zero = fms[:,1] == 0 # find zero-length segments -> these are intra-frame memory blocks fms[idx_zero, 0] += 0.1 fms[idx_zero, 1] = 0.8 fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count'][j]), label=l, color=c, alpha=0.6) print(l + f", {row['count'][j] * fms.shape[0]/Nframes:.3f} mallocs per frame") y_ticks.append(y_low + 0.5 * max(row['count'])) y_tick_labels.append(row['name']) y_low += max(row['count']) + 0.5 ax.set_yticks(y_ticks) ax.set_yticklabels(y_tick_labels) ax.set_ylabel('Memory size') ax.set_xlabel('Frame') ax.set_title('Memory analysis') # shrink current axis's height by 20% on the bottom to fit the legend box = ax.get_position() ax.set_position([box.x0, box.y0 + box.height * 0.2, box.width, box.height * 0.8]) # insert the legend below the graph ax.legend(loc="upper left", bbox_to_anchor=(0, -0.1), ncol=2, borderaxespad=0, fontsize='small') # magnify to "almost" fullscreen size mng = plt.get_current_fig_manager() mng.full_screen_toggle() # mng.frame.Maximize(True) # mng.window.showMaximized() # mng.window.state('zoomed') # show and save the figure plt.show() # plt.savefig(os.path.splitext(args.input)[0] + '.png', dpi=600) Loading
scripts/mem_analysis_malloc.py 0 → 100644 +114 −0 Original line number Diff line number Diff line #!/usr/bin/env python3 import os import argparse import csv import sys import struct import numpy as np import pandas as pd import matplotlib import tkinter matplotlib.use('TkAgg') # Qt4Agg TkAgg Gtk3Agg import matplotlib.pyplot as plt # set matplotlib in interactive mode (plots figure and return control) plt.ion() plt.close('all') parser = argparse.ArgumentParser(description='Analyze memory output file') parser.add_argument('input',type=str,help='Memory analysis file (e.g. mem_analysis.csv)') args = parser.parse_args() fileIn = args.input # read input .csv file df = pd.read_csv(fileIn, header=None, names=['action_type', 'frame', 'name', 'line_no', 'mem_size']) Nframes = max(df['frame']) # merge identical memory blocks -> create new column 'count' df = df.groupby(df.columns.tolist(),as_index=False).size() df = df.rename(columns={'size': 'count'}) # df.loc[df['action_type'] == 'D', 'frame'] += 0.9 # remove column 'action_type' df.drop(columns = ['action_type']) # merge records with the same signature but different frame number -> create list of frames (sort in ascending order) df = df.groupby(['name', 'line_no', 'mem_size', 'count'],as_index=False).agg({'frame': list}) df['frame'] = df['frame'].apply(np.sort) df['list_len'] = df['frame'].apply(len) # auxiliary column -> length of the list # merge records with the same name and frame but different line number -> sum memory sizes and counts df = df.groupby(['name', 'list_len'],as_index=False).agg({'line_no': list, 'mem_size': sum, 'count':sum, 'frame':'first'}) # sort by memory size (put inter-frame memory blocks to the bottom) select_inter = (df['list_len'] == 2) & (df.apply(lambda row : row['frame'][-1] - row['frame'][0], axis = 1) >= Nframes) df_inter = df[select_inter] df_inter = df_inter.sort_values(by=['mem_size'], ascending=False) df_intra = df[~select_inter] df_intra = df_intra.sort_values(by=['list_len'], ascending=True) # plot inter-frame memory blocks in horizontal bar graph (use .broken_barh method) fig, ax = plt.subplots() colors = iter(plt.cm.rainbow(np.linspace(0, 1, len(df.index)))) y_ticks = [] y_tick_labels = [] y_low = 1 for index, row in df_inter.iterrows(): l = f"{row['name']} on lines: {row['line_no']}, total memory size: {row['count']}x{row['mem_size']}" fms = row['frame'].reshape((-1,2)) # convert frame numbers to two-column format fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count']), label=l, color=c) y_ticks.append(y_low + 0.5 * row['count']) y_tick_labels.append(row['name']) y_low += row['count'] + 0.5 print(l + f", {row['count'] * fms.shape[0]/Nframes:.3f} mallocs per frame") # plot intra-frame memory blocks in horizontal bar graph (use .broken_barh method) df_intra = df_intra.groupby(['name'],as_index=False).agg({'list_len': list, 'line_no': list, 'mem_size': list, 'count': list, 'frame': list}) for index, row in df_intra.iterrows(): # repeat for all grouped memory records in the row for j in range(len(row['list_len'])): l = f"{row['name']} on lines: {row['line_no'][j]}, total memory size: {row['count'][j]}x{row['mem_size'][j]}" fms = row['frame'][j].astype(float).reshape((-1,2)) # convert frame numbers to two-column format fms[:,1] -= fms[:,0] # second column should now represent the duration of the segment idx_zero = fms[:,1] == 0 # find zero-length segments -> these are intra-frame memory blocks fms[idx_zero, 0] += 0.1 fms[idx_zero, 1] = 0.8 fmsT = fms.T fms_list = list(zip(fmsT[0], fmsT[1])) c = next(colors) ax.broken_barh(xranges=fms_list, yrange=(y_low, row['count'][j]), label=l, color=c, alpha=0.6) print(l + f", {row['count'][j] * fms.shape[0]/Nframes:.3f} mallocs per frame") y_ticks.append(y_low + 0.5 * max(row['count'])) y_tick_labels.append(row['name']) y_low += max(row['count']) + 0.5 ax.set_yticks(y_ticks) ax.set_yticklabels(y_tick_labels) ax.set_ylabel('Memory size') ax.set_xlabel('Frame') ax.set_title('Memory analysis') # shrink current axis's height by 20% on the bottom to fit the legend box = ax.get_position() ax.set_position([box.x0, box.y0 + box.height * 0.2, box.width, box.height * 0.8]) # insert the legend below the graph ax.legend(loc="upper left", bbox_to_anchor=(0, -0.1), ncol=2, borderaxespad=0, fontsize='small') # magnify to "almost" fullscreen size mng = plt.get_current_fig_manager() mng.full_screen_toggle() # mng.frame.Maximize(True) # mng.window.showMaximized() # mng.window.state('zoomed') # show and save the figure plt.show() # plt.savefig(os.path.splitext(args.input)[0] + '.png', dpi=600)