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]