PEAR is archived and read-only

This mirror preserves historical PEAR package releases and metadata so existing references remain available.

Home » Database » DB » Bug #4185

Performances increased

Details

Request #4185Performances increased
Submitted2005-04-20 09:33 UTC
Fromfabien dot thierry at vie-medieval dot com
StatusWont fix
PackageDB
PHP Version5.0.3
OSLinux
Roadmaps(Not assigned)

Comments

[2005-04-20 09:33 UTC] fabien dot thierry at vie-medieval dot com

Description:
------------
I have a script which took 40% of his time (1250ms) in two methods:
_convertNullArrayValuesToEmpty and _rtrimArrayValues (called by fetchInto)

These two methods are quite identical. So, I have added a new method in Common.php, to use only one 'foreach'.
So, I have updated the fetchInto method to use this new method.

Now, the fetchInto execution time in my script is: 850ms (32% of gain)...

I have tested this update only with 'mysql.php'...

:-)

Reproduce code:
---------------
/***********************************************
* In the end of fetchInto method
***********************************************/
if ($this->options['portability'] & DB_PORTABILITY_RTRIM && $this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY){
$this->_rtrim_and_convertNullArrayValuesToEmpty($arr);
} else {
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
/*
* Even though this DBMS already trims output, we do this because
* a field might have intentional whitespace at the end that
* gets removed by DB_PORTABILITY_RTRIM under another driver.
*/
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
}

/***********************************************
* The new method in Common.php
***********************************************/
/**
* Convert all null values in an array to empty strings and rtrim string values
*
* @param array $array the array to be de-nullified (passed by reference)
* @return void
* @access private
*/
function _rtrim_and_convertNullArrayValuesToEmpty(&$array)
{
foreach ($array as $key => $value) {
if (is_null($value)) {
$array[$key] = '';
}elseif (is_string($value)) {
$array[$key] = rtrim($value);
}
}
}

Expected result:
----------------
Gain of performances

Actual result:
--------------
32% of gain

[2005-04-20 09:52 UTC] smith at backendmedia dot com

Maybe we should explore using http://www.php.net/array_walk here. then we dont need to use a foreach at all.

[2005-04-20 11:53 UTC] fabien dot thierry at vie-medieval dot com

I have tested array_walk by modifying 'my' method _rtrim_and_convertNullArrayValuesToEmpty.

So, array_walk is slowest: 1050ms (with array_walk) vs 850ms (with foreach)

This the code I used:

function _rtrim_and_convertNullArrayValuesToEmpty(&$array)
{
array_walk($array, array($this, '_rtrim_and_convertNullValueToEmpty'));
}

function _rtrim_and_convertNullValueToEmpty(&$item, $key){
if (is_null($item))
$item = '';
elseif (is_string($item))
$item = rtrim($item);
}

:-)

[2005-04-20 12:01 UTC] smith at backendmedia dot com

Now this is unexpected. I know this is not what you are drving at, but how about when just using rtrim() as the call back versus the _rtrimArrayValues() method?

[2005-04-20 12:16 UTC] fabien dot thierry at vie-medieval dot com

With the original code using array_walk, it is still worse!

This is the code:

/**************************
in mysql.php - method fetchInto
**************************/
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
array_walk($arr, array($this, '_rtrim_Value'));
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
array_walk($arr, array($this, '_convertNullValueToEmpty'));
}

/**************************
in common.php
**************************/
function _rtrim_Value(&$item, $key){
if (is_string($item)) {
$item = rtrim($item);
}
}
function _convertNullValueToEmpty(&$item, $key){
if (is_null($item)) {
$item = '';
}
}

**********************************************************
Conclusion:
1060 ms for _rtrim_Value
690 ms for _convertNullValueToEmpty

array_walk seems to be VERY SLOW: for each element of the array, it calls a method...

:-)

[2005-04-20 12:20 UTC] smith at backendmedia dot com

Erm no .. what I meant is:

if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
array_walk($arr, array($this, 'rtrim'));
}

then again that probably chews up NULL's

oh well. hmm i really think there has to be a more elegant mechanism to handle this... passing an array stack of functions to apply probably also doesnt fix the performance. I will ponder this a bit.

[2005-04-20 12:32 UTC] fabien dot thierry at vie-medieval dot com

With the code:

***************************************
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
array_walk($arr, 'rtrim');
}

if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
***************************************

The execution time is 1050ms. It is better than the original code (1250ms), but worse than the previous patch (850ms)...

:-)

[2005-04-20 13:03 UTC] fabien dot thierry at vie-medieval dot com

Sorry!

You are right!

The best way is the last (with array_walk($arr, 'rtrim')) and without my patch!

In conclusion:

fetchInto execution time in one of my scripts:

1) With the original code: 1690ms
2) With my 'patch': 1250ms
3) With array_walk($arr, 'rtrim') (in replacement of 1 line in fetchInto method): 1050ms

Congratulation, Smith!

[2005-04-20 13:05 UTC] smith at backendmedia dot com

Please test what rtrim() does to NULL values. Its entirely possible that someone only has rtrim enabled and not convert NULL to empty.

[2005-04-20 13:44 UTC] fabien dot thierry at vie-medieval dot com

oups!

I have added a patch to count how many null values there is before and after the array_walk.

So, I have seen any null values!!!

:-((