LinuxQuestions.org
Latest LQ Deal: Latest LQ Deals
Go Back   LinuxQuestions.org > Forums > Linux Forums > Linux - General
User Name
Password
Linux - General This Linux forum is for general Linux questions and discussion.
If it is Linux Related and doesn't seem to fit in any other forum then this is the place.

Notices


Reply
  Search this Thread
Old 05-05-2003, 11:26 AM   #1
jiffy1111
LQ Newbie
 
Registered: May 2003
Distribution: Redhat/Slackware
Posts: 5

Rep: Reputation: 0
Performance issues with Redhat 8/9 vs other distros


Hi,
I've recently run into a little performance issue with Redhat 8 & 9. It seems that a perl script that I wrote is much slower on Redhat than on any other distro I've tried (Mandrake 9/9.1, Gentoo 1.4rc4 & Slackware 9).

The hardware is a 500MHz PIII, 128Meg RAM and a 6G HD. I used the same PC for all the distros (I've been doing a lot of rebuilding). All cron/at jobs and unnecessary services have been stopped. The kernel has been recompiled from vanilla source and the same .config was used on all distros.

Now for the problem:
The script consistently takes 17 minutes on RH and under 30 seconds on the others. It uses DBI, DBD:mysql and Mail::Sendmail modules. The new kernel proved to be no faster or slower compared to the "out of the box" one. I don't know what else to try.

Has anyone else seen performance issues?
Any ideas?

Thanks,
Jiffy1111
 
Old 05-05-2003, 03:32 PM   #2
td3201
Member
 
Registered: Jan 2002
Location: Omaha, NE US
Distribution: Red Hat/CentOS
Posts: 226

Rep: Reputation: 30
Wow....that is a big difference. I would paste your script here if you dont mind, or rather, place a link for us to view it online. Something is definately not right there.

I would break your script down into runnable pieces, perhaps by module first, then by function to see where it is taking so long.

I always stick with the redhat kernel unless I use a kernel patch like freeswan or lids....probably for no reason other than I am lazy and dont see the need for it. I can understand why you used a vanilla kernel here.
 
Old 05-06-2003, 06:57 AM   #3
jiffy1111
LQ Newbie
 
Registered: May 2003
Distribution: Redhat/Slackware
Posts: 5

Original Poster
Rep: Reputation: 0
Ok, here's the script. Please note usernames, passwords and email and ip addresses have been replace with "deleted", they're not typos. And thanks in advance.

#!/usr/bin/perl -w

# BEGIN COMMENT
#
# Program name : configure_pingsaint.pl
# Original date : 03/07/03
# Revision date : 03/07/03
# : 03/20/03
# : 04/21/03
# Author : J. Novick
# Description : Creates three configuration files needed by PingSaint
# : from the node names listed in the 'metrics' database
# : table 'ping'. It preserves the original file by reading
# : it in and comparing the lines to the node names from the
# : database - adding or deleting as needed and re-writing
# : everything else to the output files. This way, if you
# : make any kind of change to a current configuration file
# : the change won't be lost.
# Input files : services.cfg, hosts.cfg, hostgroups.cfg
# Output files : services.cfg, hosts.cfg, hostgroups.cfg
# Modules called :
# Global variables :
# Specific OS :
# Known restrictions:
# Error messages :
# Notifications :
#
#
# END COMMENT

use POSIX;
use strict;
use DBI;
use Time::Local;
use Mail::Sendmail;

#
# General-use variables
#

my $savehostgrp = ""; # Configure-PingSaint host grp line
my $cycle_cnt = 0; # Cycle log counter
my $drop_flag = ""; # Drop-a-record flag
my $header = ""; # A header line
my $cycle = "cp_cycle.txt"; # Cycle log filespec
my $dfile = "cp_debug.txt"; # Debugging filespec
my $tfile = "cfg_temp.txt"; # Temporary .cfg filespec
my $file1 = "services.cfg"; # Input/Output filespecs
my $file2 = "hostgroups.cfg";
my $file3 = "hosts.cfg";
my $semi1 = ""; # Used in processing Hostgroups.cfg
my $semi2 = "";
my $semi3 = "";
my $defl1 = ""; # Default lines for the .cfg files
my $defl2 = "";
my $defl3 = "";
my $lcnuq = ""; # Lower case node name, unqualified
my $debug = 0; # Debug flag
my $dill = 0; # DILBERT's flag
my $junk = ""; # String garbage
my $file = ""; # Full filespec
my $path = ""; # Base file path
my $line = ""; # Just a string
my $node = ""; # Single node name
my $hdr = ""; # Header information
my $cmd = ""; # Service start command line
my $msg = ""; # A message string
my $lcn = ""; # Lower case node name
my $ucn = ""; # Upper case node name
my $i = ""; # Just variables
my $j = "";
my $k = "";
my $l = "";

my $d0 = ""; # Used in date formatting
my $d1 = "";
my $d2 = "";
my $d3 = "";
my $d4 = "";
my $d5 = "";
my $d6 = "";
my $d7 = "";
my $d8 = "";
my $idx = "";
my $doty = "";
my $edate = "";
my $sdate = "";
my $xdate = "";
my $ydate = "";
my $zdate = "";

my @deflns = (); # Array of default lines
my @cpynds = (); # A working copy of @nodes
my @nodes = (); # Array of node names from DB
my @files = (); # Array of .cfg filespecs
my @ary = (); # .cfg input array
my @bry = (); # .cfg output array
my @cry = (); # All the hosts in Hostgroups.cfg

my @days = qw (Sunday Monday Tuesday Wednesday Thursday Friday Saturday);
my @months = qw (January February March April May June July August
September October November December);

#
# Mail definitions (Mail::Sendmail)
#

my %mail = (); # Hash array for E-mail
my $me = "deleted; "; # The default recipient

#
# Database definitions.
#

my $metric = "DBI:mysql:metrics:ipaddress-deleted";

my $username = "deleted"; # Do I really have to
my $password = "deleted"; # explain these?!
my $errflg = ""; # DB connection error flag
my $dbh; # Database handle for application
my $sth; # Statment handle for application

#
#######################################################################
#
# Subroutine Section
#
#######################################################################
#

#
# Log everything to the debug file, if its open.
#

sub dlog
{
my @mess = @_;

if ($debug != 0) { print DB ($mess[0]); }
return;
}

#
# Timestamp
#

sub ts
{
my $ts = "";

$d4 = (localtime ())[2];
if (length ($d4) == 1) { $d4 = "0" . $d4; } # 2-digit hour
$d5 = (localtime)[1];
if (length ($d5) == 1) { $d5 = "0" . $d5; } # 2-digit minute
$d6 = (localtime)[0];
if (length ($d6) == 1) { $d6 = "0" . $d6; } # 2-digit second

$ts = $d4 . ":" . $d5 . ":" . $d6;

return ($ts);
}

#
# Send an E-mail to everyone listed in $me one receipient at a time
# because the mail module has trouble with too many addresses(?).
#

sub mail_it
{
my @msg = @_;
my @to_ary = ();
my $to = "";
my $mflag = "";

(@to_ary) = split ("; ", $me); # Make a nice array of names

foreach $to (@to_ary)
{
$mflag = 0;
%mail = (Server => 'deleted',
To => $to,
From => 'configure_pingsaint.pl',
Subject => 'Alert Message',
Message => $msg[0]);

sendmail (%mail) or $mflag = 1;

if ($mflag != 0)
{ dlog ("To: $to Error: " . $Mail::Sendmail::error . "\n\n"); }
}
return;
}

#
#######################################################################
#
# Start of Execution
#
#######################################################################
#

#
# Set up the base path for the filespecs.
#

$path = "/usr/local/netsaint/etc/"; # Pingsaint's base path

if (defined ($ENV {COMPUTERNAME}))
{
if ($ENV {COMPUTERNAME} eq "DILBERT")
{ $path = "C:/Program Files/perl/scripts/ping_upgrade/"; $dill = 1;}
}

$cycle = $path . $cycle; # Cycle log filespec
$dfile = $path . $dfile; # Debugging filespec
$tfile = $path . $tfile; # Temporary .cfg filespec

$files[0] = $path . $file1; # Output filespecs array
$files[1] = $path . $file2;
$files[2] = $path . $file3;

#
# Setup default entries for each of the three files. The <UpCX> will get
# replaced by the node name in capitals while <LoWX> gets replaced by the
# node's lower case name. <LoWXUQ> is the lower case, unqualified node
# name (drop the <.tru.com>).
#

$defl1 = "service[LoWX]=PING;0;24x7;3;2;1;entmgt;120;24x7;1;1;1;;check_ping_2";
$defl2 = "hostgroup[Configure-PingSaint]=Configure-PingSaint;entmgt;LoWXUQ";
$defl3 = "host[LoWX]=UpCX;LoWX.tru.com;;check-host-alive;1;120;24x7;0;0;0;";

$deflns[0] = $defl1;
$deflns[1] = $defl2;
$deflns[2] = $defl3;

#
# Check if the debug file, CP_DEBUG.TXT, exists. If it doesn't,
# just skip this part. If it does, check the size of the file to ensure
# we don't fill up the disc drive. If the file is over 10Mb, clobber
# it and start a new recording.
#

$debug = 0;
if (-e $dfile)
{
$i = -s $dfile; # Get the file's size
if ($i < 10000000)
{
open (DB, ">> $dfile"); # Append to it
print DB ("\n\n");
}
else
{
open (DB, "> $dfile"); # Clobber and write to it
print DB ("Debug file for CONFIGURE_PINGSAINT\.PL\n\n");
}
$debug = 1;
}

#
# Compute a bunch of formatted timestamp strings:
# $xdate ==> 07/16/01
# $ydate ==> Monday, July 16, 2001 (doty: 197)
# $zdate ==> 10:03:37
#

$d0 = 1900 + (localtime ())[5]; # 4-digit year
$d1 = substr ($d0,2,2); # 2-digit year
$d2 = 1 + (localtime ())[4];
if (length ($d2) == 1) { $d2 = "0" . $d2; } # 2-digit month
$d3 = (localtime ())[3];
if (length ($d3) == 1) { $d3 = "0" . $d3; } # 2-digit day
$d4 = (localtime ())[2];
if (length ($d4) == 1) { $d4 = "0" . $d4; } # 2-digit hour
$d5 = (localtime)[1];
if (length ($d5) == 1) { $d5 = "0" . $d5; } # 2-digit minute
$d6 = (localtime)[0];
if (length ($d6) == 1) { $d6 = "0" . $d6; } # 2-digit second

$d7 = $days[(localtime ())[6]];
$d8 = $months[(localtime ())[4]];

$idx = 1 + (localtime ())[7]; # Day-of-the-year
$xdate = $d2 . "/" . $d3 . "/" . $d1; # dd/mm/yy
$ydate = $d7 . ", " . $d8 . " " . (localtime ())[3] . ", " . $d0;
$ydate = $ydate . " (doty: " . $idx . ")";
$zdate = $d4 . ":" . $d5 . ":" . $d6;
$sdate = ($d4 * 3600) + ($d5 * 60) + $d6; # Start time in seconds

dlog ("$xdate - $ydate - $zdate\n\n");

#
# Put the six-line header paragraph together. ($header is used later to
# decide if the input file already has a header that needs to be dropped.
# That's why its setup as a separate variable.)
#

$header = "# This file was created by: configure_pingsaint.pl";

$hdr = "
################################################################################
#
$header
#
# $xdate - $zdate
#
";

$hdr =~ s/^\s+|\s+$//g; # Remove leading & trailing spaces

#
# Connect to the metric database. If it fails, issue an E-mail, otherwise,
# read-in all the nodes into the @nodes array
#

$errflg = 0;
$dbh = DBI -> connect ($metric, $username, $password)
or $errflg = 1;

if ($errflg > 0)
{
$msg = "ERROR opening up the database: $metric\n";
$msg = $msg . $DBI::err . "\n" . $DBI::errstr . "\n";
mail_it ($msg);
}

dlog ("Opened the '" . $metric . "' database.\n\n");

(@nodes) = @{$dbh -> selectcol_arrayref ("SELECT node FROM ping")};

dlog (" Database node array:\n");
foreach $i (@nodes) { dlog (" $i\n"); }
dlog (("\n Total node count: " . ($#nodes + 1) . "\n\n"));

#
# Read each of the three files, Services.cfg, Hostgroups.cfg, and Hosts.cfg,
# into the @ary array one at a time. Copy the @nodes array to the @cpynds
# array adding the "used" file flag. Compare each record of the @ary to
# each node in the @cpynds array. If a record matches a node, put the record
# into the output array, @bry, and mark it "used" in the @cpynds array. If
# the record is a comment line, <#>, or a blank line, <\n> put it into the
# output array, also. If a record doesn't match any node, just drop it
# (deletions). When the whole @ary has been processed, check if any nodes
# are left unmarked in the @cpynds array. If there are, create a record for
# them in the @bry array (additions) using the default line for the
# particular file being processed.
#

for ($i=0; $i<@files; $i++)
{
$file = $files[$i]; # Just makes it simpler

dlog ((" Timestamp: " . ts () . "\n")); # Timestamp the log
dlog (" Processing file: $file\n\n");

@ary = (); # Clear all the arrays for
@bry = (); # "this" file
@cpynds = ();

foreach $node (@nodes)
{
push (@cpynds, $node);
push (@cpynds, 0); # Add the "used" flag
}

open (FI, "< $file") or die ("Can not open file: $file - $!\n");
while ($line = <FI>)
{
$line =~ s/\r//g; # Remove any line terminators
$line =~ s/\n//g;
push (@ary, $line);

dlog ((" " . $line . "\n"));
}
close (FI);

dlog ("\n");

#
# If this file was already created by configure_pingsaint.pl its got
# header information we have to drop. Check it and adjust the array,
# if necessary, by dropping the first six lines.
#

for ($j=0; $j<7; $j++)
{ if ($ary[$j] =~ /$header/) { splice (@ary, 0, 6); last;} }

push (@bry, $hdr); # "This" script's new header info

#
# OK, now start processing the file that was just read in.
#

foreach $line (@ary)
{
if ((length ($line) > 4) and ($line !~ /^#/))
{

#
# Process the Services.cfg file (1) and the Hosts.cfg file (3)
# the same way. The Hostgroups.cfg file (2) requires extra
# processing because each record contains a string of host names.
#

if ($i != 1)
{ # Processing: Services or Hosts
$drop_flag = 0;

for ($k=0; $k<@cpynds; $k+=2) # Node names from the database
{

#
# Unqualifiy the node name but check for both - case insensitive
#

($node, $junk) = split (/\./, $cpynds[$k], 2);

if (($line =~ /\[$node\]/i) or ($line =~ /\[$cpynds[$k]\]/i))
{
$cpynds[$k+1] = 1; # Mark the entry "used"
$drop_flag = 1; # Don't drop this record
last;
}
}

if ($drop_flag == 0)
{
dlog (" Dropped the following record:\n");
dlog ((" " . $line . "\n\n"));
}
else
{ push (@bry, $line); }
}
else
{ # Processing: Hostgroups

#
# Split the line up into 3 the groups based on a semicolon <;>.
# The 3rd group contains all the host nodes. Split that group up
# based on the comma <,> delimiter. Then check each host and put
# the whole record back together and write it out.
#

($semi1, $semi2, $semi3) = split (/;/, $line);
@cry = split (/,/, $semi3);

$line = $semi1 . ";" . $semi2 . ";";

for ($l=0; $l<@cry; $l++)
{
$drop_flag = 0;
for ($k=0; $k<@cpynds; $k+=2) # Node names from the database
{

#
# Unqualifiy the node name and compare it (case insensitive)
# to the host name we're working on. If it matches, set the
# "used" flag in the @cpynds array and add the host name (and
# a comma <,>) to the string we're building.
#

($node, $junk) = split (/\./, $cpynds[$k], 2);

if (($cry[$l] =~ /^$node$/i) or ($cry[$l] =~ /^$cpynds[$k]$/i))
{
$cpynds[$k+1] = 1;
$line = $line . $cry[$l] . ",";
$drop_flag = 1;
last;
}
}
if ($drop_flag == 0)
{
dlog (" Dropped the following host:\n");
dlog ((" " . $cry[$l] . "\n\n"));
}
}
chop ($line); # Drop the last comma <,>
push (@bry, $line);

if ($line =~ /Configure-PingSaint/)
{ $savehostgrp = $line; } # Save the line for [maybe] later
}
}
else
{ push (@bry, $line); } # A comment or a blank line
}

#
# Run down the @cpynds array to see if they're all accounted for. If
# any "used" flag entries are 0 it means we need to add that host to
# its corresponding configuration file.
#
# NOTE: If the addition is to the Hostgroups.cfg file its added to the
# Configure-PingSaint group (if it exists). It can always be
# edited later.
#

for ($k=0; $k<@cpynds; $k+=2)
{
if ($cpynds[$k+1] == 0) # Any leftover nodes to add?
{
($node, $junk) = split (/\./, $cpynds[$k], 2);
$lcn = lc ($node); # Lower case node name
$ucn = uc ($node); # Upper case node name
if ($savehostgrp eq "") # Configure-PingSaint group?
{
$line = $deflns[$i];
$line =~ s/LoWXUQ/$lcn/g;
$line =~ s/LoWX/$lcn/g;
$line =~ s/UpCX/$ucn/g;
}
else
{
$line = $savehostgrp . ";" . $lcn; # Tack it on at the end of the line
}
push (@bry, $line);

dlog (" Added the following record:\n");
dlog ((" " . $line . "\n\n"));
}
}

#
# Write the @bry to the temporary configuration file, cfg_temp.txt,
# then delete the input file and rename the temp file. Make 'netsaint'
# the file's owner.
#

open (TF, "> $tfile") or die ("Can not open file: $tfile - $!\n");
foreach $k (@bry) { print TF ("$k\n"); }
close (TF);

unlink ($file);
rename ($tfile, $file);
if ($dill == 0) { `chown netsaint\.netsaint $file`; }
}

$dbh -> disconnect (); # Disconnect sessions & database

#
# Increment and timestamp the cycle counter log file which I use
# just to make sure everything's running OK - cp_cycle.txt.
#

$cycle_cnt = $cycle_cnt + 1;
if (-e $cycle)
{
open (CC, "<$cycle"); # Open it for: R
$cycle_cnt = <CC>; # Read in the value
close (CC); # Close it
$cycle_cnt = $cycle_cnt + 1; # Increment the count
}
open (CC, ">$cycle"); # Open it for: W
print CC ($cycle_cnt); # Write out the value and
print CC ("\n$ydate - $zdate\n"); # timestamp it
close (CC); # Close it

if ($debug != 0)
{
$d4 = (localtime ())[2];
if (length ($d4) == 1) { $d4 = "0" . $d4; } # 2-digit hour
$d5 = (localtime)[1];
if (length ($d5) == 1) { $d5 = "0" . $d5; } # 2-digit minute
$d6 = (localtime)[0];
if (length ($d6) == 1) { $d6 = "0" . $d6; } # 2-digit second

$edate = $d4 . ":" . $d5 . ":" . $d6;

$d3 = (($d4 * 3600) + ($d5 * 60) + $d6) - $sdate;
$d0 = int ($d3 / 3600);
$d1 = int (($d3 - ($d0 * 3600)) / 60);
$d2 = $d3 - ($d0 * 3600) - ($d1 * 60);

if ($d0 < 10) { $d0 = "0" . $d0; }
if ($d1 < 10) { $d1 = "0" . $d1; }
if ($d2 < 10) { $d2 = "0" . $d2; }

print DB (" Ending run time : $edate Delta: $d0:$d1:$d2\n\n");

print DB (" Cycle Count : $cycle_cnt\n");
close (DB);
}

exit;

#
#
# End of file.
 
Old 05-06-2003, 08:22 AM   #4
td3201
Member
 
Registered: Jan 2002
Location: Omaha, NE US
Distribution: Red Hat/CentOS
Posts: 226

Rep: Reputation: 30
As expected, your script looks fine. I am guessing that your slow down has to do with the mail::sendmail return or mysql return.

Break your script down into pieces like I suggested, or rather, just write a different program that utilizes the same functions....like write a script that simply sends you a piece of email in the same way this one does.

You can kind of narrow it down by looking at your mysql logs as well sa your sendmail logs to see when the connection is being started, etc...
 
Old 05-06-2003, 10:28 AM   #5
jiffy1111
LQ Newbie
 
Registered: May 2003
Distribution: Redhat/Slackware
Posts: 5

Original Poster
Rep: Reputation: 0
Hi, Terry

Thanks for you suggestions, but, in the interim I've taken a slightly different approach, please don't be offended, I will try your suggestions if you feel I still should after reading this.

Here's what I've got.

Sendmail only sends an email when the MySQL server isn't responding and the MySQL server responds almost instantaneously, so I think I can eliminate them for now.

Now, I have two PC's of identical hardware, one RH 9 and one Slackware 9. I run the script at the same time on both boxes with the same results, Slack wins and RH is a dog every time. With that, I'm guessing I can eliminate the servers and the network as the bottle neck. I even swapped the hard drives from one to the other with the same results, trying to eliminate hardware issues.

I'm pretty sure the bottleneck is definately in the file parsing sections in the the script. But I'm confused as to why this script is an order of magnitude faster on Slackware.

Oh, and both are ReiserFS mounted with noatime, notail.

Jeff
 
Old 05-06-2003, 10:32 AM   #6
td3201
Member
 
Registered: Jan 2002
Location: Omaha, NE US
Distribution: Red Hat/CentOS
Posts: 226

Rep: Reputation: 30
No offense here.

What are the perl versions?
 
Old 05-06-2003, 11:52 AM   #7
jiffy1111
LQ Newbie
 
Registered: May 2003
Distribution: Redhat/Slackware
Posts: 5

Original Poster
Rep: Reputation: 0
Perl 5.8.0 on both
 
Old 07-02-2003, 02:20 PM   #8
jgaraas
LQ Newbie
 
Registered: May 2003
Posts: 27

Rep: Reputation: 15
I'm just going on a hunch here but it may lead to a possible solution. Looking at your script it sends out a single email to each recipient one at a time. I'm not to sure how slackware is set up, but when I was setting up my RedHat 8 email server using sendmail it was a complete dog when authenticating and sending mail. I found that if I add the appropriate host to IP notation in the host file for several local machines that I reduced the time to mear seconds instead of minutes for these proceses.
Depending on how many single emails you're sending out this could be your problem.

Hope this helps.
 
Old 07-03-2003, 06:07 AM   #9
jiffy1111
LQ Newbie
 
Registered: May 2003
Distribution: Redhat/Slackware
Posts: 5

Original Poster
Rep: Reputation: 0
Thanks, jgaraas,
but the script only sends the email if there was an error connecting to the database (Please re-read my response to Terry). By the way, there are only two people in that list right, but I will take your suggestion and apply it. A little extra performance here and there definitly won't hurt.

I also have other scripts that show the same symptoms.
I've just about given up on this because either noone is having this problem or not noticing it based on the (lack of) responses I've received here. Looking at migrating to Gentoo or Slackware. Both are an order of magnitude faster at running the same scripts on the same hardware with no modifications. Another script I have runs in 16 seconds on RH, which I thought was fine, until I ran it on Slackware for grins and it ran in 0.9 seconds.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Performance issues Tylerious Slackware 11 09-22-2005 08:35 AM
Performance issues clergykid Linux - Newbie 4 12-07-2004 04:41 PM
Performance Issues Gort32 Linux - Software 1 10-19-2004 01:46 PM
Performance issues? gurusmaran Linux - Newbie 2 03-18-2004 07:36 AM
RedHat 8.0 performance issues moodboy Linux - Newbie 9 03-11-2003 09:09 PM

LinuxQuestions.org > Forums > Linux Forums > Linux - General

All times are GMT -5. The time now is 11:49 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration