3v4l.org

run code in 200+ php & hhvm versions
Bugs & Features
<?php class StringStreamWrapper { const PROTOCOL = "stringstream"; private $stringstream; private $position; private $stringlength; public function stream_open($path, $mode, $options, &$opened_path) { $contextOptions = stream_context_get_options($this->context); if (!isset($contextOptions[self::PROTOCOL]['string'])) return false; $this->position = 0; // this is our stream! $this->stringstream = $contextOptions[self::PROTOCOL]['string']; $this->stringlength = strlen($this->stringstream); return true; } public function stream_read($len) { $data = substr($this->stringstream, $this->position, $len); $this->position += strlen($data); return $data; } public function stream_write($data){ $l = strlen($data); $this->stringstream = substr($this->stringstream, 0, $this->position) . $data . substr($this->stringstream, $this->position += $l); $this->stringlength = strlen($this->stringstream); return $l; } public function stream_seek($offset, $whence = SEEK_SET) { if ($whence == SEEK_CUR) { $this->position += $offset; } else if ($whence == SEEK_END) { $this->position = $this->stringlength + $offset; } else { $this->position = $offset; } return true; } public function stream_tell() { return $this->position; } public function stream_eof() { return ($this->position >= $this->stringlength); } public function stream_stat() { return array( 7 => $this->stringlength, 'size' => $this->stringlength, ); } static public function Open($string) { $context = stream_context_create(array(self::PROTOCOL => array('string' => &$string))); return fopen(self::PROTOCOL . "://",'r', false, $context); } } stream_wrapper_register(StringStreamWrapper::PROTOCOL, "StringStreamWrapper"); class replace_nullchar_filter extends php_user_filter { function filter($in, $out, &$consumed, $closing) { while ($bucket = stream_bucket_make_writeable($in)) { $bucket->data = str_replace("\0", "", $bucket->data); $consumed += $bucket->datalen; stream_bucket_append($out, $bucket); } return PSFS_PASS_ON; } } stream_filter_register('replacenullchar', 'replace_nullchar_filter'); class StringStreamWrapperFixed { public static function bug68532fixed() { if (defined('BUG68532FIXED')) return BUG68532FIXED; return version_compare(PHP_VERSION, '5.6.5', '>=') || (version_compare(PHP_VERSION, '5.5.21', '>=') && version_compare(PHP_VERSION, '5.6.0', '<')); } public static function Open($string) { if (self::bug68532fixed()) { $stream = fopen('php://temp', 'r+'); } else { $stream = tmpfile(); } fwrite($stream, $string); rewind($stream); return $stream; } } ####################################### $testString = 'test'; echo "base64_encode = " . base64_encode($testString).PHP_EOL; ####################################### # put some data in the StringStreamWrapper $stringstream = StringStreamWrapper::Open($testString); # emulate the output stream (in memory) $output = fopen('php://memory','r+'); # attach write filter to output $filter = stream_filter_append($output, 'convert.base64-encode'); flush($output); # write to output $written = stream_copy_to_stream($stringstream, $output); # remove filter stream_filter_remove($filter); rewind($output); echo "from outputstream = " . stream_get_contents($output).PHP_EOL;
based on 15g9L

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).
Note: hhvm uses a JIT which only kicks in after a few runs. Since we run scripts only once, hhvm always runs slower.

VersionSystem time (s)User time (s)Memory (MiB)
7.2.80.0100.00316.71
7.2.60.0030.00916.96
7.2.00.0060.00619.55
7.1.200.0060.00615.76
7.1.100.0030.00618.23
7.1.70.0060.00317.06
7.1.60.0070.01819.13
7.1.50.0100.01317.05
7.1.00.0000.07722.44
7.0.200.0080.00816.59
7.0.60.0100.03319.93
7.0.50.0030.08717.89
7.0.40.0130.08020.09
7.0.30.0530.05320.21
7.0.20.0370.07020.30
7.0.10.0000.06020.10
7.0.00.0100.06720.19
5.6.280.0030.05721.14
5.6.210.0170.06320.58
5.6.200.0130.03018.24
5.6.190.0100.05020.77
5.6.180.0200.05320.61
5.6.170.0170.04020.55
5.6.160.0170.08020.46
5.6.150.0000.04318.21
5.6.140.0000.07018.21
5.6.130.0100.07318.22
5.6.120.0070.05020.93
5.6.110.0070.09020.93
5.6.100.0070.03721.16
5.6.90.0100.06720.98
5.6.80.0070.03720.41
5.5.350.0270.07720.50
5.5.340.0100.07717.99
5.5.330.0070.05020.43
5.5.320.0170.04020.31
5.5.310.0200.05020.24
5.5.300.0000.04318.09
5.5.290.0130.06718.00
5.5.280.0070.08720.80
5.5.270.0170.08320.80
5.5.260.0030.05020.83
5.5.250.0100.05720.73
5.5.240.0270.07020.31
5.4.450.0230.05319.58
5.4.440.0170.06019.31
5.4.430.0230.05019.43
5.4.420.0230.05019.69
5.4.410.0200.05319.34
5.4.400.0200.05019.00
5.4.390.0230.05018.87
5.4.380.0270.04719.22
5.4.370.0270.05019.06
5.4.360.0230.07018.87
5.4.350.0070.06319.15
5.4.340.0230.06719.14
5.4.320.0200.06018.87
5.4.310.0300.04319.37
5.4.300.0130.06318.87
5.4.290.0230.04319.12
5.4.280.0130.05719.14
5.4.270.0100.05719.00
5.4.260.0100.05719.14
5.4.250.0230.04318.96
5.4.240.0200.05019.24
5.4.230.0130.05319.14
5.4.220.0070.06319.04
5.4.210.0130.05319.25
5.4.200.0070.06019.05
5.4.190.0200.05019.25
5.4.180.0130.05319.31
5.4.170.0170.05019.27
5.4.160.0170.05019.23
5.4.150.0200.05719.12
5.4.140.0270.04016.70
5.4.130.0070.05716.32
5.4.120.0200.04716.29
5.4.110.0300.04016.69
5.4.100.0200.04716.24
5.3.290.0130.06314.70
5.3.280.0200.04714.68
5.3.270.0100.06014.63
5.3.260.0200.04714.77
5.3.250.0130.05714.77
5.3.240.0130.05314.77
5.3.230.0200.05014.68
5.3.220.0200.04714.73
5.3.210.0130.06014.69
5.3.200.0200.04714.59