1*4882a593Smuzhiyun#!/usr/bin/env perl 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun# Read two files produced by the stackusage script, and show the 5*4882a593Smuzhiyun# delta between them. 6*4882a593Smuzhiyun# 7*4882a593Smuzhiyun# Currently, only shows changes for functions listed in both files. We 8*4882a593Smuzhiyun# could add an option to show also functions which have vanished or 9*4882a593Smuzhiyun# appeared (which would often be due to gcc making other inlining 10*4882a593Smuzhiyun# decisions). 11*4882a593Smuzhiyun# 12*4882a593Smuzhiyun# Another possible option would be a minimum absolute value for the 13*4882a593Smuzhiyun# delta. 14*4882a593Smuzhiyun# 15*4882a593Smuzhiyun# A third possibility is for sorting by delta, but that can be 16*4882a593Smuzhiyun# achieved by piping to sort -k5,5g. 17*4882a593Smuzhiyun 18*4882a593Smuzhiyunsub read_stack_usage_file { 19*4882a593Smuzhiyun my %su; 20*4882a593Smuzhiyun my $f = shift; 21*4882a593Smuzhiyun open(my $fh, '<', $f) 22*4882a593Smuzhiyun or die "cannot open $f: $!"; 23*4882a593Smuzhiyun while (<$fh>) { 24*4882a593Smuzhiyun chomp; 25*4882a593Smuzhiyun my ($file, $func, $size, $type) = split; 26*4882a593Smuzhiyun # Old versions of gcc (at least 4.7) have an annoying quirk in 27*4882a593Smuzhiyun # that a (static) function whose name has been changed into 28*4882a593Smuzhiyun # for example ext4_find_unwritten_pgoff.isra.11 will show up 29*4882a593Smuzhiyun # in the .su file with a name of just "11". Since such a 30*4882a593Smuzhiyun # numeric suffix is likely to change across different 31*4882a593Smuzhiyun # commits/compilers/.configs or whatever else we're trying to 32*4882a593Smuzhiyun # tweak, we can't really track those functions, so we just 33*4882a593Smuzhiyun # silently skip them. 34*4882a593Smuzhiyun # 35*4882a593Smuzhiyun # Newer gcc (at least 5.0) report the full name, so again, 36*4882a593Smuzhiyun # since the suffix is likely to change, we strip it. 37*4882a593Smuzhiyun next if $func =~ m/^[0-9]+$/; 38*4882a593Smuzhiyun $func =~ s/\..*$//; 39*4882a593Smuzhiyun # Line numbers are likely to change; strip those. 40*4882a593Smuzhiyun $file =~ s/:[0-9]+$//; 41*4882a593Smuzhiyun $su{"${file}\t${func}"} = {size => $size, type => $type}; 42*4882a593Smuzhiyun } 43*4882a593Smuzhiyun close($fh); 44*4882a593Smuzhiyun return \%su; 45*4882a593Smuzhiyun} 46*4882a593Smuzhiyun 47*4882a593Smuzhiyun@ARGV == 2 48*4882a593Smuzhiyun or die "usage: $0 <old> <new>"; 49*4882a593Smuzhiyun 50*4882a593Smuzhiyunmy $old = read_stack_usage_file($ARGV[0]); 51*4882a593Smuzhiyunmy $new = read_stack_usage_file($ARGV[1]); 52*4882a593Smuzhiyunmy @common = sort grep {exists $new->{$_}} keys %$old; 53*4882a593Smuzhiyunfor (@common) { 54*4882a593Smuzhiyun my $x = $old->{$_}{size}; 55*4882a593Smuzhiyun my $y = $new->{$_}{size}; 56*4882a593Smuzhiyun my $delta = $y - $x; 57*4882a593Smuzhiyun if ($delta) { 58*4882a593Smuzhiyun printf "%s\t%d\t%d\t%+d\n", $_, $x, $y, $delta; 59*4882a593Smuzhiyun } 60*4882a593Smuzhiyun} 61