I've got a script that runs through a loop of about 500 machine names, copies a file to each, executes it and puts the returned info into a database. Trouble is the script eats memory, maybe half a Gb!

I have no idea about good practise with regard to writing memory efficient scripts. Where do I start? I have checked the Camel book and SuperSearch but not found anything that hits me in the face. That said PP does have an efficency section which mentions avoiding 'tight' loops and excessive system calls. I have a lot of both, is there anything I can do to tidy up after them?

TIA

Oh and I ought to have said I have no idea whether my loops are 'tight' or not but there are lots of loops

Ok, I think you deserve a laugh, here's a cut down (slightly cut down) version of the code.
#! d:/perl/bin/perl.exe -w use Win32::ODBC; use File::ReadBackwards; use Net::Ping; if ($ARGV[0]) { Use this info somewhere in the script as variable $lik +e } else { $like = '1' } open (LOG, ">>PathToLog.txt"); &date(); ### # Get latest AV version ## if ($db = new Win32::ODBC("SWDHAP301")) {} else {die "Could not connect to database via DSN SWDHAP301\n"} $db->Sql("Query to find packageID of AntiVirus software package"); while ($db->FetchRow()) { Get result of query; Put sought after info into $ver; } $db->Close(); ### # Get name of next machines to try and install package on ## $db = new Win32::ODBC("avXtra"); $db->Sql("Query to get all machines requiring install"); while ($db->FetchRow()) { $var = $db->Data ; @servers = (@servers, $var); } $db->Close(); $no = @servers; print LOG "# STARTING SCRIPT @ $datetime\tetc etc #"; ### For all machines in list as requring install, attempt to install t +hem. LOOP: foreach $server (@servers){ $verRead = $avv = ''; print "\n$time\t$server"; &date(); my $p = Net::Ping->new(); $p->hires(); ($ret, $duration, $ip) = $p->ping($server, 5.5); if ($ret) { printf("\n[ip: $ip] alive (packet return time: %.2f ms)", 1000 * $ +duration); print " \n\tChecking current AV version in anplc.coe file\n"; ### CHECK IF CLIENT IS ACTUALLY UP TO DATE $path = "\\\\$server\\c\$\\anplc.coe"; if (-e "$path") { open (FILE, "$path"); @contents = <FILE>; close (FILE); } else { print "\tCouldnt open file on $server, What now?\n" } LOOP2: foreach $line (@contents) { if ($line =~ /Virus Update - .*(\d{4}).*/) { $verRead = $1 ; print "\tVersion of AV read from anplc.coe as part of chec +k was $1\n" ; last LOOP2 ; } } if ($verRead == $ver) { print "\tAV already upto date\n"; $db9 = new Win32::ODBC("avXtra"); $db9->Sql("Update db to show client now up to date"); $db9->Close(); next LOOP; } else { print "\tVersion of client read as $verRead\n\t Continuing +with script copy and install...\n"} print LOG "Something, $aVariable, something else"; $var2 = `copy D:\\Perl\\bin\\avXtra\\$PackageSourceFiles\\$fil +ename \\\\$server\\c\$\\$filename`; if ($var2=~/1 file\(s\) copied./) { print " Copied "; print LO +G "something";} else { print " Copy Failed $var2 "; print LOG "Something" ; &FAILED(Copy_Failed_Path_Not_Found); next LOOP; } print LOG "Another something including say $datetime"; $var = `D:\\GetSupport\\utils\\psexec \\\\$server -i \"c:\\$fi +lename\" -f`; print LOG "$datetime again"; if ($var=~/error code 0/) { print " Executed Succesfully "; pr +int LOG "$datetime...";} else { print " Execution Failed "; print LOG "and again ($date +time)" } ### Delete the package. Otherwise over time the users hard drive +will get full $var3 = `del \\\\$server\\c\$\\$filename`; print LOG "not funny now"; ### Update the db with the correct version as now installed $path = "\\\\$server\\c\$\\anplc.coe"; if ($bw = File::ReadBackwards->new( "$path" )){ while(($log_line = $bw->readline)){ @array = ($log_line, @array); } } LOOP: foreach $line (@array){ if ($line =~ /Virus Update - .*(\d{4}).*/) { $avv = $1 + ; last LOOP } } $db = new Win32::ODBC("avXtra"); print "\nAV_Version = $avv , lastUpdated = $SQLdateTime , Comment += ScriptInstalled WHERE machineName like $server\n"; $db->Sql("UPDATE tbl_avXtra_main SET AV_Version = '$avv' , lastUpd +ated = '$SQLdateTime' , Comment = 'ScriptInstalled' WHERE machineName + like '$server'"); $db->Close(); } # Endof PING loop else { print " Not On Network "; print LOG "\n$datetime\t$server not on network" ; $db6 = new Win32::ODBC("avXtra"); $db6->Sql("UPDATE tbl_avXtra_main SET lastUpdated = '$SQLdateT +ime' WHERE machineName like '$server'"); $db6->Close(); } } # Endof server loop close (LOG); sub date { create some variables relating to date and time here } sub FAILED { $db = new Win32::ODBC("avXtra"); $db->Sql("UPDATE tbl_avXtra_main SET lastUpdated = '$SQLdateTime' , Co +mment = '$_[0]' WHERE machineName like '$server'"); $db->Close(); } exit 0;

In reply to Memory Leak Advice by 2mths

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.