From 73644b3f766f1494d5c39b21adbc8c8cd1a6f7f7 Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Sun, 23 Sep 2018 16:41:09 +0200 Subject: checkAPIs.pl: speed up check_value_string_arrays and remove_if0_code The initial execution time on packet-ieee80211.c was 940ms. Optimize: - Assume that "static const value_string ... = { ... };" does not have other preceding stuff (including optional whitespace). This speeds up check_value_string_arrays and reduces runtime by 440ms to 500ms. - Rewrite remove_if0_code to avoid invoking a substitution for every line. This reduces runtime by 130ms to 370ms. packet-rrc.c used to take 9.4s. The fixes improved it to 3.0s and 2.8s. Change-Id: Ifc7efa447d64dccba3e211f0741099451b61b95a Reviewed-on: https://code.wireshark.org/review/29794 Petri-Dish: Peter Wu Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman --- tools/checkAPIs.pl | 116 ++++++++++++++++++++++++----------------------------- 1 file changed, 52 insertions(+), 64 deletions(-) (limited to 'tools') diff --git a/tools/checkAPIs.pl b/tools/checkAPIs.pl index 384df1a5d4..5f3864a638 100755 --- a/tools/checkAPIs.pl +++ b/tools/checkAPIs.pl @@ -406,7 +406,7 @@ my $StaticRegex = qr/ static \s+ my $ConstRegex = qr/ const \s+ /xs; my $Static_andor_ConstRegex = qr/ (?: $StaticRegex $ConstRegex | $StaticRegex | $ConstRegex) /xs; my $ValueStringVarnameRegex = qr/ (?:value|val64|string|range|bytes)_string /xs; -my $ValueStringRegex = qr/ ^ \s* $Static_andor_ConstRegex ($ValueStringVarnameRegex) \ + [^;*]+ = [^;]+ [{] .+? [}] \s*? ; /xms; +my $ValueStringRegex = qr/ $Static_andor_ConstRegex ($ValueStringVarnameRegex) \ + [^;*]+ = [^;]+ [{] .+? [}] \s*? ; /xs; my $EnumValRegex = qr/ $Static_andor_ConstRegex enum_val_t \ + [^;*]+ = [^;]+ [{] .+? [}] \s*? ; /xs; my $NewlineStringRegex = qr/ ["] [^"]* \\n [^"]* ["] /xs; @@ -950,81 +950,69 @@ sub print_usage # args codeRef, fileName # returns: codeRef # -# Essentially: Use s//patsub/meg to pass each line to patsub. -# patsub monitors #if/#if 0/etc and determines -# if a particular code line should be removed. -# XXX: This is probably pretty inefficient; -# I could imagine using another approach such as converting -# the input string to an array of lines and then making -# a pass through the array deleting lines as needed. +# Essentially: split the input into blocks of code or lines of #if/#if 0/etc. +# Remove blocks that follow '#if 0' until '#else/#endif' is found. { # block begin -my ($if_lvl, $if0_lvl, $if0); # shared vars my $debug = 0; sub remove_if0_code { my ($codeRef, $fileName) = @_; - my ($preprocRegEx) = qr { - ( # $1 [complete line) - ^ - (?: # non-capturing - \s* \# \s* - (if \s 0| if | else | endif) # $2 (only if #...) - ) ? - .* - $ - ) - }xom; - - ($if_lvl, $if0_lvl, $if0) = (0,0,0); - $$codeRef =~ s{ $preprocRegEx }{patsub($1,$2,$fileName)}xegm; - - ($debug == 2) && print "==> After Remove if0: code: [$fileName]\n$$codeRef\n===<\n"; - return $codeRef; - } - - sub patsub { - my $fileName = @_[2]; - - if ($debug == 99) { - print "-->$_[0]\n"; - (defined $_[1]) && print " >$_[1]<\n"; - } - - # #if/#if 0/#else/#endif processing - if (defined $_[1]) { - my ($if) = $_[1]; - if ($if eq 'if') { - $if_lvl += 1; - } elsif ($if eq 'if 0') { - $if_lvl += 1; - if ($if0_lvl == 0) { - $if0_lvl = $if_lvl; - $if0 = 1; # inside #if 0 + # Preprocess output (ensure trailing LF and no leading WS before '#') + $$codeRef =~ s/^\s*#/#/m; + if ($$codeRef !~ /\n$/) { $$codeRef .= "\n"; } + + # Split into blocks of normal code or lines with conditionals. + my $ifRegExp = qr/if 0|if|else|endif/; + my @blocks = split(/^(#\s*(?:$ifRegExp).*\n)/m, $$codeRef); + + my ($if_lvl, $if0_lvl, $if0) = (0,0,0); + my $lines = ''; + for my $block (@blocks) { + my $if; + if ($block =~ /^#\s*($ifRegExp)/) { + # #if/#if 0/#else/#endif processing + $if = $1; + if ($debug == 99) { + print(STDERR "if0=$if0 if0_lvl=$if0_lvl lvl=$if_lvl [$if] - $block"); } - } elsif ($if eq 'else') { - if ($if0_lvl == $if_lvl) { - $if0 = 0; - } - } elsif ($if eq 'endif') { - if ($if0_lvl == $if_lvl) { - $if0 = 0; - $if0_lvl = 0; - } - $if_lvl -= 1; - if ($if_lvl < 0) { - die "patsub: #if/#endif mismatch in $fileName" + if ($if eq 'if') { + $if_lvl += 1; + } elsif ($if eq 'if 0') { + $if_lvl += 1; + if ($if0_lvl == 0) { + $if0_lvl = $if_lvl; + $if0 = 1; # inside #if 0 + } + } elsif ($if eq 'else') { + if ($if0_lvl == $if_lvl) { + $if0 = 0; + } + } elsif ($if eq 'endif') { + if ($if0_lvl == $if_lvl) { + $if0 = 0; + $if0_lvl = 0; + } + $if_lvl -= 1; + if ($if_lvl < 0) { + die "patsub: #if/#endif mismatch in $fileName" + } } } - return $_[0]; # don't remove preprocessor lines themselves - } - # not preprocessor line: See if under #if 0: If so, remove - if ($if0 == 1) { - return ''; # remove + if ($debug == 99) { + print(STDERR "if0=$if0 if0_lvl=$if0_lvl lvl=$if_lvl\n"); + } + # Keep preprocessor lines and blocks that are not enclosed in #if 0 + if ($if or $if0 != 1) { + $lines .= $block; + } } - return $_[0]; + $$codeRef = $lines; + + ($debug == 2) && print "==> After Remove if0: code: [$fileName]\n$$codeRef\n===<\n"; + return $codeRef; } } # block end -- cgit v1.2.3