Dear Monks,
I do not know if this is actually the correct place to write my observations and ask for your questions, so bare with me in case of not correctly posting this question here.
I am not expert in scripting or in Perl, I am relative new programmer with a short experience, so my observations maybe are not the most correct ones.
Why to use Perl with Object Oriented approach?
I found on book Beginning Perl (Programmer to Programmer) written by Simon Cozens and Peter Wainwright. At chapter 11 Object-Oriented Perl the following quotation appears under the subject "Do you need OO?" page 336:
Object-oriented programs run slightly slower than equally-written procedural programs that do the same job, because packaging things into objects and passing objects around is expensive, both in terms of time and resources used. If you can get away without using object orientation, you probably should.The only the reason that I could come up with is to minimize and simplify the code and maybe, maybe, increase the process speed in some cases.
So in order to understand more about it I created my own experiment with and without Object Oriented approach. I tried to time the performance with assistance of Benchmark Tool.
I have two identical processes on the same script, on one of them sends the data from main.pl to the MySQL.pm module, the data are processed and send back to the main.pl script. The second process it does exactly the same process but instead of sending the data to another module completes the process on the same script. The purposes creating the same process twice on the same script is to test the execution speeds processes etc. by comparing them.
This is the main.plscript.
#!/usr/bin/perl use strict; use warnings; use MySQL; use DBD::mysql; use Data::Dumper; use Config::Simple; use Benchmark qw(:all); my $path = 'conf.ini'; my $checkExist; my %config; my $count = -5 || die "Need a count!\n"; sub MySQL_OO { my $range = 50; my $minimum = 100; my $random_number = int(rand($range)) + $minimum; my $time = time(); my $object = new MySQL( $time , $random_number ); my @input = $object->getInputDB(); return @input; } sub local_MySQL { Config::Simple->import_from("".$path."", \%config) or die Config::Simple->error(); #my $encrypted = password41($config{'MySQL.pass'}); # for MySQL 4. +1 or my $dbh = DBI->connect("dbi:mysql::".$config{'MySQL.host'}.":".$co +nfig{'MySQL.port'}."", "".$config{'MySQL.user'}."", #"".$encrypted."", "".$config{'MySQL.pass'}."", { 'PrintError' => 1, 'RaiseError' => 1 } ) or die "Could not connect to ". $config{'MySQL.host'} .": ". $DB +I::errstr ."\n"; my $databases = $dbh->do("SHOW DATABASES LIKE '".$config{'MySQL.db +'}."'") or die "Error: " .dbh->errstr. "\n"; if ($databases eq 1) { # printf "Database: ". $config{'MySQL.db'} ." exists not creating: + ". $config{'MySQL.db'} ."\n"; } else { # printf "Database: ". $config{'MySQL.db'} ." does not exist creat +ing: ". $config{'MySQL.db'} ."\n"; $checkExist = $dbh->do("CREATE DATABASE IF NOT EXISTS `".$conf +ig{'MySQL.db'}."`") or die "Could not create the: ".$config{'MySQL.db'}." error: " +. $dbh->errstr ."\n"; } # End of else $dbh->do("USE ".$config{'MySQL.db'}."") or die "Error: " .dbh->errstr. "\n"; my $tables = $dbh->do("SHOW TABLES FROM `".$config{'MySQL.db'}."` +WHERE Tables_in_".$config{'MySQL.db'}." LIKE '".$config{'MySQL.table' +}."'") or die "Error: " .dbh->errstr. "\n"; if ($tables eq 1) { # printf "Table: ".$config{'MySQL.table'}." exists not creating: " +.$config{'MySQL.table'}."\n"; } else { # printf "Table: ".$config{'MySQL.table'}." does not exist creatin +g: ".$config{'MySQL.table'}."\n"; $checkExist = $dbh->prepare("CREATE TABLE IF NOT EXISTS `".$config +{'MySQL.table'}."` ( `id` int(11) NOT NULL AUTO_INCREMENT, `UnixTime` int(11) NOT NULL, `losses` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREM +ENT=1 ;" , { "mysql_use_result" => 1 }); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } } # End of else my $range = 50; my $minimum = 100; my $random_number = int(rand($range)) + $minimum; my $time = time(); my @data = ($time,$random_number); $checkExist = $dbh->prepare("INSERT IGNORE INTO `".$config{'MySQL. +table'}."` (`UnixTime`, `losses`) VALUES ('".$time."','".$random_numb +er."')" , { "mysql_use_result" => 1 }); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } $checkExist->finish(); $dbh->disconnect(); return @data; } # End of mysql sub my $r = timethese ( $count , { 'MySQL_OO' => '&MySQL_OO', 'local_MySQL' => '&local_MySQL' } ); cmpthese $r; #print "This is the time from \@result: ".$result[0]."\n"; #print "This is the random_number from \@result: ".$result[1]."\n"; 1;
This is the MySQL.pm module which processes the data.
#!/usr/bin/perl use strict; use warnings; use DBD::mysql; use Config::Simple; $|=1; #flush every time the program my $path = 'conf.ini'; my $checkExist; my %config; package MySQL; sub new { Config::Simple->import_from("".$path."", \%config) or die Config::Simple->error(); #my $encrypted = password41($config{'MySQL.pass'}); # for MySQL 4. +1 or my $dbh = DBI->connect("dbi:mysql::".$config{'MySQL.host'}.":".$co +nfig{'MySQL.port'}."", "".$config{'MySQL.user'}."", #"".$encrypted."", "".$config{'MySQL.pass'}."", { 'PrintError' => 1, 'RaiseError' => 1 } ) or die "Could not connect to ". $config{'MySQL.host'} .": ". $DB +I::errstr ."\n"; my $databases = $dbh->do("SHOW DATABASES LIKE '".$config{'MySQL.db +'}."'") or die "Error: " .dbh->errstr. "\n"; if ($databases eq 1) { # printf "Database: ". $config{'MySQL.db'} ." exists not creating: + ". $config{'MySQL.db'} ."\n"; } else { # printf "Database: ". $config{'MySQL.db'} ." does not exist creat +ing: ". $config{'MySQL.db'} ."\n"; $checkExist = $dbh->do("CREATE DATABASE IF NOT EXISTS `".$conf +ig{'MySQL.db'}."`") or die "Could not create the: ".$config{'MySQL.db'}." error: " +. $dbh->errstr ."\n"; } # End of else $dbh->do("USE ".$config{'MySQL.db'}."") or die "Error: " .dbh->errstr. "\n"; my $tables = $dbh->do("SHOW TABLES FROM `".$config{'MySQL.db'}."` +WHERE Tables_in_".$config{'MySQL.db'}." LIKE '".$config{'MySQL.table' +}."'") or die "Error: " .dbh->errstr. "\n"; if ($tables eq 1) { # printf "Table: ".$config{'MySQL.table'}." exists not creating: " +.$config{'MySQL.table'}."\n"; } else { # printf "Table: ".$config{'MySQL.table'}." does not exist creatin +g: ".$config{'MySQL.table'}."\n"; $checkExist = $dbh->prepare("CREATE TABLE IF NOT EXISTS `".$config +{'MySQL.table'}."` ( `id` int(11) NOT NULL AUTO_INCREMENT, `UnixTime` int(11) NOT NULL, `losses` int(11) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREM +ENT=1 ;" , { "mysql_use_result" => 1 }); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } } # End of else my $class = shift; my $data = { _time => shift, _random_number => shift, }; # Print all the values just for clarification. #print "Time is $data->{_time}\n"; #print "Random Number is $data->{_random_number}\n"; bless $data, $class; $checkExist = $dbh->prepare("INSERT IGNORE INTO `".$config{'MySQL. +table'}."` (`UnixTime`, `losses`) VALUES ('".$data->{_time}."','".$da +ta->{_random_number}."')" , { "mysql_use_result" => 1 }); if (!$checkExist->execute()) { die "Error: ". $checkExist->errstr ."\n"; } $checkExist->finish(); $dbh->disconnect(); return $data; } # End of mysql sub sub getInputDB { my ( $data ) = @_; return $data->{_time} , $data->{_random_number}; } 1;
I am also including the conf.ini file in case that someone want to replicate the experiment.
[MySQL] user=******** pass=******** host=localhost port=3306 db=Speed table=Data
I contact the experiment 4 times to get different results and observe the output.
Output straight from my terminal:
Benchmark: running MySQL_OO, local_MySQL for at least 5 CPU seconds... MySQL_OO: 186 wallclock secs ( 4.69 usr + 0.77 sys = 5.46 CPU) @ 5 +63.92/s (n=3079) local_MySQL: 196 wallclock secs ( 4.78 usr + 0.79 sys = 5.57 CPU) @ +608.98/s (n=3392) Rate MySQL_OO local_MySQL MySQL_OO 564/s -- -7% local_MySQL 609/s 8% -- tiny@OS:~/Desktop/PeRl_MySQL$ perl main.pl Benchmark: running MySQL_OO, local_MySQL for at least 5 CPU seconds... MySQL_OO: 182 wallclock secs ( 4.55 usr + 0.72 sys = 5.27 CPU) @ 6 +16.89/s (n=3251) local_MySQL: 186 wallclock secs ( 5.00 usr + 0.82 sys = 5.82 CPU) @ +565.98/s (n=3294) Rate local_MySQL MySQL_OO local_MySQL 566/s -- -8% MySQL_OO 617/s 9% -- tiny@OS:~/Desktop/PeRl_MySQL$ perl main.pl Benchmark: running MySQL_OO, local_MySQL for at least 5 CPU seconds... MySQL_OO: 155 wallclock secs ( 4.33 usr + 0.73 sys = 5.06 CPU) @ 5 +58.10/s (n=2824) local_MySQL: 172 wallclock secs ( 4.45 usr + 0.76 sys = 5.21 CPU) @ +558.73/s (n=2911) Rate MySQL_OO local_MySQL MySQL_OO 558/s -- -0% local_MySQL 559/s 0% -- tiny@OS:~/Desktop/PeRl_MySQL$ perl main.pl Benchmark: running MySQL_OO, local_MySQL for at least 5 CPU seconds... MySQL_OO: 163 wallclock secs ( 4.41 usr + 0.72 sys = 5.13 CPU) @ 5 +47.56/s (n=2809) local_MySQL: 162 wallclock secs ( 4.55 usr + 0.75 sys = 5.30 CPU) @ +541.89/s (n=2872) Rate local_MySQL MySQL_OO local_MySQL 542/s -- -1% MySQL_OO 548/s 1% --
On the first run the results is as expected, the Object Oriented process was slower by 7%.
The impressive part one the rest of the rounds. It actually shows that the Object Oriented process is almost fast as the normal process and at some point it is even faster!
The book was written back on 2000, fourteen years ago. From my point of view Object Oriented programming is a huge advantage, it makes the code shorter and also possibly faster on some occasions.
So in conclusion, when a user should choose to follow an Object Oriented programming approach if the code is really long only?
Thank you all for your time and effort to assist me with my question/discussion.
|
|---|