def postprocess_collected(config: Config, dfs: DFs) -> None: """Postprocess tables after reading all sources.""" # Prune tables according to configuration options. This happens before # fill_holes() so that space of any pruned symbols will be accounted for, # and to avoid unnecessary work for pruned sections. for c in [SymbolDF, SectionDF]: if c.name in dfs: dfs[c.name] = memdf.select.select_configured( config, dfs[c.name], memdf.select.COLLECTED_CHOICES) # Account for space not used by any symbol, or by multiple symbols. if (SymbolDF.name in dfs and SectionDF.name in dfs and config.get('args.fill_holes', True)): dfs.update(fill_holes(config, dfs[SymbolDF.name], dfs[SectionDF.name])) # Create synthetic columns (e.g. 'region') and prune tables # according to their configuration. This happens after fill_holes() # so that synthetic column values will be created for the gap symbols. for c in [SymbolDF, SectionDF]: if c.name in dfs: for column in memdf.select.SYNTHETIC_CHOICES: dfs[c.name] = memdf.select.synthesize_column( config, dfs[c.name], column) dfs[c.name] = memdf.select.select_configured_column( config, dfs[c.name], column) for df in dfs.values(): if demangle := set((c for c in df.columns if c.endswith('symbol'))): df.attrs['demangle'] = demangle if hexify := set((c for c in df.columns if c.endswith('address'))): df.attrs['hexify'] = hexify
def write_dfs(self, config: Config, frames: DFs, output: OutputOption = None, **kwargs) -> None: """Write a group of memory usage data frames.""" args = self._args(kwargs) frames = {k: prep(config, df, args) for k, df in frames.items()} self.group(config, frames, output, self.single, **args)
def write_text(config: Config, frames: DFs, output: OutputOption, method: str) -> None: """Write a group of of memory usage data frames as human-readable text.""" with open_output(config, output) as out: sep = '' for df in frames.values(): print(end=sep, file=out) sep = '\n' write_table(config, df, out)
def write_one(config: Config, frames: DFs, output: OutputOption, writer: Callable, **kw) -> None: """Write a group of of memory usage data frames to a single file.""" with open_output(config, output) as out: sep = '' for df in frames.values(): print(end=sep, file=out) if kw.get('title') and 'titlefmt' in kw and 'title' in df.attrs: print(kw['titlefmt'].format(df.attrs['title']), file=out) sep = '\n' writer(config, df, out, **kw)
def write_json(config: Config, frames: DFs, output: OutputOption, method: str) -> None: """Write a group of memory usage data frames as json.""" orient = method[5:] with open_output(config, output) as out: sep = '[' for df in frames.values(): print(sep, file=out) sep = ',' df.to_json(out, orient=orient) print(']', file=out)
def write_jsons(config: Config, frames: DFs, output: OutputOption, writer: Callable, **kwargs) -> None: """Write a group of memory usage data frames as a json dictionary.""" with open_output(config, output) as out: print('{', file=out) if metadata := config['output.metadata']: for k, v in metadata.items(): print(f' {json.dumps(k)}: {json.dumps(v)},', file=out) print(' "frames": ', file=out, end='') sep = '{' for df in frames.values(): name = df.attrs.get('name', df.attrs.get('title', dfname(df))) print(sep, file=out) sep = ',' print(f' {json.dumps(name)}: ', file=out, end='') writer(config, df, out, indent=6, **kwargs) print('}}', file=out)