[linux] Re: awk en performance

Cecil Westerhof CecilWesterhof op xs4all.nl
Do Mrt 13 21:23:45 CET 2008


Op do, 13-03-2008 te 18:24 +0100, schreef Cecil Westerhof:
> > > Uiteindelijk bleek dat door het overzicht per veld te creëren, de
> > > performance fors omhoog ging. (Een factor drie tot vier sneller.) En nu
> > > wordt het bestand dus wel drie keer gescanned i.p.v. één keer. Op zich
> > > zou ik me hier iets bij voor kunnen stellen als er een geheugen probleem
> > > zou zijn, maar tijdens het draaien van het oorspronkelijke script was
> > > het swap gebruik precies nul. Dus iemand een idee waar dit aan zou
> > > kunnen liggen?
> > 
> > Niet zonder biede versies van het script te zien.
> 
> Ben er de laatste hand aan het leggen. Als dat klaar is post ik het wel.
> (En moet ik de oude versie weer genereren.)

Blijkbaar heb ik met het aanpassen van de code ook iets anders
verbeterd. Het verschil tussen alles in één keer doen en in drie passes,
is nog maar een faktor anderhalf. Maar dat blijft nog steeds vreemd dat
drie afzonderlijke passes anderhalf keer zo snel is als één pass.

De oude versie:
        #!/usr/bin/env bash
        
        awk '
          BEGIN {
            cat[""]            = 0;
            msg[""]            = 0;
            note[""]           = 0;
        
            i                  = 1;
            optionalNames[i++] = "src";
            optionalNames[i++] = "dst";
            optionalNames[i++] = "note";
          }
        
          END {
            printField("msg", msg);
            printField("note", note);
            printField("cat", cat);
          }
          
          function getField(fieldName, values,    regExp, headLen, tailLen, i) {
            if( match($0, fieldName "=\"[^\"]*\"") ) {
              headLen = length(fieldName) + 2;
              tailLen = 1;
              values[substr($0, RSTART + headLen, RLENGTH - (headLen + tailLen))]++;
              return 0;
            } else {
              for(i in optionalNames) {
                if( fieldName == optionalNames[i] ) {
                  return 0;
                }
              }
              return 1;
            }
          }
        
          function printField(fieldName, values,    format, delimeter, sort, differentRecords, totalRecords, i) {
            format = "| %-70.70s | %8.8s |\n";
            delimeter = sprintf(format, "", "");
            gsub(/ /, "-", delimeter);
            printf "%s",  delimeter;
            printf format, fieldName, "aantal";
            printf "%s",  delimeter;
            sort = "sort";
            for(i in values) {
              if( i != "" ) {
                printf format, i, values[i] | sort;
                differentRecords++;
                totalRecords += values[i];
              }
            }
            close(sort);
            printf "%s",  delimeter;
            printf format, "Aantal verschillende records", differentRecords;
            printf format, "Totaal aantal records", totalRecords;
            printf "%s",  delimeter;
            print "";
          }
        
          {
            if( match($0, / last message repeated [0-9]+ times/) ) {
              next;
            }
            error = 0;
            if( getField("msg", msg) ) {
              error = 1;
            }
            if( getField("note", note) ) {
              error = 1;
            }
            if( getField("cat", cat) ) {
              error = 1;
            }
            if( error ) {
              print "Line " NR " is in the wrong format. (" $0 ")";
            }
          }
        ' /var/log/router.log
        
De nieuwe versie:
        #!/usr/bin/env bash
        
        function getList() {
            awk -v fieldName=${1} '
              BEGIN {
                i                  = 1;
                optionalNames[i++] = "src";
                optionalNames[i++] = "dst";
                optionalNames[i++] = "note";
                values[""]         = 0;
              }
            
              END {
                printField()
              }
              
              function getField(   regExp, headLen, tailLen, i) {
                if( match($0, fieldName "=\"[^\"]*\"") ) {
                  headLen = length(fieldName) + 2;
                  tailLen = 1;
                  values[substr($0, RSTART + headLen, RLENGTH - (headLen + tailLen))]++;
                  return 0;
                } else {
                  for(i in optionalNames) {
                    if( fieldName == optionalNames[i] ) {
                      return 0;
                    }
                  }
                  return 1;
                }
              }
            
              function printField(   format, delimeter, sort, differentRecords, totalRecords, i) {
                format = "| %-70.70s | %8.8s |\n";
                delimeter = sprintf(format, "", "");
                gsub(/ /, "-", delimeter);
                printf "%s",  delimeter;
                printf format, fieldName, "aantal";
                printf "%s",  delimeter;
                sort = "sort";
                for(i in values) {
                  if( i != "" ) {
                    printf format, i, values[i] | sort;
                    differentRecords++;
                    totalRecords += values[i];
                  }
                }
                close(sort);
                printf "%s",  delimeter;
                printf format, "Aantal verschillende records", differentRecords;
                printf format, "Totaal aantal records", totalRecords;
                printf "%s",  delimeter;
                print "";
              }
            
              {
                if( match($0, / last message repeated [0-9]+ times/) ) {
                  next;
                }
                if( getField() ) {
                  print "Line " NR " is in the wrong format. Missing: " fieldName ". (" $0 ")";
                }
              }
            ' /var/log/router.log
        }
        
        getList msg
        getList note
        getList cat

-- 
Cecil Westerhof <CecilWesterhof op xs4all.nl>




More information about the Linux mailing list