start 18.840ms average per iteration end 2.222ms average per iteration 88% less time or 847% improvement? #### As provided. NOTE: Numerous "Use of uninitialized value in..." lines 28, 32, 54, 57 25 trials of GMDT (471.000ms total), 18.840ms/trial Editing lines 27,28, 29 giving $szIntegerPart = ($2||''); $szDecimalPart = ($4||'') . ($6||''); $szFloatPart = $7||''; 25 trials of GMDT (250.000ms total), 10.000ms/trial Converted if (condition) { return 'constant'; } to return 'constant' if condition; 25 trials of GMDT (200.000ms total), 8.000ms/trial Changed if (not defined $varValue) { return 'NULL' } to return 'NULL' unless $varValue; 25 trials of GMDT (151ms total), 6.040ms/trial Chnaged $iLength = length $varValue; return( 'CHAR(' . $iLength . ')' ); to return 'CHAR(' . length($varValue) . ')'; and removed redundant variable; 25 trials of GMDT (100.000ms total), 4ms/trial Changed my $varValue = shift(@_)]; my ($iScale, $iPrecision my ($szIntegerPart, $szDecimalPart, $szFloatPart); to my $varValue = $_[0]; my ($iScale, $iPrecision, $szIntegerPart, $szDecimalPart, $szFloatPart); 25 trials of GMDT (121.000ms total), 4.840ms/trial Changed constant numeric expressions to constant subs. use constant SHORT_MIN => -32768; use constant SHORT_MAX => 32767; use constant LONG_MIN => -2147483648; use constant LONG_MAX => 2147483647; use constant FLOAT_MIN => 1.175 * 10 ** -38; use constant FLOAT_MAX => 3.402 * 10 ** 38; use constant DOUBLE_MIN => 1.175 * 10 ** -308; use constant DOUBLE_MAX => 3.402 * 10 ** 308; 25 trials of GMDT (90ms total), 3.600ms/trial Changed # 1 2 3 4 5 6 7 if ($varValue =~ /^ [+-]? ( (\d+) (\.(\d*))? | (\.(\d+)) ) ([Ee][+-]?\d+)? $/ox ) { $szIntegerPart = ($2||''); $szDecimalPart = ($4||'') . ($6||''); $szFloatPart = ($7||''); to if ($varValue =~ /^ [+-]? (?: (\d+) (?:\.(\d*))? | (?:\.(\d+)) ) ([Ee][+-]?\d+)? $/ox ) { #Check for numeric types $szIntegerPart = ($1||''); $szDecimalPart = ($2||'') . ($3||''); $szFloatPart = ($4||''); No discernable difference over 25 trials - increased number of trials from 25 to 500 500 trials of GMDT (1.455s total), 2.910ms/trial Moved return from string to top of sub, return 'CHAR(' . length($varValue) . ')' unless $varValue =~ /^ [+-]? (?: (\d+) (?:\.(\d*))? | (?:\.(\d+)) ) ([Ee][+-]?\d+)? $/ox ; 500 trials of GMDT (1.201s total), 2.402ms/trial Made the regex a constant sub. Difference to small to be sure of any advantage one way or the other. use constant RE_NUMERIC => qr/^ [+-]? (?: (\d+) (?:\.(\d*))? | (?:\.(\d+)) ) ([Ee][+-]?\d+)? $/x; ... unless $varValue =~ RE_NUMERIC; 500 trials of GMDT (1.111s total), 2.222ms/trial #### #! perl -slw use Benchmark::Timer; use strict; use constant SHORT_MIN => -32768; use constant SHORT_MAX => 32767; use constant LONG_MIN => -2147483648; use constant LONG_MAX => 2147483647; use constant FLOAT_MIN => 1.175 * 10 ** -38; use constant FLOAT_MAX => 3.402 * 10 ** 38; use constant DOUBLE_MIN => 1.175 * 10 ** -308; use constant DOUBLE_MAX => 3.402 * 10 ** 308; use constant RE_NUMERIC => qr/^ [+-]? (?: (\d+) (?:\.(\d*))? | (?:\.(\d+)) ) ([Ee][+-]?\d+)? $/x; my $t = new Benchmark::Timer; while( ) { $t->start('GMDT'); print GetMinimalDataType($_); $t->stop('GMDT'); }; $t->report; exit; sub GetMinimalDataType { my $varValue = $_[0]; my ($iScale, $iPrecision, $szIntegerPart, $szDecimalPart, $szFloatPart); return 'NULL' unless $varValue; return 'CHAR(' . length($varValue) . ')' unless $varValue =~ RE_NUMERIC; #Check for numeric types $szIntegerPart = ($1||''); $szDecimalPart = ($2||'') . ($3||''); $szFloatPart = ($4||''); #Is this a simple integer? if ($szIntegerPart ne '' and $szDecimalPart eq '' and $szFloatPart eq '' ) { #SMALLINT 16 bits ?32,768 to 32,767 Signed short (word) return 'SMALLINT' if $varValue >= SHORT_MIN and $varValue <= SHORT_MAX; #INTEGER 32 bits ?2,147,483,648 to 2,147,483,647 Signed long (longword) return 'INTEGER' if $varValue >= LONG_MIN and $varValue <= LONG_MAX; } #Is this a simple decimal? if ( not $szFloatPart) { $iScale = length $szDecimalPart; $iPrecision = (length $szIntegerPart) + $iScale; return "DECIMAL($iPrecision,$iScale)" if $iPrecision >= 1 and $iPrecision <= 18 #Precision = 1 to 18 and $iScale >= 0 and $iScale <= 18 #Scale = 0 to 18 and $iScale <= $iPrecision; #Scale must be <= to precision } #Float maybe? #1.175 x 10 ?38 to 3.402 x 10 38 return 'FLOAT' if $varValue >= FLOAT_MIN and $varValue <= FLOAT_MAX; #2.225 x 10 ?308 to 1.797 x 10 308 return 'DOUBLE PRECISION' if $varValue >= DOUBLE_MIN and $varValue <= DOUBLE_MAX; #Dates here eventually # #Check for strings return 'CHAR(' . length($varValue) . ')'; } __DATA__ 0e0 0 +0 -0 1. 0.14 .14 1.24e5 24e5 -24e-5 2.3. 2.3.4 1..2 .1.1 4. .23-2147483648 2147483647 +2147483647 -2147483649 2147483648 10e10 10e-10 Dom Dominic Dominic Bush .... For the 500 trials I simply replicated the original test data 20 times.