Search code examples
phpvariablesfor-loopcreation

Extra variable or object creation -- what is better in PHP?


What is better / faster / more efficient in PHP?

Using extra variable:

$dateStep = new DateInterval('P1D');

for($di = 0; $di <= $dateInterval; ++$di)
{
    $theDate = ($di > 0) ? $startDate->add($dateStep) : $startDate;

    ...
}

Or creating object each time it is required:

for($di = 0; $di <= $dateInterval; ++$di)
{
    $theDate = ($di > 0) ? $startDate->add(new DateInterval('P1D')) : $startDate;

    ...
}

I'd vote for first option, but my knowledge in optimization and performance in PHP is quite limited.

EDIT: It seems, that I didn't expressed that enough, but I'm asking specifically for a scenario like this -- when creation of object returns static value, that is used over and over again inside following loop.


Solution

  • To look at this also from another angle, let's take a look at both scripts and the opcode:

    script1:

    <?php
    
    $dateStep = new DateInterval('P1D');
    $dateInterval = 5;
    $startDate = new DateTime();
    
    for($di = 0; $di <= $dateInterval; ++$di)
    {
        $theDate = ($di > 0) ? $startDate->add($dateStep) : $startDate;
    
        //...
    }
    

    opcode:

    number of ops:  26
    compiled vars:  !0 = $dateStep, !1 = $dateInterval, !2 = $startDate, !3 = $di, !4 = $theDate
    line     # *  op                           fetch          ext  return  operands
    ---------------------------------------------------------------------------------
       3     0  >   FETCH_CLASS                                   4  :0      'DateInterval'
             1      NEW                                              $1      :0
             2      SEND_VAL                                                 'P1D'
             3      DO_FCALL_BY_NAME                              1          
             4      ASSIGN                                                   !0, $1
       4     5      ASSIGN                                                   !1, 5
       5     6      FETCH_CLASS                                   4  :5      'DateTime'
             7      NEW                                              $6      :5
             8      DO_FCALL_BY_NAME                              0          
             9      ASSIGN                                                   !2, $6
       7    10      ASSIGN                                                   !3, 0
            11  >   IS_SMALLER_OR_EQUAL                              ~10     !3, !1
            12    > JMPZNZ                                        F          ~10, ->25
            13  >   PRE_INC                                                  !3
            14    > JMP                                                      ->11
       9    15  >   IS_SMALLER                                       ~12     0, !3
            16    > JMPZ                                                     ~12, ->22
            17  >   INIT_METHOD_CALL                                         !2, 'add'
            18      SEND_VAR                                                 !0
            19      DO_FCALL_BY_NAME                              1  $14     
            20      QM_ASSIGN_VAR                                    $15     $14
            21    > JMP                                                      ->23
            22  >   QM_ASSIGN_VAR                                    $15     !2
            23  >   ASSIGN                                                   !4, $15
      12    24    > JMP                                                      ->13
            25  > > RETURN                                                   1
    

    script2:

    <?php
    
    
    $dateInterval = 5;
    $startDate = new DateTime();
    
    for($di = 0; $di <= $dateInterval; ++$di)
    {
        $theDate = ($di > 0) ? $startDate->add(new DateInterval('P1D')) : $startDate;
    
       // ...
    }
    

    opcode:

    number of ops:  25
    compiled vars:  !0 = $dateInterval, !1 = $startDate, !2 = $di, !3 = $theDate
    line     # *  op                           fetch          ext  return  operands
    ---------------------------------------------------------------------------------
       4     0  >   ASSIGN                                                   !0, 5
       5     1      FETCH_CLASS                                   4  :1      'DateTime'
             2      NEW                                              $2      :1
             3      DO_FCALL_BY_NAME                              0          
             4      ASSIGN                                                   !1, $2
       7     5      ASSIGN                                                   !2, 0
             6  >   IS_SMALLER_OR_EQUAL                              ~6      !2, !0
             7    > JMPZNZ                                        A          ~6, ->24
             8  >   PRE_INC                                                  !2
             9    > JMP                                                      ->6
       9    10  >   IS_SMALLER                                       ~8      0, !2
            11    > JMPZ                                                     ~8, ->21
            12  >   INIT_METHOD_CALL                                         !1, 'add'
            13      FETCH_CLASS                                   4  :10     'DateInterval'
            14      NEW                                              $11     :10
            15      SEND_VAL                                                 'P1D'
            16      DO_FCALL_BY_NAME                              1          
            17      SEND_VAR_NO_REF                               0          $11
            18      DO_FCALL_BY_NAME                              1  $13     
            19      QM_ASSIGN_VAR                                    $14     $13
            20    > JMP                                                      ->22
            21  >   QM_ASSIGN_VAR                                    $14     !1
            22  >   ASSIGN                                                   !3, $14
      12    23    > JMP                                                      ->8
            24  > > RETURN                                                   1
    

    Now as you can see in the opcode of the second script it's creating a new instance of the class every iteration and you creating a huge overhead which seems you don't need (Look at # * 13 - 16 in the second opcode), so first you are creating new instances which are completely unnecessary and second this will slow your performance down.

    So as long as you don't need a completely new class every iteration the first script is better for you as it only creates the DateInterval object only once and assign it to the variable.


    Also a little bit of extra info: