Home » Database » DB » Bug #4185
Performances increased
Details
| Request #4185 | Performances increased |
|---|---|
| Submitted | 2005-04-20 09:33 UTC |
| From | fabien dot thierry at vie-medieval dot com |
| Status | Wont fix |
| Package | DB |
| PHP Version | 5.0.3 |
| OS | Linux |
| 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!!!
:-((