Project

General

Profile

Actions

Feature #88754

closed

Codesmell GeneralUtility::trimExplode()

Added by Dieter Porth almost 5 years ago. Updated almost 5 years ago.

Status:
Closed
Priority:
Should have
Assignee:
-
Category:
Performance
Target version:
-
Start date:
2019-07-15
Due date:
% Done:

0%

Estimated time:
PHP Version:
Tags:
Complexity:
Sprint Focus:

Description

Optimize Coding of GeneralUtility:trimExplode. The Foreach-loop and the slice-Operation seems not good in the current method.

I guess, the following-code is faster.


public static function trimExplode($delim, $string, $removeEmptyValues = false, $limit = 0) {
    if ($limit>0)  {
        $result = array_map('trim',
            explode($delim, $string,$limit));
    } else  {
        $result = array_map('trim',
            explode($delim, $string));
    }  
    if ($removeEmptyValues === true) {
        $result = array_filter($result, function($k){
             return  $k !== ''
        });
    }
    return $result;
 }

The code-example and the performance is not tested yet.

Perhaps: If the $removeEmptyValues ist related to the php-Function empty(), then the filter-function is obsolete.
$result = array_filter($result)

Actions #1

Updated by Benni Mack almost 5 years ago

  • Status changed from New to Needs Feedback

It would be very interesting to see if it is actually faster.

using tools like "phpbench" would help us here. Care to give it a try to see before/after information?

Actions #2

Updated by Frank Nägler almost 5 years ago

The following bench results are from a quick phpbench check.

Old means the existing method
new means the method of this issue

All runs started with a string containing 1000 entries, also duplicates.
Thew runs 3+4 (...RemoveEmpty) are using the third parameter "removeEmptyValues".

The fourth parameter limit and more combinations of arguments were not tested yet.

\TrimExplodeBench

    benchOld                      I0 P0         [μ Mo]/r: 613.259 613.259 (μs)  [μSD μRSD]/r: 0.000μs 0.00%
    benchNew                      I0 P0         [μ Mo]/r: 570.521 570.521 (μs)  [μSD μRSD]/r: 0.000μs 0.00%
    benchOldRemoveEmpty           I0 P0         [μ Mo]/r: 1,330.770 1,330.770 (μs)      [μSD μRSD]/r: 0.000μs 0.00%
    benchNewRemoveEmpty           I0 P0         [μ Mo]/r: 2,591.502 2,591.502 (μs)      [μSD μRSD]/r: 0.000μs 0.00%

4 subjects, 4 iterations, 4,000 revs, 0 rejects, 0 failures, 0 warnings
(best [mean mode] worst) = 570.521 [1,276.513 1,276.513] 570.521 (μs)
⅀T: 5,106.052μs μSD/r 0.000μs μRSD/r: 0.000%
Actions #3

Updated by Oliver Hader almost 5 years ago

  • Category set to Performance
Actions #4

Updated by Frank Nägler almost 5 years ago

The bench class

<?php

include 'typo3/sysext/core/Classes/Utility/GeneralUtility.php';

class TrimExplodeBench
{
    static $string = '1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,';

    /**
     * @Revs({1000})
     */
    public function benchOld()
    {
        \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', self::$string, false);
    }

    /**
     * @Revs({1000})
     */
    public function benchNew()
    {
        \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplodeNew(',', self::$string, false);
    }

    /**
     * @Revs({1000})
     */
    public function benchOldRemoveEmpty()
    {
        \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', self::$string, true);
    }

    /**
     * @Revs({1000})
     */
    public function benchNewRemoveEmpty()
    {
        \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplodeNew(',', self::$string, true);
    }
}

Actions #5

Updated by Oliver Hader almost 5 years ago

Thx, I've adjusted implementation a litte bit and added 5 iterations, keeping 1000 revolutions.
Test have been executed in CLI mode, having opCache enabled. Tests are organized in groups to determine proper difference and std deviation.

String, 1000 numerics, no spaces or empty items (like shown before)

static $string = '1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,1,2,3,4,5,6,7,8,9,10,';
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+
| benchmark        | subject                     | set | revs | its | mem_peak | best      | mean      | mode      | worst     | stdev    | rstdev | diff  |
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old       | 0   | 1000 | 5   | 513,456b | 501.934μs | 516.467μs | 513.863μs | 533.355μs | 11.068μs | 2.14%  | 1.00x |
| TrimExplodeBench | bench_trimExplode_candidate | 0   | 1000 | 5   | 513,464b | 511.662μs | 535.493μs | 527.610μs | 572.027μs | 20.160μs | 3.76%  | 1.04x |
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+

New candidate seems to be a litte bit slower, but still "almost equal".

+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+
| benchmark        | subject                                       | set | revs | its | mem_peak | best        | mean        | mode        | worst       | stdev    | rstdev | diff  |
+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old_removeEmptyValues       | 0   | 1000 | 5   | 513,472b | 1,158.088μs | 1,186.733μs | 1,174.369μs | 1,225.729μs | 24.106μs | 2.03%  | 1.00x |
| TrimExplodeBench | bench_trimExplode_candidate_removeEmptyValues | 0   | 1000 | 5   | 513,808b | 1,583.447μs | 1,630.353μs | 1,607.766μs | 1,717.071μs | 47.140μs | 2.89%  | 1.37x |
+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+

New candidate seems to be slower.

String, 1000 alpha-numerics, all wrapped by spaces, random number of empty items

static $string = '  , 9 , 7 , m , 61 , 46 , 75 , i , 58 , 93 , 41 , 55 , 68 , 26 , 72 , 9 , 2 , 0 , 32 , g , s ,  , 75 , 4 ,  , i , 78 , p , r , a , v , x , 27 , 60 , 54 , 91 , 91 , 78 , 71 , 62 , o , 17 , 56 , 72 , 91 , 78 , d , 13 , c , 52 , 27 , 22 , 12 , 60 , 100 , 15 , 38 , 11 , 81 , 28 , 82 , 18 , 22 , 74 , s , 73 , 17 , 74 , 70 , 22 , 22 , 85 , 21 , 37 , 20 , 9 , 46 ,  ,  , 3 , 32 ,  , 3 , d , 78 , 63 , 22 ,  , 82 , 91 , 97 , 69 , 46 , 74 , u , 20 , 66 , 13 , b , 30 , h , 59 , 21 , 0 , v , 82 ,  , 92 , 80 , 68 , r , 72 , 40 , x , n , 1 , 49 , 56 , 82 , 12 , 42 , 28 , t , 87 , 61 , 37 , 75 , 38 , c , 77 , 88 , h , 95 ,  , 34 , 82 , m ,  , u , 87 , 16 , 64 , 87 , 51 , w , 1 ,  , 50 , 35 , 21 , 93 , 13 , 14 , 66 , 45 , z , k , 6 , z , 39 , 54 , 7 , d , 71 , 12 , e , 77 , 70 , 71 , i , 69 , g , 97 , 48 , 47 , 0 , e ,  ,  , 44 , 40 , 54 , 76 , 52 , 78 , 85 ,  , 90 , 57 , 96 , 99 , 44 , 79 , 60 , x , 22 , 59 , o , k , 4 , h , h , 8 , 50 , u ,  , c , 56 , 94 , v , 75 , 93 , 58 , r , 62 , 14 , 48 , 35 ,  , z , 45 , 13 , 40 , x , 57 , 0 , 73 , 22 , 34 , 41 , 73 , 35 , 20 , 23 , l , r , k , 86 , 17 ,  ,  , b , 77 , 11 , 90 , 2 , 12 , 35 , 36 , 40 , 87 ,  , u , 52 , 57 , 3 ,  , 48 , 47 , 12 , 50 , g , 95 , 13 ,  , n , 15 , 41 , 32 , 88 , 84 , 49 , 2 , 77 , 59 ,  ,  , 12 , c , 6 , 4 , c , 45 , 62 ,  , 41 , 82 , 3 , 97 ,  , f , 5 , 64 ,  , 60 , 35 , 59 , 57 ,  , 66 , 52 , 56 , 39 , z , r , 37 , 52 , 77 , 96 , 71 , 99 , 9 , 29 , 21 , 53 , s , 7 , 97 , 8 , 82 , 81 , q , 88 , 12 , 55 , 53 , c , v , 99 , 22 , 35 , 50 , 92 , 21 , 16 , a , 78 , k , v , 74 , 14 , 45 , 93 , 82 , l , 9 , w , 44 , 27 ,  , 4 , 96 , v , 15 ,  , 30 , 99 , 58 , 61 , x , 91 , q , 97 , u , z , 18 , 65 , 88 , 55 , 59 , 19 , 7 , h , 87 , 9 , 86 ,  ,  , u , 16 , 13 , 93 , 37 , h ,  ,  , 2 , 66 , n , 89 , 17 , 50 , b , 32 , 9 , p , 13 , 15 , x , 89 , 64 , 73 , 77 , y , 42 ,  , 65 , p , e , t , 15 , 62 , 66 , 91 , 24 , 54 , 4 , p , 28 , 80 , m , 45 ,  , 27 , 72 , 77 , 39 , 77 ,  , 33 , 63 , 60 , 17 , 53 , 20 , 72 , 59 , r , w , 99 , c ,  , 14 , 79 , 85 , s , 59 , 21 , 58 , 23 , 67 ,  , 70 , d , 22 , 66 , f , 4 , 19 , 86 , 9 , 12 , 63 , 77 , 58 , 2 , h , 21 , 22 , 70 , 70 , 100 , t , m , 67 , j , 77 , f , 59 , 44 , j , 10 , h , 97 ,  , 14 , 89 ,  , 53 , 79 , 26 , 28 , m , q , 64 , n , 82 , 41 , 100 , 100 , 30 , k , s , 7 , 76 ,  ,  , 97 , 93 , 85 , 1 , 33 ,  , 64 , 46 , 5 , 35 , 66 , 88 , 32 , 6 , 9 ,  , 100 , 43 , 33 , 17 , n , 36 , l , 7 , 30 , 56 , 10 , 66 , 3 , 41 , 90 , 6 , w , 59 , 5 , 33 , 81 , n , 96 , 51 , m , k , 21 , 79 , 95 , 36 , 22 , 58 , 82 , p , 2 , 25 , s , 56 , 52 , 98 , 45 , 75 , 7 , 60 , 21 , 45 , 84 , 88 , 23 , 90 , 71 , 94 , 60 , 7 , 44 , 93 , 42 , 2 , 51 , 57 , 61 ,  , x ,  , z , 57 , 13 , 98 , g , 64 , 28 , 15 , 28 , 69 , d , 15 , 22 , 100 , 12 ,  , 69 , 89 , 28 , 20 , 22 , 69 , o , t , d , 37 , 44 , 94 , x , 98 ,  , x , 27 , 47 , x , 57 , 32 ,  , 26 , 26 , 41 , 34 , 100 , 93 , 76 , 67 , 30 , 9 , 40 , 55 , d , 8 , 71 , 99 , 61 , 5 , r , x , 69 ,  , 38 , 78 ,  , 24 , 86 , 44 , 80 , 93 , 5 , 11 , 28 , 25 , 1 , 86 , u ,  , 44 , 6 ,  , x , 100 , 89 , 68 , 99 , x , 72 , 18 , 61 ,  , 45 , 81 , 49 , m , 58 , 70 , 61 ,  , 0 , 83 , 74 , 28 , 5 , 87 , 42 , m , 21 , 37 , 38 , w , 92 , 8 ,  , 38 , 71 , 4 , 86 , g , o , 91 , 72 , 66 , 48 , n , 45 , 62 , 31 , 82 , 100 , 99 , 93 , 94 , 54 , m , 33 , w , 72 , 18 , 77 , 15 , q , 14 , b , 22 , 98 , j ,  , 2 , 2 , 51 , 86 , 46 , 18 ,  , 25 , 35 , 52 , 1 ,  ,  , 76 , 81 , 94 ,  , 65 , 35 , 42 ,  , 10 , 4 , a ,  , x ,  , a , z , 85 , i , 62 , 15 , 38 , m , r , 40 , 13 , j , 12 , 36 , 47 , 65 , 76 , c , 12 , 4 , 82 , 46 , q , 77 , 16 , 7 , 13 , 5 , 88 , 100 , 99 , 77 , q , q , 95 , 11 , 7 , 49 , d , 83 , 53 , 61 , i , 46 , 96 , 39 , 44 ,  , 31 , 52 , 0 ,  , h , 60 , 29 , c , 68 , k , 33 , 68 , 100 , 71 , 67 , 28 , 60 , 41 , 44 , 96 , 57 , a , g , k , 99 ,  , 32 , 92 , 42 , 90 , 7 , 52 ,  , 69 , 1 , 91 ,  ,  ,  , 67 ,  , 49 , 15 , 36 , 24 , 83 , x , q , q , 4 , 10 , s , 74 , 45 , t , 94 , 35 , 20 , 47 , 9 , m , 58 , v , z , 66 , 37 , 55 , e , 98 ,  , 77 , 88 ,  , 85 , 96 , 87 , s ,  , 21 , n , 71 , 47 , 51 , 69 , 89 , 79 , q , 16 , 47 , 88 , 22 ,  ,  , 90 , 58 , 54 , 40 , 99 , 2 , z , e , v , 73 , 88 , 72 , 12 , 23 , v , 13 , h , 30 , 39 , g , 34 , h , 33 ,  , 47 , t , 83 , 78 , k , x , 48 , b , 84 , k ,  , o , 80 , 44 , 11 , b , 20 , 65 , n , u , 58 , j , w , 8 , 18 , 66 , 72 , 78 , 2 , 15 , 79 , i , 7 , k , 71 , 61 , 92 , 57 , 76 , e , 95 , 57 , 58 , l , 90 , 98 , 9 , 73 , 90 , 1 , 38 , 75 , 65 , 30 , 74 , 22 , 22 , 33 , 1 , 2 , g , 50 , o , p , 67 , s , 18 , 73 , z , 0 , h , 43 , 92 , 88 , j';
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+
| benchmark        | subject                     | set | revs | its | mem_peak | best      | mean      | mode      | worst     | stdev    | rstdev | diff  |
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old       | 0   | 1000 | 5   | 577,328b | 538.255μs | 566.207μs | 550.838μs | 618.631μs | 29.232μs | 5.16%  | 1.03x |
| TrimExplodeBench | bench_trimExplode_candidate | 0   | 1000 | 5   | 577,336b | 538.232μs | 547.454μs | 550.331μs | 551.910μs | 5.178μs  | 0.95%  | 1.00x |
+------------------+-----------------------------+-----+------+-----+----------+-----------+-----------+-----------+-----------+----------+--------+-------+

New candidate seems to be a litte bit faster, but still "almost equal".

+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+
| benchmark        | subject                                       | set | revs | its | mem_peak | best        | mean        | mode        | worst       | stdev    | rstdev | diff  |
+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old_removeEmptyValues       | 0   | 1000 | 5   | 574,816b | 1,158.764μs | 1,181.165μs | 1,169.680μs | 1,218.746μs | 21.701μs | 1.84%  | 1.00x |
| TrimExplodeBench | bench_trimExplode_candidate_removeEmptyValues | 0   | 1000 | 5   | 577,360b | 1,607.001μs | 1,679.464μs | 1,660.833μs | 1,783.334μs | 57.386μs | 3.42%  | 1.42x |
+------------------+-----------------------------------------------+-----+------+-----+----------+-------------+-------------+-------------+-------------+----------+--------+-------+

New candidate seems to be slower.

String, shortened, like used in configuration or database CSV references

static $string = 'be_users_14,,,tx_whatever_19,28,4321,,pages_1';
+------------------+-----------------------------+-----+------+-----+----------+---------+---------+---------+---------+---------+--------+-------+
| benchmark        | subject                     | set | revs | its | mem_peak | best    | mean    | mode    | worst   | stdev   | rstdev | diff  |
+------------------+-----------------------------+-----+------+-----+----------+---------+---------+---------+---------+---------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old       | 0   | 1000 | 5   | 475,688b | 8.241μs | 8.431μs | 8.310μs | 8.644μs | 0.170μs | 2.02%  | 1.12x |
| TrimExplodeBench | bench_trimExplode_candidate | 0   | 1000 | 5   | 475,696b | 7.319μs | 7.511μs | 7.401μs | 7.753μs | 0.173μs | 2.31%  | 1.00x |
+------------------+-----------------------------+-----+------+-----+----------+---------+---------+---------+---------+---------+--------+-------+

New candidate seems to be a litte bit faster.

+------------------+-----------------------------------------------+-----+------+-----+----------+----------+----------+----------+----------+---------+--------+-------+
| benchmark        | subject                                       | set | revs | its | mem_peak | best     | mean     | mode     | worst    | stdev   | rstdev | diff  |
+------------------+-----------------------------------------------+-----+------+-----+----------+----------+----------+----------+----------+---------+--------+-------+
| TrimExplodeBench | bench_trimExplode_old_removeEmptyValues       | 0   | 1000 | 5   | 475,704b | 12.096μs | 13.335μs | 13.246μs | 14.708μs | 0.837μs | 6.28%  | 1.00x |
| TrimExplodeBench | bench_trimExplode_candidate_removeEmptyValues | 0   | 1000 | 5   | 475,720b | 19.652μs | 20.403μs | 20.147μs | 21.500μs | 0.626μs | 3.07%  | 1.53x |
+------------------+-----------------------------------------------+-----+------+-----+----------+----------+----------+----------+----------+---------+--------+-------+

New candidate seems to be slower.

Summary

TYPO3 is making use of 3rd parameter $removeEmptyValues (enabled) which means that new candidate actually might slow down things.
Anyway, additional measurements and reports are welcome here.

Actions #6

Updated by Dieter Porth almost 5 years ago

Summary

The method trimExplodeNewSix or variations of it seems not to be faster than the old trimExplode. You get in some cases different results.
I wouldn't change the method, because it is used in 555 places.

Suggestion

The description of trimExplode should be changed and $limit should be renamed to $reformCount, because it has not a ordinary limit-function (see tests).

 * Explodes a string fully into an array-stack and trims all values for whitespace. 
 * If $onlyNonEmptyValues is set, then all blank ('') values are removed. 
 * If $reformCount is greater 0, it will implode all overflow array-element into the last array-element .
 * If $reformCount is lower 0, it will remove the last $reformCount of of the array-stack

I know, my english is horribly germanized.

remark

I should have done unittests before publishing.
',g,g, g, g,' will cause different results in trimExplode and trimExplodeNew for limit=5 and remove=true, because trimExplodeNewFour generates ["g","g","g","g,"] and trimExplode generates ["g","g","g","g"] (last comma is missing).
',g,g, g, g,' will cause different indexing in trimExplode and trimExplodeNew for limit=0 and remove=true.

',g,g, g, g,' will cause different results in trimExplode and trimExplodeNewFour for limit=5 and remove=true, because trimExplodeNewFour generates ["g","g","g","g,"].
',g,g, g, g,' will cause different results in trimExplode and trimExplodeNewSix for limit=5 and remove=true, because trimExplodeNewFour generates ["g","g","g","g,"].


    public static function trimExplodeNewFour($delim, $string, $removeEmptyValues = false, $limit = 0)
    {
        if ($limit > 0) {
            $result = array_map('trim',
                explode($delim, $string, $limit)
            );
        } else {
            $result = array_map('trim',
                explode($delim, $string)
            );
        }

        if ($removeEmptyValues === true) {
            $temp = [];
            foreach ($result as $value) {
                if (trim($value) !== '') {
                    $temp[] = $value;
                }
            }
            $result = $temp;
        }
        return $result;
    }

    public static function trimExplodeNewSix($delim, $string, $removeEmptyValues = false, $limit = 0)
    {
        if ($limit > 0) {
            $result = [];
            $check = explode($delim, $string, $limit);
            foreach ($check as $value) {
                $result[] = trim($value);
            }
        } else {
            $check = explode($delim, $string);
            $result = [];
            foreach ($check as $value) {
                $result[] = trim($value);
            }
        }

        if ($removeEmptyValues === true) {
            $temp = [];
            foreach ($result as $value) {
                if (trim($value) !== '') {
                    $temp[] = $value;
                }
            }
            $result = $temp;
        }
        return $result;
    }

Use the following-Test to check identical results


namespace Porth\Checker\Benchmark;

use PHPUnit\Framework\TestCase;

class TrimExplodeTest extends TestCase
{
// Tests conatins no negative limits.
    public function dataProvidertrimExplodeByVariation()
    {
        $result = [];
        $item = [];
        $item['expects'] = 'test to value of referenz-function';
        foreach (['remove empty' => true, 'allow empty' => false] as $removeMessage => $removeEmpty) {
            $item['params']['removeEmptyValues'] = $removeEmpty;
            foreach (['limit all' => 0, 'limit five' => 5, 'limit hundred' => 100] as $limitMessage => $limit) {
                $item['params']['limit'] = $limit;
                    foreach ([-3, 0, 1, 2, 3, 7, 13, 100] as $addLimit) {
                        $parts = $addLimit + $limit;
                        if ($parts >= 0) {
                            foreach (['emptyTwo' => ',', 'emptyInlet' => ',g,,g,', 'nothingempty' => '',] as $addTest) {
                                $item['params']['testString'] = $addTest;

                                $baseMessage = $removeMessage . ' with ' . $limitMessage . ' and ' . $parts . ' parts ';

                                $item['params']['testString'] .= rtrim(str_repeat('g,', $parts), ',') .$addTest;
                                $item['message'] = $baseMessage . ' and add NO space';
                                $result[] = $item;

                                $item['params']['testString'] .= rtrim(str_repeat(' g,', $parts), ',') .$addTest;
                                $item['message'] = $baseMessage . ' and add right to parameter the space';
                                $result[] = $item;

                                $item['params']['testString'] .= rtrim(str_repeat('g ,', $parts), ',') .$addTest;
                                $item['message'] = $baseMessage . ' and add left to parameter the space';
                                $result[] = $item;

                                $item['params']['testString'] .= rtrim(str_repeat(' g ,', $parts), ',') .$addTest;
                                $item['message'] = $baseMessage . ' and add on both sides of parameter the space';
                                $result[] = $item;
                            }
                        }

                    }

            }
        }

        return $result;
    }

    /**
     *
     * @dataProvider dataProvidertrimExplodeByVariation
     * @test
     */
    public function trimExplodeByVariation($expects, $params, $message)
    {
        if (!isset($expects) && empty($expects)) {
            $this->assertSame(true, false, 'empty-data at the end of the provider or emopty dataprovider');
        } else {
            $delim = ',';

            $six = \Porth\Checker\Benchmark\TrimExplode::trimExplodeNewSix($delim,
                $params['testString'],
                $params['removeEmptyValues'],
                $params['limit']
            );
            $four = \Porth\Checker\Benchmark\TrimExplode::trimExplodeNewFour($delim,
                $params['testString'],
                $params['removeEmptyValues'],
                $params['limit']
            );
            $new = \Porth\Checker\Benchmark\TrimExplode::trimExplodeNew($delim,
                $params['testString'],
                $params['removeEmptyValues'],
                $params['limit']
            );
            $old = \Porth\Checker\Benchmark\TrimExplode::trimExplode($delim,
                $params['testString'],
                $params['removeEmptyValues'],
                $params['limit']
            );

            $this->assertSame(
                json_encode($old),
                json_encode($new),
                ('Org->new: ' . $message . "\n".$params['testString']."\n".$params['limit']." - ".$params['removeEmptyValues']."\n" . json_encode($old) . "\n" . json_encode($new))
            );
            $this->assertSame(
                json_encode($old),
                json_encode($four),
                ('Org->four: ' . $message . "\n".$params['testString']."\n".$params['limit']." - ".$params['removeEmptyValues']. "\n" . json_encode($old) . "\n" . json_encode($four))
            );
            $this->assertSame(
                json_encode($old),
                json_encode($six),
                ('Org->six: ' . $message . "\n".$params['testString']."\n".$params['limit']." - ".$params['removeEmptyValues']. "\n" . json_encode($old) . "\n" . json_encode($four))
            );
        }
    }
}

post scriptuum

benchmarks-tests (obsolet)

It was interesting for me, that the for-loop in php is as fast as the internal functions. Perhaps it is interesting for someone else.
Test with XAMPP7.2 /Windows 10.
I have not tested it with php7.3.

Oliver Hader #5: String, 1000 alpha-numerics, all wrapped by spaces, random number of empty items


+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+
| benchmark        | subject                       | set | revs | iter | mem_peak | time_rev    | comp_z_value | comp_deviation |
+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+
| TrimExplodeBench | benchOld                      | 0   | 1000 | 0    | 550,784b | 1,605.462μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNew                      | 0   | 1000 | 0    | 550,784b | 1,588.716μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFour                  | 0   | 1000 | 0    | 550,784b | 1,571.796μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSix                   | 0   | 1000 | 0    | 550,784b | 2,179.349μs | 0.00σ        | 0.00%          |
+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+
| TrimExplodeBench | benchOldRemoveEmpty           | 0   | 1000 | 0    | 548,896b | 3,901.338μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewRemoveEmpty           | 0   | 1000 | 0    | 550,792b | 3,768.027μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFourRemoveEmpty       | 0   | 1000 | 0    | 550,792b | 3,886.772μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSixRemoveEmpty        | 0   | 1000 | 0    | 579,512b | 6,827.562μs | 0.00σ        | 0.00%          |
+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+
| TrimExplodeBench | benchOldRemoveEmptyLim100     | 0   | 1000 | 0    | 559,640b | 2,645.360μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewRemoveEmptyLim100     | 0   | 1000 | 0    | 493,432b | 403.837μs   | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFourRemoveEmptyLim100 | 0   | 1000 | 0    | 493,432b | 402.702μs   | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSixRemoveEmptyLim100  | 0   | 1000 | 0    | 493,432b | 453.241μs   | 0.00σ        | 0.00%          |
+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+
| TrimExplodeBench | benchOldRemoveEmptyLim5       | 0   | 1000 | 0    | 555,760b | 2,527.818μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewRemoveEmptyLim5       | 0   | 1000 | 0    | 493,424b | 36.379μs    | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFourRemoveEmptyLim5   | 0   | 1000 | 0    | 493,432b | 41.819μs    | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSixRemoveEmptyLim5    | 0   | 1000 | 0    | 493,432b | 32.987μs    | 0.00σ        | 0.00%          |
+------------------+-------------------------------+-----+------+------+----------+-------------+--------------+----------------+

Oliver Hader #5: String, shortened, like used in configuration or database CSV references


+------------------+-----------------------------+-----+------+------+----------+----------+--------------+----------------+
| benchmark        | subject                     | set | revs | iter | mem_peak | time_rev | comp_z_value | comp_deviation |
+------------------+-----------------------------+-----+------+------+----------+----------+--------------+----------------+
| TrimExplodeBench | benchOld                    | 0   | 1000 | 0    | 482,488b | 22.468μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNew                    | 0   | 1000 | 0    | 482,488b | 23.473μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFour                | 0   | 1000 | 0    | 482,488b | 22.244μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSix                 | 0   | 1000 | 0    | 482,488b | 30.038μs | 0.00σ        | 0.00%          |
+------------------+-----------------------------+-----+------+------+----------+----------+--------------+----------------+
| TrimExplodeBench | benchOldRemoveEmpty         | 0   | 1000 | 0    | 482,496b | 36.954μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewRemoveEmpty         | 0   | 1000 | 0    | 482,496b | 46.706μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFourRemoveEmpty     | 0   | 1000 | 0    | 482,496b | 41.657μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSixRemoveEmpty      | 0   | 1000 | 0    | 482,496b | 44.545μs | 0.00σ        | 0.00%          |
+------------------+-----------------------------+-----+------+------+----------+----------+--------------+----------------+
| TrimExplodeBench | benchOldRemoveEmptyLim5     | 0   | 1000 | 0    | 482,496b | 38.587μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewRemoveEmptyLim5     | 0   | 1000 | 0    | 482,496b | 31.861μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewFourRemoveEmptyLim5 | 0   | 1000 | 0    | 482,504b | 35.335μs | 0.00σ        | 0.00%          |
| TrimExplodeBench | benchNewSixRemoveEmptyLim5  | 0   | 1000 | 0    | 482,504b | 31.838μs | 0.00σ        | 0.00%          |
+------------------+-----------------------------+-----+------+------+----------+----------+--------------+----------------+

Actions #7

Updated by Dieter Porth almost 5 years ago

I remarked in #4 (my private typo3-account), that trimExplode
shows in some cases other results than trimExplodeNew, trimExplodeNewFour and trimExplodeNewSix *
See compare-test with phpunit in #4.

TYPO3 contains 555 places, where the function trimExplode is used.
I would close this ticket, because my suggested solution is not really better than the current version.

Actions #8

Updated by Susanne Moog almost 5 years ago

  • Status changed from Needs Feedback to Closed

Closed as requested by the author.

Actions

Also available in: Atom PDF