3

In PHP, assuming $value = 12345;(an integer), which is faster when casting $value from an integer to a string;

$value = (string)$value;

or

$value = "$value";

This is a kind of performance measure question and specifically for this case. Thanks for your help!

Nico Haase
  • 11,420
  • 35
  • 43
  • 69
Derick Alangi
  • 1,080
  • 1
  • 11
  • 31
  • 3
    well ... did you measure it ? i'm dying to know :) – YvesLeBorg Feb 12 '19 at 14:19
  • 1
    @YvesLeBorg , I measured it by type casting an integer 200 million times using both the methods. On average, Implicit type casting is few hundred milliseconds faster than explicit. – Adarsh Sojitra Feb 12 '19 at 14:25
  • @YvesLeBorg, not sure how I can, I'm still to but wanted to know if someone has come across such an issue. I'm looking for some recommended profiling tools for this kind of things. If you have any suggestion, please let me know :) – Derick Alangi Feb 12 '19 at 14:35
  • 1
    @xSavitar i gave you elements of an approach for this kind of (interesting and very tricky) questions you may have. – YvesLeBorg Feb 12 '19 at 16:13
  • @YvesLeBorg, thanks! I'll also like to work on this with the Zend interpreter and PHPNG interpreter (PHP 5 and PHP 7 respectively) to see the kind of difference I'll have. :) – Derick Alangi Feb 12 '19 at 17:10

2 Answers2

7

Your question is really about the efficacy of the php interpreter, and how it converts php code (the one you write) to php bytecode (the one that runs and may actually consume time and resources). If i take p01ymath's experiment, and decompose it:

implicit.php

<?php
$str = 12345;
for($i=0;$i<=200000000;$i++){
    $str2 = "$str";
}

implicit.php bytecode

DarkMax:temp yvesleborg$ php -dvld.active=1 -dvld.verbosity=0 -dvld.exececute=0 implicit.php 
filename:       /Users/yvesleborg/temp/implicit.php
function name:  (null)
number of ops:  14
compiled vars:  !0 = $str, !1 = $i, !2 = $str2
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
 2     0    E >   EXT_STMT                                                 
       1          ASSIGN                                                   !0, 12345
 3     2          EXT_STMT                                                 
       3          ASSIGN                                                   !1, 0
       4        > JMP                                                      ->10
 4     5      >   EXT_STMT                                                 
       6          CAST                                          6  ~5      !0
       7          ASSIGN                                                   !2, ~5
 3     8          POST_INC                                         ~7      !1
       9          FREE                                                     ~7
      10      >   IS_SMALLER_OR_EQUAL                              ~8      !1, 200000000
      11          EXT_STMT                                                 
      12        > JMPNZ                                                    ~8, ->5
 7    13      > > RETURN                                                   1

branch: #  0; line:     2-    3; sop:     0; eop:     4; out0:  10
branch: #  5; line:     4-    3; sop:     5; eop:     9; out0:  10
branch: # 10; line:     3-    3; sop:    10; eop:    12; out0:  13; out1:   5; out2:  13; out3:   5
branch: # 13; line:     7-    7; sop:    13; eop:    13; out0:  -2
path #1: 0, 10, 13, 
path #2: 0, 10, 5, 10, 13, 
path #3: 0, 10, 5, 10, 13, 
path #4: 0, 10, 13, 
path #5: 0, 10, 5, 10, 13, 
path #6: 0, 10, 5, 10, 13,

explicit.php

<?php
$str = 12345;
for($i=0;$i<=200000000;$i++){
    $str2 = (string)$str;
}

explicit.php bytecode

DarkMax:temp yvesleborg$ php -dvld.active=1 -dvld.verbosity=0 -dvld.exececute=0 explicit.php 
filename:       /Users/yvesleborg/temp/explicit.php
function name:  (null)
number of ops:  14
compiled vars:  !0 = $str, !1 = $i, !2 = $str2
line     #* E I O op                           fetch          ext  return  operands
-------------------------------------------------------------------------------------
   2     0  E >   EXT_STMT                                                 
         1        ASSIGN                                                   !0, 12345
   3     2        EXT_STMT                                                 
         3        ASSIGN                                                   !1, 0
         4      > JMP                                                      ->10
   4     5    >   EXT_STMT                                                 
         6        CAST                                          6  ~5      !0
         7        ASSIGN                                                   !2, ~5
   3     8        POST_INC                                         ~7      !1
         9        FREE                                                     ~7
        10    >   IS_SMALLER_OR_EQUAL                              ~8      !1, 200000000
        11        EXT_STMT                                                 
        12      > JMPNZ                                                    ~8, ->5
   7    13    > > RETURN                                                   1

branch: #  0; line:     2-    3; sop:     0; eop:     4; out0:  10
branch: #  5; line:     4-    3; sop:     5; eop:     9; out0:  10
branch: # 10; line:     3-    3; sop:    10; eop:    12; out0:  13; out1:   5; out2:  13; out3:   5
branch: # 13; line:     7-    7; sop:    13; eop:    13; out0:  -2
path #1: 0, 10, 13, 
path #2: 0, 10, 5, 10, 13, 
path #3: 0, 10, 5, 10, 13, 
path #4: 0, 10, 13, 
path #5: 0, 10, 5, 10, 13, 
path #6: 0, 10, 5, 10, 13,

as you can see, both snippets produce exactly the same bytecode (which you would expect from any well-crafted compiler/interpreter). Thus, the experiment above merely measures the actual run-time performance of the engine as it is sequencing the bytecode, at the time it was run, and on the box (chipset) it was run on.

To really answer your own question, you have to ponder the trickier question:

Under which circumstances does an explicit cast produce different bytecode from an implicit cast.

and if you find such circumstances, instrument a test to measure their respective performance.

If you want to pursue this quest, you will need the pecl vld component. You can follow this interesting post to get familiar with vld (be sure to check on pecl, and install the appropriate version for your php compiler under test)

YvesLeBorg
  • 9,070
  • 8
  • 35
  • 48
  • 1
    Thanks a lot for your response. Very resourceful and for the link to the post too, I'll read it. :) I'm willing to explore the quest more and more over time and feedback from SO is very much welcome to broaden ideas for whosoever finds this quest useful too. – Derick Alangi Feb 12 '19 at 17:03
2

Interesting question. I am totally dumb about testing these kind of things but I do it anyways. After seeing your question, I got an idea to check which one is faster.

So the idea is simple, I will just create a script to type cast an integer using both implicit and explicit methods 200 million times to see if there is a difference.

What I found out is, There is no much difference in speed. Here is the script I made to perform the tests.

<?php
$str = 12345;

$startTimeExplicit = microtime(true);
for($i=0;$i<=200000000;$i++){
    $str2 = (string)$str;
}
$endTimeExplicit = microtime(true);
$explicit = round($endTimeExplicit-$startTimeExplicit,6);

$startTimeImplicit = microtime(true);
for($i=0;$i<=200000000;$i++){
    $str2 = "$str";
}
$endTimeImplicit = microtime(true);
$implicit = round($endTimeImplicit-$startTimeImplicit,6);

echo "Average time (Implicit type casting): ".$implicit."<br>";
echo "Average time (Explicit type casting): ".$explicit."<br>";

?>

And here are the results I got after executing this script multiple times.

Average time (Implicit type casting): 14.815689
Average time (Explicit type casting): 14.614734

Average time (Implicit type casting): 14.56812
Average time (Explicit type casting): 15.190028

Average time (Implicit type casting): 14.649186
Average time (Explicit type casting): 15.587608

Average time (Implicit type casting): 15.522457
Average time (Explicit type casting): 15.566786

Average time (Implicit type casting): 15.235483
Average time (Explicit type casting): 15.333145

Average time (Implicit type casting): 15.972657
Average time (Explicit type casting): 16.161957

As you can see, both of them are equally fast. Sometimes Implicit type casting is few hundred milliseconds fast and sometimes Explicit. But on Average, You can't see much difference.

Adarsh Sojitra
  • 2,059
  • 1
  • 27
  • 50
  • Thanks for this! I'll wrap my head around this a bit using a profiling tool if possible not a plain PHP script but thanks a lot! – Derick Alangi Feb 12 '19 at 14:36
  • 2
    Actually, what you have measured is the outcome of this experiment, nothing else, which may (or may not be related to OP's quest). What if ... say ... the actual time to cast is background noise compared to the loop. You would not be able to affirm **`There is no much difference in speed`**. Not until you have looked at the bytecode of both methods (and possibly the code implementing the instructions) could you devise a meaningful experiment. .02 – YvesLeBorg Feb 12 '19 at 14:46
  • 1
    @YvesLeBorg Yes, I understand that there is no noise in this program that can make a difference and it would be there in an actual program. But I tested based on the inputs given in the question. – Adarsh Sojitra Feb 12 '19 at 14:48