3v4l.org

run code in 300+ PHP versions simultaneously
<?php header("content-type: text/plain"); error_reporting(E_ALL); $var='derp global $var...'; function hhb_var_dump() { //<changelog> //version 5 ( 1370984700423 ) //v5, fixed warnings on PHP < 5.0.2 (PHP_EOL not defined) (although we do not undefine("PHP_EOL") .. not sure how to do that :( ), //also we can use xdebug_var_dump when available now. tested working with 5.0.0 to 5.5.0beta2 (thanks to http://viper-7.com and http://3v4l.org ) //and fixed a (corner-case) bug with "0" (empty() considders string("0") to be empty, this caused a bug in sourcecode analyze) //v4, now (tries to) tell you the source code that lead to the variables //v3, HHB_VAR_DUMP_START and HHB_VAR_DUMP_END . //v2, now compat with.. PHP5.0 + i think? tested down to 5.2.17 (previously only 5.4.0+ worked) //</changelog> //<settings> $settings=array(); if(!defined('PHP_EOL')){//for PHP <5.0.2 $we_defined_PHP_EOL=true; define('PHP_EOL',"\n"); } $settings['debug_hhb_var_dump'] = false; //if true, may throw exceptions on errors.. $settings['use_xdebug_var_dump']=true;//try to use xdebug_var_dump (instead of var_dump) if available? $settings['analyze_sourcecode'] = true; //false to disable the source code analyze stuff. //(it will fallback to making $settings['analyze_sourcecode']=false, if it fail to analyze the code, anyway..) $settings['hhb_var_dump_prepend'] = 'HHB_VAR_DUMP_START'.PHP_EOL; $settings['hhb_var_dump_append'] = 'HHB_VAR_DUMP_END'.PHP_EOL; //</settings> $settings['use_xdebug_var_dump']=($settings['use_xdebug_var_dump'] && is_callable("xdebug_var_dump")); $argv = func_get_args(); $argc = count($argv, COUNT_NORMAL); if (version_compare(PHP_VERSION, '5.4.0', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 1); } else if (version_compare(PHP_VERSION, '5.3.6', '>=')) { $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); } else if (version_compare(PHP_VERSION, '5.2.5', '>=')) { $bt = debug_backtrace(false); } else { $bt = debug_backtrace(); }; $analyze_sourcecode = $settings['analyze_sourcecode']; //later, $analyze_sourcecode will be compared with $config['analyze_sourcecode'] //to determine if the reason was an error analyzing, or if it was disabled.. $bt = $bt[0]; //<analyzeSourceCode> if ($analyze_sourcecode) { $argvSourceCode = array(0 => 'ignore [0]...'); try { if (version_compare(PHP_VERSION, '5.2.2', '<')) { throw new Exception("PHP version is <5.2.2 .. see token_get_all changelog.."); }; $xsource = file_get_contents($bt['file']); if (empty($xsource)) { throw new Exception('cant get the source of '.$bt['file']); }; $xsource.= '<?php ignore_this_hhb_var_dump_workaround();'; //workaround, making sure that at least 1 token is an array, and has the $tok[2] >= line of hhb_var_dump $xTokenArray = token_get_all($xsource); //<trim$xTokenArray> $tmpstr=''; $tmpUnsetKeyArray = array(); ForEach($xTokenArray as $xKey => $xToken) { if (is_array($xToken)) { $tmpstr = trim($xToken[1]); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; continue; }; switch ($xToken[0]) { case T_COMMENT: case T_DOC_COMMENT: //T_ML_COMMENT in PHP4 -.- case T_INLINE_HTML: { $tmpUnsetKeyArray[] = $xKey; continue; }; default: { continue; } } } else if (is_string($xToken)) { $tmpstr = trim($xToken); if (empty($tmpstr) && $tmpstr!=='0'/*string("0") is considered "empty" -.-*/) { $tmpUnsetKeyArray[] = $xKey; }; continue; } else { //should be unreachable.. //failed both is_array() and is_string() ??? throw new LogicException('Impossible! $xToken fails both is_array() and is_string() !! .. '); }; }; ForEach($tmpUnsetKeyArray as $toUnset) { unset($xTokenArray[$toUnset]); }; $xTokenArray = array_values($xTokenArray); //fixing the keys.. //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,'before:',count(token_get_all($xsource),COUNT_NORMAL),'after',count($xTokenArray,COUNT_NORMAL))); unset($tmpstr,$xKey, $xToken, $toUnset, $tmpUnsetKeyArray); //</trim$xTokenArray> $firstInterestingLineTokenKey = -1; $lastInterestingLineTokenKey = -1; //<find$lastInterestingLineTokenKey> ForEach($xTokenArray as $xKey => $xToken) { if (!is_array($xToken) || !array_key_exists(2,$xToken) || !is_integer($xToken[2]) || $xToken[2] < $bt['line']) continue; $tmpkey = $xKey; //we don't got what we want yet.. while (true) { if (!array_key_exists($tmpkey, $xTokenArray)) { throw new Exception('1unable to find $lastInterestingLineTokenKey !'); }; if ($xTokenArray[$tmpkey] === ';') { //var_dump(__LINE__.":SUCCESS WITH",$tmpkey,$xTokenArray[$tmpkey]); $lastInterestingLineTokenKey = $tmpkey; break; } //var_dump(__LINE__.":FAIL WITH ",$tmpkey,$xTokenArray[$tmpkey]); //if $xTokenArray has >=PHP_INT_MAX keys, we don't want an infinite loop, do we? ;p //i wonder how much memory that would require though.. over-engineering, err, time-wasting, ftw? if ($tmpkey >= PHP_INT_MAX) { throw new Exception('2unable to find $lastIntperestingLineTokenKey ! (PHP_INT_MAX reached without finding ";"...)'); }; ++$tmpkey; } break; }; if ($lastInterestingLineTokenKey <= -1) { throw new Exception('3unable to find $lastInterestingLineTokenKey !'); }; unset($xKey,$xToken,$tmpkey); //</find$lastInterestingLineTokenKey> //<find$firstInterestingLineTokenKey> //now work ourselves backwards from $lastInterestingLineTokenKey to the first token where $xTokenArray[$tmpi][1] == "hhb_var_dump" //i doubt this is fool-proof but.. cant think of a better way (in userland, anyway) atm.. $tmpi = $lastInterestingLineTokenKey; do { if (array_key_exists($tmpi, $xTokenArray) && is_array($xTokenArray[$tmpi]) && array_key_exists(1, $xTokenArray[$tmpi]) && is_string($xTokenArray[$tmpi][1]) && strcasecmp($xTokenArray[$tmpi][1], $bt['function']) === 0) { //var_dump(__LINE__."SUCCESS WITH",$tmpi,$xTokenArray[$tmpi]); if (!array_key_exists($tmpi + 2, $xTokenArray)) { //+2 because [0] is (or should be) "hhb_var_dump" and [1] is (or should be) "(" throw new Exception('1unable to find the $firstInterestingLineTokenKey...'); }; $firstInterestingLineTokenKey = $tmpi + 2; break; /**/ }; //var_dump(__LINE__."FAIL WITH ",$tmpi,$xTokenArray[$tmpi]); --$tmpi; } while (-1 < $tmpi); //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__,$tmpi)); if ($firstInterestingLineTokenKey <= -1) { throw new Exception('2unable to find the $firstInterestingLineTokenKey...'); }; unset($tmpi); //Note: $lastInterestingLineTokeyKey is likely to contain more stuff than only the stuff we want.. //</find$firstInterestingLineTokenKey> //<rebuildInterestingSourceCode> //ok, now we have $firstInterestingLineTokenKey and $lastInterestingLineTokenKey.... $interestingTokensArray = array_slice($xTokenArray, $firstInterestingLineTokenKey, (($lastInterestingLineTokenKey - $firstInterestingLineTokenKey) + 1)); unset($addUntil, $tmpi, $tmpstr,$tmpi,$argvsourcestr, $tmpkey,$xTokenKey,$xToken); $addUntil = array(); $tmpi = 0; $tmpstr = ""; $tmpkey = ""; $argvsourcestr = ""; //$argvSourceCode[X]='source code..'; ForEach($interestingTokensArray as $xTokenKey => $xToken) { if (is_array($xToken)) { $tmpstr = $xToken[1]; //var_dump($xToken[1]); } else if (is_string($xToken)) { $tmpstr = $xToken; //var_dump($xToken); } else { /*should never reach this */ throw new LogicException('Impossible situation? $xToken fails is_array() and fails is_string() ...'); }; $argvsourcestr.= $tmpstr; if ($xToken === '(') { $addUntil[] = ')'; continue; }; if ($xToken === ')') { if (false === ($tmpkey = array_search(')', $addUntil, false))) { $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the ")" if (count($argvSourceCode, COUNT_NORMAL) - 1 === $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { break; /*We read em all! :D (.. i hope)*/ }; /*else... oh crap*/ throw new Exception('failed to read source code of (what i think is) argv['.count($argvSourceCode, COUNT_NORMAL).'] ! sorry..'); } unset($addUntil[$tmpkey]); continue; } if (empty($addUntil) && $xToken === ','){ $argvSourceCode[] = substr($argvsourcestr, 0, -1); //-1 is to strip the comma $argvsourcestr = ""; }; }; //die(var_dump('die(var_dump(...)) in '.__FILE__.':'.__LINE__, //$firstInterestingLineTokenKey,$lastInterestingLineTokenKey,$interestingTokensArray,$tmpstr //$argvSourceCode)); if (count($argvSourceCode, COUNT_NORMAL) - 1 != $argc) /*-1 because $argvSourceCode[0] is bullshit*/ { throw new Exception('failed to read source code of all the arguments! (and idk which ones i missed)! sorry..'); }; //</rebuildInterestingSourceCode> } catch (Exception $ex) { $argvSourceCode = array(); //clear it //TODO: failed to read source code //die("TODO N STUFF..".__FILE__.__LINE__); $analyze_sourcecode = false; //ERROR.. if ($settings['debug_hhb_var_dump']) { throw $ex; } else {/*exception ignored, continue as normal without $analyze_sourcecode */}; } unset($xsource, $xToken, $xTokenArray, $firstInterestingLineTokenKey, $lastInterestingLineTokenKey, $xTokenKey, $tmpi, $tmpkey,$argvsourcestr); }; //</analyzeSourceCode> $msg = $settings['hhb_var_dump_prepend']; if ($analyze_sourcecode != $settings['analyze_sourcecode']) { $msg.= ' (PS: some error analyzing source code)'.PHP_EOL; }; $msg.= 'in "'.$bt['file']. '": on line "'.$bt['line']. '": '.$argc. ' variable'.($argc === 1 ? '' : 's') //because over-engineering ftw? .PHP_EOL; if ($analyze_sourcecode) { $msg.= ' hhb_var_dump('; $msg.= implode(",", array_slice($argvSourceCode, 1));//$argvSourceCode[0] is bullshit. $msg.= ')'.PHP_EOL; } //array_unshift($bt,$msg); echo $msg; $i = 0; foreach($argv as &$val) { echo 'argv['.++$i.']'; if ($analyze_sourcecode) { echo ' >>>'.$argvSourceCode[$i].'<<<'; } echo ':'; if ($settings['use_xdebug_var_dump']) { xdebug_var_dump($val); } else { var_dump($val); }; } echo $settings['hhb_var_dump_append']; //call_user_func_array("var_dump",$args); } function shutdownf(){ global $starttime; //echo 'time used: ',microtime(true)-$starttime; } function f(){ return 'f() returns lol n stuff :D'; } register_shutdown_function("shutdownf"); $starttime=microtime(true); hhb_var_dump ( $var,'lol',array(array(array('',100)),NULL),"",f('', 'break(break me!!) break me!', 100, NULL ,array(array( '',100)) ),NULL,"",1337, 0 , (1?true:false) ,(1) && true );

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
7.2.00.0000.01519.46
7.1.70.0100.00717.02
7.1.60.0100.01419.32
7.1.50.0040.01516.74
7.1.00.0000.08322.58
7.0.200.0030.00916.55
7.0.140.0000.07721.96
7.0.100.0030.04720.75
7.0.90.0030.05020.80
7.0.80.0030.03720.74
7.0.70.0070.03720.78
7.0.60.0030.03320.70
7.0.50.0130.03021.13
7.0.40.0030.04319.97
7.0.30.0030.04319.97
7.0.20.0000.04320.09
7.0.10.0000.05320.16
7.0.00.0030.05320.15
5.6.280.0070.07722.13
5.6.250.0070.04721.86
5.6.240.0070.04321.67
5.6.230.0000.04721.70
5.6.220.0030.03721.75
5.6.210.0030.03721.53
5.6.200.0100.03322.25
5.6.190.0030.03722.18
5.6.180.0030.04722.16
5.6.170.0070.04322.04
5.6.160.0130.06022.11
5.6.150.0100.07022.06
5.6.140.0100.04722.09
5.6.130.0070.07022.15
5.6.120.0100.03722.22
5.6.110.0070.08722.06
5.6.100.0070.05722.21
5.6.90.0100.07722.16
5.6.80.0130.07321.60
5.6.70.0130.03721.49
5.6.60.0130.03321.48
5.6.50.0030.04021.41
5.6.40.0100.08021.51
5.6.30.0070.07721.57
5.6.20.0030.08021.59
5.6.10.0070.08321.34
5.6.00.0200.07021.61
5.5.380.0000.04021.45
5.5.370.0030.04321.52
5.5.360.0030.03721.43
5.5.350.0070.03321.50
5.5.340.0070.03322.02
5.5.330.0030.03721.75
5.5.320.0100.03022.03
5.5.310.0000.04021.98
5.5.300.0000.04021.84
5.5.290.0030.04321.99
5.5.280.0000.09021.88
5.5.270.0070.07721.89
5.5.260.0030.05721.87
5.5.250.0030.06721.77
5.5.240.0100.07321.29
5.5.230.0000.07721.31
5.5.220.0030.07721.41
5.5.210.0130.06321.41
5.5.200.0100.08021.38
5.5.190.0070.06321.28
5.5.180.0030.08021.34
5.5.160.0030.04021.24
5.5.150.0070.04721.35
5.5.140.0070.04321.27
5.5.130.0130.08321.05
5.5.120.0100.07721.28
5.5.110.0130.07721.21
5.5.100.0130.03021.18
5.5.90.0100.08321.25
5.5.80.0030.08021.21
5.5.70.0030.04321.19
5.5.60.0100.05321.25
5.5.50.0030.07321.24
5.5.40.0030.05321.25
5.5.30.0030.04721.18
5.5.20.0130.07721.03
5.5.10.0030.04321.06
5.5.00.0100.05721.08
5.4.450.0000.05020.27
5.4.440.0000.04320.45
5.4.430.0130.07320.34
5.4.420.0030.08720.54
5.4.410.0070.04720.18
5.4.400.0070.07020.07
5.4.390.0000.04320.15
5.4.380.0030.05020.06
5.4.370.0030.03720.22
5.4.360.0170.03020.13
5.4.350.0030.04019.93
5.4.340.0000.04720.15
5.4.320.0030.07719.93
5.4.310.0100.06320.00
5.4.300.0030.03720.02
5.4.290.0030.07020.02
5.4.280.0030.08020.06
5.4.270.0130.05720.14
5.4.260.0030.07319.92
5.4.250.0030.04020.29
5.4.240.0070.03720.07
5.4.230.0100.07720.04
5.4.220.0000.04720.16
5.4.210.0030.05720.02
5.4.200.0000.05320.09
5.4.190.0130.06020.04
5.4.180.0070.05720.14
5.4.170.0030.04720.08
5.4.160.0070.07320.13
5.4.150.0000.07019.91
5.4.140.0000.04717.41
5.4.130.0030.05317.44
5.4.120.0070.07017.44
5.4.110.0100.04317.41
5.4.100.0100.03017.55
5.4.90.0000.03717.54
5.4.80.0000.04717.39
5.4.70.0100.03017.39
5.4.60.0100.06317.52
5.4.50.0000.04017.48
5.4.40.0100.03717.55
5.4.30.0070.06317.34
5.4.20.0070.07717.39
5.4.10.0130.07017.39
5.4.00.0000.07716.80
5.3.290.0130.07015.82
5.3.280.0000.04315.85
5.3.270.0000.06315.70
5.3.260.0070.04015.68
5.3.250.0100.07715.86
5.3.240.0070.03715.72
5.3.230.0030.03715.68
5.3.220.0030.03715.73
5.3.210.0070.07715.66
5.3.200.0030.04715.64
5.3.190.0000.07715.78
5.3.180.0070.07315.82
5.3.170.0070.07315.69
5.3.160.0100.07315.85
5.3.150.0070.06715.64
5.3.140.0170.07015.74
5.3.130.0100.07315.73
5.3.120.0030.04715.77
5.3.110.0100.07315.63
5.3.100.0200.06315.32
5.3.90.0130.03015.23
5.3.80.0000.08015.06
5.3.70.0000.08015.14
5.3.60.0070.06315.15
5.3.50.0070.09315.03
5.3.40.0030.04015.25
5.3.30.0070.06314.99
5.3.20.0100.07014.71
5.3.10.0000.08014.75
5.3.00.0030.07314.73

preferences:
39.27 ms | 400 KiB | 5 Q