At 10:33 AM 8/14/01 -0400, Yacketta, Ronald wrote:
>I spoke with Mr. Peter Scott and he informed me that I would be ok to
>cut/paste my code in
>an email and post it to the list,

Didn't think of the posting a URL solution at the time :-(

>Please be open and honest, I am looking to speed up the script and make it
>more efficient as well

Snippage below.

>#!/usr/bin/perl -w
>
>use Getopt::Long;
>use Time::Local;
>use strict;

I always put use strict as the first line after the shebang, just to make 
it a standard incantation.

>if ( @ARGV < 2 ) {
>         print "You must supply two command line options\n";

So more than 2 would also be an error, no?  Perhaps check if @ARGV != 2?

>         print "The run # and the sleeptime\n";
>         print "\n IE: $0 1 60\n";;
>         exit (1);
>}
># This just times the script, it should take roughly 30 - 45 seconds to run
>to completion

What is this comment above referring to?

># Disable buffering of output
>$| = 1;

Tiny style point: personally, I'd have put that comment on the same line.

># declare global variables for use
>
>my ($smtx, $syscl, $usr, $sys, $wt, $idl, $CPUS, $avg1, $avg2, $avg3, @time,
>%otime, $otime, $tmp, $stime, %stime, $oratime, $systime);
>my (@mpstat, $OUT, $OFN, $ldavg, $STAT, $SFAN, $header, @lookFor, %results,
>$results, $clients, $pricing, @output, %lookFor);
>my ($get_errors_timer, $tt, $RTDLOGDIR, $RTDUSER, $RTDPASS, $RTD_ORACLE_SID,
>$sessions, $active, $VQUSER, $VQPASS, $lwtime);
>my ($TARGET_HOST, @sessions,@active);

I am 99.99% sure that most of those shouldn't be global variables, and I 
haven't read any more yet :-)  And the ones that should, should be commented.

># A timer so I can limit when the get_errors() runs
>my $time = time() + 30;
>
># oracle related values, used to gather connect times
>$RTDLOGDIR = $ENV{APPSPATH} . "/logs/runtime_logs/";
>$RTDUSER="rtdiag";
>$RTDPASS="byteme";
>$RTD_ORACLE_SID="VALUTEST";
>$VQUSER="VQ3994";
>$VQPASS="VQUIX04";

Thanks for telling us your db password :-)  Consider whether it should be 
passed in from the command line.

>$TARGET_HOST="mc0300uv004";
>
>if ( $ENV{NODE} =~ /NodeA/ ) { $VQUSER="VQ3993"; }
>
># Initialy zero out all the hash values
>foreach my $keys (keys %lookFor ) { $results{$keys} = 0; }
>
># Start some benchmarking stuff
>$tt = new Benchmark;
>
>sub abort ()  {
># set currnt timer time
>my $t3 = new Benchmark;
># find the processing time
>my $te = timediff($t3, $tt);
># report the processing time
>print OFN "elapsed time\t: " . timestr($te) . "\n";
>close(SFN);
>close(OFN);
>exit(1);
>}

Fix the indentation.  It's more important than you might think.  Same 
comment applies in other places.

>sub timer () {
>
>         if ( time() > $time )  {
>                         return 1;
>         } else {
>             return 0;
>         }
>}
>
>
>%SIG = (
>          HUP  => \&abort, # just because it seems only reasonable!
>          INT  => \&abort,
>          QUIT => \&abort,  # can kids inherit these? should they?
>          TERM => \&abort,
>);
>
>
># cleanup routine called every iteration through the get_errors()
># to 0 out all values and hopefully reclaim memory...
>sub cleanup () {
>@output = ();
>%otime = ();
>%stime = ();
>@mpstat = ();
>%results = ();
>@sessions = ();
>@active = ();
>foreach my $keys (keys %lookFor ) { $results{$keys} = 0; }
>}
>
># setup some output files
>my $host = `hostname`;
>my $date = `date +%b%d`;
>chomp( $host);
>chomp( $date );

You can actually do these in one step if you want:

chomp( my $host = `hostname` );

Weird, eh?

># Define the output files used
>$OUT = $ENV{APPSPATH} . "/trg/ltt/scripts/" . $host . "_" . $date .
>"_run$ARGV[0]_$$.out";
>$STAT = $ENV{APPSPATH} . "/trg/ltt/scripts/" . $host . "_" . $date .
>"_run$ARGV[0]_$$.xls";

Put at least the "/trg/ltt/scripts/" in a constant defined at the 
top.  Also, interpolation is your friend:

$OUT = "$ENV{APPSPATH}/trg/ltt/scripts/${host}_${date}_run$ARGV[0]_$$.out";

># BIG UGLY hash of current errors we are tracking for each SLT
># please add new elements to the bottom of the hash, also ensure
># that the print_stat_header() and the  generate_statistic_output()
># are updated accordingly
>
># yeah yeah yeah, I could remove the => ; but why they look so so pretty ;-P

Which is a good reason to keep them in.  I can't think of a reason to take 
them out.

>%lookFor = (
>         "ORA-"                          =>      "ORACLE errors  (various
>Oracle errors)",
>         "Fault 2-001"           =>      "Fault 2-001    Host/server down or
>[snip]);
>
># This begins the output of the statistical data for graphical manipulation
>
># print the Excel column header
>sub print_stat_header () {
>print SFN "\n";
>print SFN
>"DateTimeStamp,ORAn,F2001,F2002,F2003,F2004,F2005,F2006,F2007,F2008,F2009,F2
>010,F2011,F2012,F2013,F2015,F2016,";
>print SFN
>"F2017,F2018,F2019,FactoryFailure,SystemError,SystemException,CommunicationF
>ailure,ORBProblem,GetQError,";
>print SFN "# of clients still running,# of PricingSessions still running,#
>of clients Finished Test,smtx / syscl,user %,";
>print SFN "sys %,wt %,idl %,current load average,current load
>average,current load average,input,errs,output,errs,colls,";
>print SFN "input,errs,output,errs,colls\n";

Use a here doc for the above printing (the << construct).

>sub get_mpstats () {
>
>         $smtx = $syscl = $usr = $sys = $wt = $idl = 0;
>         @mpstat = qx(mpstat 5 2 | sed 1,`mpstat|egrep -c  '[0-9]|CPU'`d);
>         foreach (@mpstat) {
>                 # skip the header output of mpstat
>                 next if /CPU/;
>                 # remove the leading spaces in output
>                 s/^\s+//;
>                 # seperate the output by spaces and pull certain columns
>(see above)
>                 # out for use
>                 my ($A, $B, $C, $D, $E, $F ) = ( split ( /\s+/))
>[9,11,12,13,14,15];
>                 # begin the calculation of the stats
>                 $smtx += $A;
>                 $syscl += $B;
>                 $usr += $C;
>                 $sys += $D;
>                 $wt += $E;
>                 $idl += $F;
>         }

See if you don't like this better:

         my @fields = (split)[9,11..15];
         for ($smtx, $syscl, $usr, $sys, $wt, $idl) { $_ += shift @fields }

>}
>
>sub get_load_average () {
>         # the previous way to get this information was from parsing the
>"top"
>         # output, IMHO that is senseless when you can just use uptime and
>have
>         # the date right there with little parsing needs.
>         $ldavg = `uptime`;
>                 # remove linefeeds from the output
>                 chomp($ldavg);
>                 # remove the leadeing space from the output
>                 $ldavg =~ s/^\s+//;
>                 # parse the data on spaces and store the data
>                 # from the output
>                 ($avg1,$avg2,$avg3) = ( split ( /\s+/,$ldavg)) [9,10,11];
>                 # remove the ugly ","
>                 $avg1 =~ s/,//;
>                 $avg2 =~ s/,//;
>                 $avg3 =~ s/,//;

I would have done this as:

         ($avg1, $avg2, $avg3) = (`uptime` =~ /average: (.*?), (.*), (.*)/);

>}
>
>sub get_oracle_time () {
># Lets get the time it takes to connect to oracle
>         my ( $key, $value );
>         $oratime = qx(
>(timex sqlplus $RTDUSER/$RTDPASS\@RTD_ORACLE_SID <<-!>/dev/null
>quit
>!
>) 2>&1);

If you just want to time how long something takes, I'd use Time::HiRes 
instead of calling timex.  Oh wait, you're getting the user and system time 
as well as wallclock.  Sure you care about those?

>         # remove lineffeds from the output
>         $oratime =~ tr/\n//s;
>         # removeing any linefeeds at the begining of a line
>         $oratime =~ tr/^\n//;
>         # remove any leading speaces
>         $oratime =~ s/^\s+//;
>         # split the date into two variables
>         ($key,$value) = split(/\s+/,$oratime);
>         # populate the hash, the key will be the first column (real, usr and
>sys)
>         # the value will be the corresponding data from the output
>         $otime{$key} = $value;
>
>}
>
>sub get_client_time () {
># Lets get the time it takes to connect to oracle and get a single worksheet

[snip same code as above] - Make a subroutine just for calling timex on 
something.

>sub get_errors () {
>         # Here is the big dady of sub-routines
>         # it looks small, but man oh man is it key
>         # to the sucess of this script
>
>         # start a timer for this sub-routine
>         my $t0 = new Benchmark;
>         # ensure each value key of results is
>         # 0 when we start, if not we get major errors
>         foreach my $key ( keys %lookFor ) { $results{$key} = 0; }
>         # run the perl script that forks 3 egreps on the
>         # logs and parse the data real time.
>         open(COM, "parse.pl |") || die("fork failed: \l$!\n");
>             while (<COM>) {
>                 # increment the number of occurances we see
>                 # for a certain error.
>                 # this will become our error count for
>                 # statistical and reporting output
>                 foreach my $test (keys %lookFor) {

This is the part that can be sped up.  A lot.  Instead of checking all the 
possible things to match one at a time, you want to construct a regex that 
looks for all of them at once.  The basic approach is something like:

$regex = 'join ('|', keys %lookFor);
if (/($regex)/o) {
   # Now switch on $1 for your specific sub-tests like /Factory/ etc
}

If you're looking for a speedup, this is the place to get it.

>                         if ( $test eq "Communication" ) {
>                                 $results{$test}++ if ( $_ =~ /$test/ && $_
>=~ /failure/);
>                                 next;
>                         }
>
>                         if ( $test eq "Bind" ) {
>                                 $results{$test}++ if ($_ =~ /$test/ && $_ =~
>/Factory/ && $_ =~ /failed/);
>                                 next;
>                         }

[snip]

Okay, I've run out of steam... but that'll give you a start.

--
Peter Scott
Pacific Systems Design Technologies
http://www.perldebugged.com


-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to