├── .gitignore ├── .gitmodules ├── LICENCE.markdown ├── README.markdown ├── build.sh ├── cli-c ├── README.markdown ├── build.sh ├── exec.sh └── mandelbrot.c ├── cli-hhvm-ext ├── build.sh ├── config.cmake ├── config.hdf ├── exec.sh ├── exec_jitted.sh ├── ext_treffynnon.cpp ├── ext_treffynnon.php └── test.php ├── cli-hhvm-hack ├── exec.sh ├── exec_jitted.sh └── test.hh ├── cli-hhvm-php ├── exec.sh └── exec_jitted.sh ├── cli-php-ext ├── build.sh ├── config.m4 ├── exec.sh ├── exec_no_opcache.sh ├── php_treffynnon.h ├── test.php └── treffynnon.c ├── cli-php-php ├── exec.sh ├── exec_no_opcache.sh └── test.php ├── cli-php-qb ├── README.md ├── exec.sh ├── exec_no_opcache.sh └── test.php ├── cli-php-zephir-cblock ├── README.markdown ├── build.sh ├── exec.sh ├── exec_no_opcache.sh ├── test.php └── treffynnoncblock │ ├── config.json │ └── treffynnoncblock │ └── test.zep ├── cli-php-zephir-optimizer ├── README.markdown ├── build.sh ├── exec.sh ├── exec_no_opcache.sh ├── test.php └── treffynnonoptimizer │ ├── config.json │ ├── ext │ ├── my_mandelbrot.c │ └── my_mandelbrot.h │ ├── optimizers │ ├── MandelbrotToFileOptimizer.php │ └── MandelbrotToMemOptimizer.php │ └── treffynnonoptimizer │ └── test.zep ├── cli-php-zephir ├── build.sh ├── exec.sh ├── exec_no_opcache.sh ├── test.php └── treffynnon │ ├── config.json │ └── treffynnon │ └── test.zep ├── exec.sh ├── fcgi-hhvm-ext ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-hhvm-hack ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-hhvm-php ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-ext ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-php ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-qb ├── README.md ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-zephir-cblock ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-zephir-optimizer ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── fcgi-php-zephir ├── exec.sh ├── setup.sh ├── setup_no_options.sh ├── teardown.sh └── test.php ├── graph_chart_template.html ├── graph_index_template.html ├── reporting_collect_csv_reports.sh ├── reporting_exec.sh ├── reporting_generate_charts.php └── reporting_parse_and_compile_csv.php /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### C++ ### 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Compiled Dynamic libraries 11 | *.so 12 | *.dylib 13 | *.dll 14 | 15 | # Compiled Static libraries 16 | *.lai 17 | *.la 18 | *.a 19 | *.lib 20 | 21 | # Executables 22 | *.exe 23 | *.out 24 | *.app 25 | 26 | 27 | ### C ### 28 | # Object files 29 | *.o 30 | *.ko 31 | *.obj 32 | *.elf 33 | 34 | # Libraries 35 | *.lib 36 | *.a 37 | 38 | # Shared objects (inc. Windows DLLs) 39 | *.dll 40 | *.so 41 | *.so.* 42 | *.dylib 43 | 44 | # Executables 45 | *.exe 46 | *.out 47 | *.app 48 | *.i*86 49 | *.x86_64 50 | *.hex 51 | 52 | 53 | # Ignore build files 54 | # 55 | # to add all untracked files to .gitignore use: 56 | # git status --porcelain | grep '^??' | cut -c4- >>.gitignore 57 | # src: http://stackoverflow.com/a/15142010 58 | cli-c/mandelbrot 59 | cli-hhvm-ext/CMakeCache.txt 60 | cli-hhvm-ext/CMakeFiles/ 61 | cli-hhvm-ext/CMakeLists.txt 62 | cli-hhvm-ext/Makefile 63 | cli-hhvm-ext/cmake_install.cmake 64 | cli-php-ext/.deps 65 | cli-php-ext/Makefile 66 | cli-php-ext/Makefile.fragments 67 | cli-php-ext/Makefile.global 68 | cli-php-ext/Makefile.objects 69 | cli-php-ext/acinclude.m4 70 | cli-php-ext/aclocal.m4 71 | cli-php-ext/autom4te.cache/ 72 | cli-php-ext/build/ 73 | cli-php-ext/config.guess 74 | cli-php-ext/config.h 75 | cli-php-ext/config.h.in 76 | cli-php-ext/config.log 77 | cli-php-ext/config.nice 78 | cli-php-ext/config.status 79 | cli-php-ext/config.sub 80 | cli-php-ext/configure 81 | cli-php-ext/configure.in 82 | cli-php-ext/install-sh 83 | cli-php-ext/libtool 84 | cli-php-ext/ltmain.sh 85 | cli-php-ext/missing 86 | cli-php-ext/mkinstalldirs 87 | cli-php-ext/run-tests.php 88 | cli-php-zephir-cblock/treffynnoncblock/.temp/ 89 | cli-php-zephir-cblock/treffynnoncblock/ext/ 90 | cli-php-zephir-optimizer/treffynnonoptimizer/.temp/ 91 | cli-php-zephir-optimizer/treffynnonoptimizer/ext/ 92 | !cli-php-zephir-optimizer/treffynnonoptimizer/ext/my_mandelbrot.h 93 | !cli-php-zephir-optimizer/treffynnonoptimizer/ext/my_mandelbrot.c 94 | cli-php-zephir/treffynnon/.temp/ 95 | cli-php-zephir/treffynnon/ext/ 96 | 97 | results.csv 98 | parsed_results_* 99 | results_* 100 | results-* 101 | index.html 102 | composer.phar 103 | composer.lock 104 | vendor 105 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "fcgicli"] 2 | path = fcgicli 3 | url = git@github.com:treffynnon/fcgicli.git 4 | -------------------------------------------------------------------------------- /LICENCE.markdown: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Simon Holywell 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | 8 | 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 9 | 10 | 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. 11 | 12 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 13 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | PHP vs HHVM vs Zephir vs QB 2 | =========================== 3 | 4 | This benchmark is using the [Mandelbrot set](http://en.wikipedia.org/wiki/Mandelbrot_set) as its task. 5 | 6 | ![Image of the Mandelbrot set](http://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Mandel_zoom_00_mandelbrot_set.jpg/320px-Mandel_zoom_00_mandelbrot_set.jpg) 7 | 8 | ## Mandelbrot 9 | 10 | The actual algorithm code is not mine and was written by contributors to [The Computer Language Benchmarks Game](http://benchmarksgame.alioth.debian.org/u64/performance.php?test=mandelbrot): 11 | 12 | - [C](http://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=gcc&id=2#sourcecode) 13 | - [PHP](http://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=php&id=1#sourcecode) 14 | 15 | The code in the game is all licenced under a [Revised BSD license](http://benchmarksgame.alioth.debian.org/license.php). 16 | 17 | ## Running the tests 18 | 19 | ### Building 20 | #### Prerequisites 21 | 22 | To run the builds you will need to first ensure you have built the following from source: 23 | 24 | - [PHP](https://github.com/php/php) 25 | - [HHVM](https://github.com/facebook/hhvm/wiki#wiki-building-hhvm) 26 | - [Zephir](http://zephir-lang.com/install.html) 27 | - [QB](https://github.com/chung-leong/qb) 28 | 29 | It is best to build PHP from source instead of using a precompiled package to level the playing field. You must build HHVM from source otherwise the HHVM extension won't be installable. 30 | 31 | #### Setting environment vars 32 | 33 | So that the build script knows where Zephir and HHVM are installed you'll need to specify the following to environment variables. Run the next two commands in your console (after adjusting the paths!): 34 | 35 | ```bash 36 | export HPHP_HOME=/path/to/hhvm 37 | export ZPHP_HOME=/path/to/zephir 38 | ``` 39 | 40 | #### Building the project in one hit 41 | 42 | In the root directory of this project running the following command (turn on unlimited scrollback in your console first): 43 | 44 | ```bash 45 | ./build.sh 46 | ``` 47 | 48 | Keep an eye out for any build errors that will need to be rectified before continuing. 49 | 50 | ### Executing the tests 51 | 52 | Tests are run a number of times so that an average can be taken (by default this is 20 times). Additionally there is a seed value - this is the value that is used to seed the Mandelbrot set calculations. The higher the seed number the more complex the calculation that the programmes must complete. 53 | 54 | If you want to ensure that your tests are given favourable scheduling for proc time then review the [`nice` manual page](http://unixhelp.ed.ac.uk/CGI/man-cgi?nice). 55 | 56 | #### Setting environment vars 57 | 58 | So that the exec script knows where Zephir and HHVM are installed you'll need to specify the following to environment variables. Run the next two commands in your console (after adjusting the paths!): 59 | 60 | ```bash 61 | export HPHP_HOME=/path/to/hhvm 62 | export ZPHP_HOME=/path/to/zephir 63 | ``` 64 | 65 | You'll only need to run this once per ssh connection/console session. 66 | 67 | #### To screen 68 | 69 | This can take some time to complete as it does a number of iterations with a static seed value (currently defaults to 1000). 70 | 71 | ```bash 72 | ./exec.sh 73 | ``` 74 | 75 | You can specify some options at execution time. 76 | 77 | ##### Supply the seed 78 | 79 | This is the value that is used to seed the Mandelbrot set calculations. The higher the seed number the more complex the calculation that the programmes must complete. 80 | 81 | ```bash 82 | ./exec.sh 16000 83 | ``` 84 | 85 | ##### Supply an alternate format for `time` 86 | 87 | See the [`time` man page](http://unixhelp.ed.ac.uk/CGI/man-cgi?time) for more information on the tokens you can use. 88 | 89 | ```bash 90 | ./exec.sh 1600 "Time in seconds: %e CPU: %P" 91 | ``` 92 | 93 | #### To reporting CSVs 94 | 95 | This will be quite slow as it does a number of iterations with a number of different seeds: 96 | 97 | - iterations x seed 98 | - 20 x 100 99 | - 20 x 200 100 | - 20 x 1000 101 | - 20 x 5000 102 | - 20 x 16000 103 | 104 | ```bash 105 | ./reporting_exec.sh 106 | ``` 107 | 108 | This will output a csv file for each item listed above and additionally a parsed (averaged and prettified) csv for each test. 109 | 110 | You can specify some options at execution time. 111 | 112 | ##### How many iterations? 113 | 114 | Tests are run a number of times so that an average can be taken (by default this is 20 times). The following would run all the tests 100 times. 115 | 116 | ```bash 117 | ./reporting_exec.sh 100 118 | ``` 119 | 120 | ## Licence 121 | 122 | This package falls under the [3-clause BSD licence](http://opensource.org/licenses/BSD-3-Clause). See LICENCE.markdown for more. 123 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo " " 3 | echo "Treffynnon benchmarker" 4 | echo "^^^^^^^^^^^^^^^^^^^^^^" 5 | echo " " 6 | echo "#################################" 7 | echo "# Treffynnon build script begin #" 8 | echo "#################################" 9 | echo " " 10 | echo " " 11 | echo "Clearing previous builds" 12 | echo "========================" 13 | echo "All untracked and .gitignored files will be removed! (This includes results from previous runs)" 14 | read -p "Are you sure you wish to do this (y/n)? " -n 1 -r 15 | if [[ $REPLY =~ ^[Yy]$ ]] 16 | then 17 | git clean -fdx 18 | fi 19 | 20 | echo " " 21 | echo "Building HHVM extension" 22 | echo "=======================" 23 | cd cli-hhvm-ext 24 | ./build.sh 25 | 26 | cd .. 27 | 28 | echo " " 29 | echo "Building PHP extension" 30 | echo "======================" 31 | cd cli-php-ext 32 | ./build.sh 33 | 34 | cd .. 35 | 36 | echo " " 37 | echo "Building plain C" 38 | echo "================" 39 | cd cli-c 40 | ./build.sh 41 | 42 | cd .. 43 | 44 | echo " " 45 | echo "Zephir: CBLOCK" 46 | echo "==============" 47 | cd cli-php-zephir-cblock 48 | ./build.sh 49 | 50 | cd .. 51 | 52 | echo " " 53 | echo "Zephir: Optimizer" 54 | echo "=================" 55 | cd cli-php-zephir-optimizer 56 | ./build.sh 57 | 58 | cd .. 59 | 60 | echo " " 61 | echo "Zephir: Zephir lang" 62 | echo "===================" 63 | cd cli-php-zephir 64 | ./build.sh 65 | 66 | cd .. 67 | 68 | echo " " 69 | echo "Setup FCGI CLI client" 70 | echo "===================================================" 71 | echo " " 72 | git submodule init 73 | git submodule update 74 | cd fcgicli 75 | git checkout master 76 | git pull origin master 77 | make 78 | cd .. 79 | 80 | echo " " 81 | echo "####################################" 82 | echo "# Treffynnon build script complete #" 83 | echo "####################################" 84 | echo " " 85 | -------------------------------------------------------------------------------- /cli-c/README.markdown: -------------------------------------------------------------------------------- 1 | Mandelbrot in C 2 | =============== 3 | 4 | This is a simple C programme to print the Mandelbrot set as ASCII or as a .pbm (Portable Bitmap). ASCII can be read in a console and the .pbm can be viewed in something like GIMP. 5 | 6 | The [original code](http://benchmarksgame.alioth.debian.org/u64q/program.php?test=mandelbrot&lang=gcc&id=2#sourcecode) is from [The Computer Languages Benchmark Game](http://benchmarksgame.alioth.debian.org) and I have modified it (with inspiration from [Glenn Rhoads code](http://docs.parrot.org/parrot/0.9.1/html/examples/pir/mandel.pir.html)) to include the ASCII output. 7 | 8 | ## Build 9 | 10 | Run `./build.sh`. 11 | 12 | ## Usage 13 | 14 | To run the benchmark you can call `./exec.sh`. 15 | 16 | You can run the code manually by running `./mandelbrot 100` for a set that is 100 heigh and 100 wide in ASCII printed to STDOUT. 17 | 18 | Specify `./mandelbrot 100 1` for binary or `./mandelbrot 100 0` for the default ASCII. 19 | 20 | Finally, you can call `./mandelbrot 100 1 output.pbm` to have it save the portable bitmap to a file. To save the ASCII as a file you can run `./mandelbrot 100 0 output.txt`. 21 | -------------------------------------------------------------------------------- /cli-c/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | /usr/bin/env gcc -pipe -Wall -O3 -fomit-frame-pointer -march=native -std=c99 -mfpmath=sse -msse2 -fopenmp mandelbrot.c -o mandelbrot 3 | -------------------------------------------------------------------------------- /cli-c/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" ./mandelbrot "$ARG" 11 | -------------------------------------------------------------------------------- /cli-c/mandelbrot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | /* 8 | * Function adapted from example in The Computer 9 | * Languages Benchmark Game 10 | * 11 | * ASCII switch added by Simon Holywell and inspired 12 | * by code from Glenn Rhoads 13 | * (http://docs.parrot.org/parrot/0.9.1/html/examples/pir/mandel.pir.html) 14 | */ 15 | bool write_mandelbrot_to_stream(int w, int h, FILE *stream, bool bitmap) { 16 | int bit_num = 0; 17 | char byte_acc = 0; 18 | int i, iter = 50; 19 | double x, y, limit = 2.0; 20 | double Zr, Zi, Cr, Ci, Tr, Ti; 21 | const char* ochars = " .:-;!/>)|&IH%*#"; 22 | 23 | if(bitmap) 24 | fprintf(stream, "P4\n%d %d\n", w, h); 25 | 26 | for(y=0;y= 3 && atoi(argv[2]) == 1) { 115 | binary = true; 116 | } 117 | 118 | if(argc == 4) { 119 | mandelbrot_to_file(argv[3], w, h, binary); 120 | } else { 121 | printf("%s", mandelbrot_to_mem(w, h, binary)); 122 | } 123 | return 0; 124 | } 125 | -------------------------------------------------------------------------------- /cli-hhvm-ext/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$HPHP_HOME" == "" ]]; then 3 | echo "HPHP_HOME environment variable must be set!" 4 | echo 'export HPHP_HOME=/path/to/hhvm' 5 | exit 1 6 | fi 7 | $HPHP_HOME/hphp/tools/hphpize/hphpize 8 | cmake . 9 | make 10 | -------------------------------------------------------------------------------- /cli-hhvm-ext/config.cmake: -------------------------------------------------------------------------------- 1 | set(TREFFYNNON_EXTENSION_NAME "treffynnon") 2 | HHVM_EXTENSION(${TREFFYNNON_EXTENSION_NAME} "ext_${TREFFYNNON_EXTENSION_NAME}.cpp") 3 | HHVM_SYSTEMLIB(${TREFFYNNON_EXTENSION_NAME} "ext_${TREFFYNNON_EXTENSION_NAME}.php") 4 | -------------------------------------------------------------------------------- /cli-hhvm-ext/config.hdf: -------------------------------------------------------------------------------- 1 | DynamicExtensions { 2 | * = treffynnon.so 3 | } 4 | -------------------------------------------------------------------------------- /cli-hhvm-ext/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$HPHP_HOME" == "" ]]; then 3 | echo "HPHP_HOME environment variable must be set!" 4 | echo 'export HPHP_HOME=/path/to/hhvm' 5 | exit 1 6 | fi 7 | ARG=1000 8 | TIMEFORMAT="-v" 9 | if [ "$1" != "" ]; then 10 | ARG="$1" 11 | fi 12 | if [ "$2" != "" ]; then 13 | TIMEFORMAT="--format=$2" 14 | fi 15 | /usr/bin/env time "$TIMEFORMAT" $HPHP_HOME/hphp/hhvm/hhvm -c config.hdf -v "DynamicExtensionPath=`pwd`" test.php "$ARG" 16 | -------------------------------------------------------------------------------- /cli-hhvm-ext/exec_jitted.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # This run exists because of http://www.hhvm.com/blog/713/hhvm-optimization-tips 4 | # tl;dr HHVM cannot JIT code in global space 5 | # 6 | # Additionally as we are running it via the CLI we must manually enable JIT: http://www.leaseweblabs.com/2013/09/benchmarking-hiphopvm-php-5-3-ubuntu-12-04/#comment-6630 7 | 8 | 9 | if [[ "$HPHP_HOME" == "" ]]; then 10 | echo "HPHP_HOME environment variable must be set!" 11 | echo 'export HPHP_HOME=/path/to/hhvm' 12 | exit 1 13 | fi 14 | ARG=1000 15 | TIMEFORMAT="-v" 16 | if [ "$1" != "" ]; then 17 | ARG="$1" 18 | fi 19 | if [ "$2" != "" ]; then 20 | TIMEFORMAT="--format=$2" 21 | fi 22 | /usr/bin/env time "$TIMEFORMAT" $HPHP_HOME/hphp/hhvm/hhvm -c config.hdf -v "DynamicExtensionPath=`pwd`" -vEval.Jit=1 test.php "$ARG" 23 | -------------------------------------------------------------------------------- /cli-hhvm-ext/ext_treffynnon.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Simon Holywell 3 | * @license BSD 4 | */ 5 | 6 | #include "hphp/runtime/base/base-includes.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | /* 14 | * Function adapted from example in The Computer 15 | * Languages Benchmark Game 16 | * 17 | * ASCII switch added by Simon Holywell and inspired 18 | * by code from Glenn Rhoads 19 | * (http://docs.parrot.org/parrot/0.9.1/html/examples/pir/mandel.pir.html) 20 | */ 21 | bool write_mandelbrot_to_stream(int w, int h, FILE *stream, bool bitmap) { 22 | int bit_num = 0; 23 | char byte_acc = 0; 24 | int i, iter = 50; 25 | double x, y, limit = 2.0; 26 | double Zr, Zi, Cr, Ci, Tr, Ti; 27 | const char* ochars = " .:-;!/>)|&IH%*#"; 28 | 29 | if(bitmap) 30 | fprintf(stream, "P4\n%d %d\n", w, h); 31 | 32 | for(y=0;y> function treffynnon_mandelbrot_to_mem (int $w, int $h, bool $binary_output): string; 4 | <<__Native>> function treffynnon_mandelbrot_to_file (string $filename, int $w, int $h, bool $binary_output): bool; -------------------------------------------------------------------------------- /cli-hhvm-ext/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 25 | $pack_format = 'c*'; 26 | 27 | for ($y = 0 ; $y < $h ; ++$y) { 28 | $Ci = $y * $yfac - 1.0; 29 | for ($x = 0 ; $x < $w ; ++$x) { 30 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 31 | $Cr = $x * $xfac - 1.5; 32 | do { 33 | for ($i = 0; $i < $iter; ++$i) { 34 | $Zi = 2.0 * $Zr * $Zi + $Ci; 35 | $Zr = $Tr - $Ti + $Cr; 36 | $Tr = $Zr * $Zr; 37 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 38 | } 39 | $byte_acc += $bit_num; 40 | } while (false); 41 | 42 | if($bitmap) { 43 | if ($bit_num === 1) { 44 | fwrite($stream, pack($pack_format, $byte_acc)); 45 | $bit_num = 128; 46 | $byte_acc = 0; 47 | } else { 48 | $bit_num >>= 1; 49 | } 50 | } else { 51 | if($i == $iter) { 52 | fwrite($stream, $ochars[0]); 53 | } else { 54 | fwrite($stream, $ochars[($i+1) & 15]); 55 | } 56 | } 57 | } 58 | if($bitmap) { 59 | if ($bit_num !== 128) { 60 | fwrite($stream, pack($pack_format, $byte_acc)); 61 | $bit_num = 128; 62 | $byte_acc = 0; 63 | } 64 | } else { 65 | fwrite($stream, "\n"); 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | function treffynnon_mandelbrot_to_file(string $filename, int $w, int $h, bool $binary_output): bool { 72 | $file_open_type = 'w'; 73 | if($binary_output) 74 | $file_open_type = 'wb'; 75 | 76 | $stream = fopen((string) $filename, $file_open_type); 77 | if(false === $stream) 78 | return false; 79 | 80 | write_mandelbrot_to_stream($w, $h, $stream, $binary_output); 81 | fclose($stream); 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_mem(int $w, int $h, bool $binary_output): string { 86 | $file_open_type = 'w+'; 87 | if($binary_output) 88 | $file_open_type = 'w+b'; 89 | 90 | $stream = fopen('php://memory', $file_open_type); 91 | if(false === $stream) 92 | return ''; 93 | 94 | write_mandelbrot_to_stream($w, $h, $stream, $binary_output); 95 | rewind($stream); 96 | $ret = stream_get_contents($stream); 97 | fclose($stream); 98 | return $ret; 99 | } 100 | 101 | echo treffynnon_mandelbrot_to_mem((int) $argv[1], (int) $argv[1], false); 102 | -------------------------------------------------------------------------------- /cli-hhvm-php/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$HPHP_HOME" == "" ]]; then 3 | echo "HPHP_HOME environment variable must be set!" 4 | echo 'export HPHP_HOME=/path/to/hhvm' 5 | exit 1 6 | fi 7 | ARG=1000 8 | TIMEFORMAT="-v" 9 | if [ "$1" != "" ]; then 10 | ARG="$1" 11 | fi 12 | if [ "$2" != "" ]; then 13 | TIMEFORMAT="--format=$2" 14 | fi 15 | /usr/bin/env time "$TIMEFORMAT" $HPHP_HOME/hphp/hhvm/hhvm ../cli-php-php/test.php "$ARG" 16 | -------------------------------------------------------------------------------- /cli-hhvm-php/exec_jitted.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | # This run exists because of http://www.hhvm.com/blog/713/hhvm-optimization-tips 4 | # tl;dr HHVM cannot JIT code in global space 5 | # 6 | # Additionally as we are running it via the CLI we must manually enable JIT: http://www.leaseweblabs.com/2013/09/benchmarking-hiphopvm-php-5-3-ubuntu-12-04/#comment-6630 7 | 8 | 9 | if [[ "$HPHP_HOME" == "" ]]; then 10 | echo "HPHP_HOME environment variable must be set!" 11 | echo 'export HPHP_HOME=/path/to/hhvm' 12 | exit 1 13 | fi 14 | ARG=1000 15 | TIMEFORMAT="-v" 16 | if [ "$1" != "" ]; then 17 | ARG="$1" 18 | fi 19 | if [ "$2" != "" ]; then 20 | TIMEFORMAT="--format=$2" 21 | fi 22 | /usr/bin/env time "$TIMEFORMAT" $HPHP_HOME/hphp/hhvm/hhvm -vEval.Jit=1 ../cli-php-php/test.php "$ARG" 23 | -------------------------------------------------------------------------------- /cli-php-ext/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | phpize 3 | ./configure 4 | make 5 | -------------------------------------------------------------------------------- /cli-php-ext/config.m4: -------------------------------------------------------------------------------- 1 | PHP_ARG_WITH(treffynnon, for treffynnon support, 2 | [ --with-treffynnon[=DIR] Include treffynnon support. DIR is the optional path to the treffynnon directory.], yes) 3 | PHP_ARG_ENABLE(treffynnon-debug, whether to enable build debug output, 4 | [ --enable-treffynnon-debug treffynnon: Enable debugging during build], no, no) 5 | 6 | if test "$PHP_TREFFYNNON" != "no"; then 7 | withtreffynnon="$PHP_TREFFYNNON" 8 | treffynnon_enabledebug="$PHP_TREFFYNNON_DEBUG" 9 | PHP_NEW_EXTENSION(treffynnon, treffynnon.c, $ext_shared) 10 | PHP_SUBST(TREFFYNNON_SHARED_LIBADD) 11 | else 12 | AC_MSG_RESULT([treffynnon was not enabled]) 13 | AC_MSG_ERROR([Enable treffynnon to build this extension.]) 14 | fi 15 | -------------------------------------------------------------------------------- /cli-php-ext/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=modules/treffynnon.so" -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-ext/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=modules/treffynnon.so" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-ext/php_treffynnon.h: -------------------------------------------------------------------------------- 1 | #ifndef PHP_TREFFYNNON_H 2 | # define PHP_TREFFYNNON_H 1 3 | # define PHP_TREFFYNNON_VERSION "1.0.0" 4 | # define PHP_TREFFYNNON_EXTNAME "treffynnon" 5 | PHP_FUNCTION(treffynnon_mandelbrot_to_file); 6 | PHP_FUNCTION(treffynnon_mandelbrot_to_mem); 7 | extern zend_module_entry php_treffynnon_module_entry; 8 | # define phpext_php_treffynnon_ptr &php_treffynnon_module_entry 9 | #endif 10 | -------------------------------------------------------------------------------- /cli-php-ext/test.php: -------------------------------------------------------------------------------- 1 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "php.h" 12 | #include "php_ini.h" 13 | #include "ext/standard/info.h" 14 | #include "SAPI.h" 15 | #include "php_treffynnon.h" 16 | 17 | ZEND_BEGIN_ARG_INFO_EX(arginfo_treffynnon_mandelbrot_to_file, 0, 0, 4) 18 | ZEND_ARG_INFO(0, filename) 19 | ZEND_ARG_INFO(0, w) 20 | ZEND_ARG_INFO(0, h) 21 | ZEND_ARG_INFO(0, binary_output) 22 | ZEND_END_ARG_INFO() 23 | 24 | ZEND_BEGIN_ARG_INFO_EX(arginfo_treffynnon_mandelbrot_to_mem, 0, 0, 3) 25 | ZEND_ARG_INFO(0, w) 26 | ZEND_ARG_INFO(0, h) 27 | ZEND_ARG_INFO(0, binary_output) 28 | ZEND_END_ARG_INFO() 29 | 30 | /* {{{ treffynnon_functions[] 31 | */ 32 | const zend_function_entry treffynnon_functions[] = { 33 | PHP_FE(treffynnon_mandelbrot_to_file, arginfo_treffynnon_mandelbrot_to_file) 34 | PHP_FE(treffynnon_mandelbrot_to_mem, arginfo_treffynnon_mandelbrot_to_mem) { 35 | NULL, NULL, NULL} 36 | }; 37 | /* }}} */ 38 | 39 | /* {{{ PHP_MINFO_FUNCTION 40 | */ 41 | PHP_MINFO_FUNCTION(treffynnon) { 42 | php_info_print_table_start(); 43 | php_info_print_table_row(2, PHP_TREFFYNNON_EXTNAME " Module", "enabled"); 44 | php_info_print_table_row(2, "version", PHP_TREFFYNNON_VERSION); 45 | if (sapi_module.phpinfo_as_text) { 46 | /* No HTML for you */ 47 | php_info_print_table_row(2, "By", 48 | "Simon Holywell\nhttp://www.simonholywell.com"); 49 | } else { 50 | /* HTMLified version */ 51 | php_printf("" 52 | "By" 53 | "" 54 | "" 56 | "Simon Holywell" 57 | ""); 58 | } 59 | php_info_print_table_end(); 60 | } 61 | /* }}} */ 62 | 63 | 64 | /* 65 | * Function adapted from example in The Computer 66 | * Languages Benchmark Game 67 | * 68 | * ASCII switch added by Simon Holywell and inspired 69 | * by code from Glenn Rhoads 70 | * (http://docs.parrot.org/parrot/0.9.1/html/examples/pir/mandel.pir.html) 71 | */ 72 | bool write_mandelbrot_to_stream(int w, int h, FILE *stream, bool bitmap) { 73 | int bit_num = 0; 74 | char byte_acc = 0; 75 | int i, iter = 50; 76 | double x, y, limit = 2.0; 77 | double Zr, Zi, Cr, Ci, Tr, Ti; 78 | const char* ochars = " .:-;!/>)|&IH%*#"; 79 | 80 | if(bitmap) 81 | fprintf(stream, "P4\n%d %d\n", w, h); 82 | 83 | for(y=0;y= 20010901 202 | STANDARD_MODULE_HEADER, 203 | #endif 204 | PHP_TREFFYNNON_EXTNAME, 205 | treffynnon_functions, 206 | NULL /* PHP_MINIT(treffynnon) */, 207 | NULL /* PHP_MSHUTDOWN(treffynnon) */, 208 | NULL /* PHP_RINIT(treffynnon) */, /* Replace with NULL if there's nothing to do at request start */ 209 | NULL /* PHP_RSHUTDOWN(treffynnon)*/, /* Replace with NULL if there's nothing to do at request end */ 210 | PHP_MINFO(treffynnon), 211 | #if ZEND_MODULE_API_NO >= 20010901 212 | PHP_TREFFYNNON_VERSION, 213 | #endif 214 | STANDARD_MODULE_PROPERTIES 215 | }; 216 | /* }}} */ 217 | 218 | #ifdef COMPILE_DL_TREFFYNNON 219 | ZEND_GET_MODULE(treffynnon) 220 | #endif 221 | -------------------------------------------------------------------------------- /cli-php-php/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-php/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-php/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 25 | $pack_format = 'c*'; 26 | 27 | for ($y = 0 ; $y < $h ; ++$y) { 28 | $Ci = $y * $yfac - 1.0; 29 | for ($x = 0 ; $x < $w ; ++$x) { 30 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 31 | $Cr = $x * $xfac - 1.5; 32 | do { 33 | for ($i = 0; $i < $iter; ++$i) { 34 | $Zi = 2.0 * $Zr * $Zi + $Ci; 35 | $Zr = $Tr - $Ti + $Cr; 36 | $Tr = $Zr * $Zr; 37 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 38 | } 39 | $byte_acc += $bit_num; 40 | } while (false); 41 | 42 | if($bitmap) { 43 | if ($bit_num === 1) { 44 | fwrite($stream, pack($pack_format, $byte_acc)); 45 | $bit_num = 128; 46 | $byte_acc = 0; 47 | } else { 48 | $bit_num >>= 1; 49 | } 50 | } else { 51 | if($i == $iter) { 52 | fwrite($stream, $ochars[0]); 53 | } else { 54 | fwrite($stream, $ochars[($i+1) & 15]); 55 | } 56 | } 57 | } 58 | if($bitmap) { 59 | if ($bit_num !== 128) { 60 | fwrite($stream, pack($pack_format, $byte_acc)); 61 | $bit_num = 128; 62 | $byte_acc = 0; 63 | } 64 | } else { 65 | fwrite($stream, "\n"); 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | function treffynnon_mandelbrot_to_file($filename, $w, $h, $binary_output) { 72 | $file_open_type = 'w'; 73 | if($binary_output) 74 | $file_open_type = 'wb'; 75 | 76 | $stream = fopen((string) $filename, $file_open_type); 77 | if(false === $stream) 78 | return false; 79 | 80 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 81 | fclose($stream); 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_mem($w, $h, $binary_output) { 86 | $file_open_type = 'w+'; 87 | if($binary_output) 88 | $file_open_type = 'w+b'; 89 | 90 | $stream = fopen('php://memory', $file_open_type); 91 | if(false === $stream) 92 | return ''; 93 | 94 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 95 | rewind($stream); 96 | $ret = stream_get_contents($stream); 97 | fclose($stream); 98 | return $ret; 99 | } 100 | 101 | echo treffynnon_mandelbrot_to_mem((int) $argv[1], (int) $argv[1], false); -------------------------------------------------------------------------------- /cli-php-qb/README.md: -------------------------------------------------------------------------------- 1 | QB 2 | == 3 | 4 | There are a couple of caveats with this implementation: 5 | 6 | 1. QB doesn't handle streams being passed as parameters so I am printing the output and catching it using `ob_start()` to simulate a memory stream. When I emailed Chung he said this would probably be the closest to the original algorithm I'd be able to get. 7 | 2. You can't echo the result of a PHP function from QB directly and you must assign it to a variable first hence the lines like `print $tmp = pack()`. You can print directly from QB functions though. 8 | -------------------------------------------------------------------------------- /cli-php-qb/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=qb.so" -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-qb/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=qb.so" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-qb/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 40 | 41 | for ($y = 0 ; $y < $h ; ++$y) { 42 | $Ci = $y * $yfac - 1.0; 43 | for ($x = 0 ; $x < $w ; ++$x) { 44 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 45 | $Cr = $x * $xfac - 1.5; 46 | do { 47 | for ($i = 0; $i < $iter; ++$i) { 48 | $Zi = 2.0 * $Zr * $Zi + $Ci; 49 | $Zr = $Tr - $Ti + $Cr; 50 | $Tr = $Zr * $Zr; 51 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 52 | } 53 | $byte_acc += $bit_num; 54 | } while (false); 55 | 56 | if($bitmap) { 57 | if ($bit_num === 1) { 58 | echo $byte_acc; 59 | $bit_num = 128; 60 | $byte_acc = 0; 61 | } else { 62 | $bit_num >>= 1; 63 | } 64 | } else { 65 | if($i == $iter) { 66 | echo $ochars[0]; 67 | } else { 68 | echo $ochars[($i+1) & 15]; 69 | } 70 | } 71 | } 72 | if($bitmap) { 73 | if ($bit_num !== 128) { 74 | echo $byte_acc; 75 | $bit_num = 128; 76 | $byte_acc = 0; 77 | } 78 | } else { 79 | echo "\n"; 80 | } 81 | } 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_file($filename, $w, $h, $binary_output) { 86 | $file_open_type = 'w'; 87 | if($binary_output) 88 | $file_open_type = 'wb'; 89 | 90 | $stream = fopen((string) $filename, $file_open_type); 91 | if(false === $stream) 92 | return false; 93 | 94 | ob_start(); 95 | write_mandelbrot_to_stream((int) $w, (int) $h, (bool) $binary_output); 96 | fwrite($stream, ob_get_clean()); 97 | return true; 98 | } 99 | 100 | function treffynnon_mandelbrot_to_mem($w, $h, $binary_output) { 101 | ob_start(); 102 | write_mandelbrot_to_stream((int) $w, (int) $h, (bool) $binary_output); 103 | return ob_get_clean(); 104 | } 105 | 106 | echo treffynnon_mandelbrot_to_mem((int) $argv[1], (int) $argv[1], false); 107 | -------------------------------------------------------------------------------- /cli-php-zephir-cblock/README.markdown: -------------------------------------------------------------------------------- 1 | Zephir with CBLOCK 2 | ================== 3 | 4 | This is the simplest way (**not** the best way) of including a call to a C function directly inside Zephir. 5 | 6 | See [pull request #21](https://github.com/phalcon/zephir/pull/21) on the Zephir repository for more information. 7 | 8 | For information on building Zephir see [their documentation](http://zephir-lang.com/install.html). 9 | -------------------------------------------------------------------------------- /cli-php-zephir-cblock/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$ZPHP_HOME" == "" ]]; then 3 | echo "ZPHP_HOME environment variable must be set!" 4 | echo 'export ZPHP_HOME=/path/to/zephir' 5 | exit 1 6 | fi 7 | cd treffynnoncblock 8 | $ZPHP_HOME/bin/zephir compile 9 | cd .. 10 | -------------------------------------------------------------------------------- /cli-php-zephir-cblock/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=treffynnoncblock/ext/modules/treffynnoncblock.so" -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir-cblock/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=treffynnoncblock/ext/modules/treffynnoncblock.so" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir-cblock/test.php: -------------------------------------------------------------------------------- 1 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include "kernel/string.h" 14 | 15 | }% 16 | 17 | // this is the beginning of the C block 18 | %{ 19 | 20 | /* 21 | * Function adapted from example in The Computer 22 | * Languages Benchmark Game 23 | * 24 | * ASCII switch added by Simon Holywell and inspired 25 | * by code from Glenn Rhoads 26 | * (http://docs.parrot.org/parrot/0.9.1/html/examples/pir/mandel.pir.html) 27 | */ 28 | bool write_mandelbrot_to_stream(int w, int h, FILE *stream, bool bitmap) { 29 | int bit_num = 0; 30 | char byte_acc = 0; 31 | int i, iter = 50; 32 | double x, y, limit = 2.0; 33 | double Zr, Zi, Cr, Ci, Tr, Ti; 34 | const char* ochars = " .:-;!/>)|&IH%*#"; 35 | 36 | if(bitmap) 37 | fprintf(stream, "P4\n%d %d\n", w, h); 38 | 39 | for(y=0;y string 124 | { 125 | string ret = ""; 126 | %{ 127 | ZVAL_STRING(ret, mandelbrot_to_mem(w, h, binary_output), 1); 128 | }% 129 | return ret; 130 | } 131 | 132 | public static function treffynnon_mandelbrot_to_file(string filename, long w, long h, bool binary_output) -> bool 133 | { 134 | bool ret = false; 135 | %{ 136 | ret = mandelbrot_to_file(Z_STRVAL_P(filename), w, h, binary_output); 137 | }% 138 | return ret; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/README.markdown: -------------------------------------------------------------------------------- 1 | Zephir with Optimizer 2 | ===================== 3 | 4 | This is the Zephir way of including a call to a C function directly inside Zephir. 5 | 6 | See [pull request #21](https://github.com/phalcon/zephir/pull/21#issuecomment-26178522) on the Zephir repository for more information. Additionally there is some [Optimizer documentation](http://zephir-lang.com/functions.html#using-optimizers) in the Zephir manual pages. My [issue #128](https://github.com/phalcon/zephir/issues/128) provides some additional configuration information missing from other sources. 7 | 8 | For information on building Zephir see [their documentation](http://zephir-lang.com/install.html). 9 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$ZPHP_HOME" == "" ]]; then 3 | echo "ZPHP_HOME environment variable must be set!" 4 | echo 'export ZPHP_HOME=/path/to/zephir' 5 | exit 1 6 | fi 7 | cd treffynnonoptimizer 8 | $ZPHP_HOME/bin/zephir compile 9 | cd .. 10 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=treffynnonoptimizer/ext/modules/treffynnonoptimizer.so" -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d "extension=treffynnonoptimizer/ext/modules/treffynnonoptimizer.so" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#"; 18 | 19 | if(bitmap) 20 | fprintf(stream, "P4\n%d %d\n", w, h); 21 | 22 | for(y=0;y 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | char* my_mandelbrot_to_mem(zval* w, zval* h, zval* binary_output); 10 | bool my_mandelbrot_to_file(zval* filename, zval* w, zval* h, zval* binary_output); 11 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/treffynnonoptimizer/optimizers/MandelbrotToFileOptimizer.php: -------------------------------------------------------------------------------- 1 | processExpectedReturn($context); 11 | 12 | $symbolVariable = $call->getSymbolVariable(); 13 | if ($symbolVariable->isNotVariableAndString()) { 14 | throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression); 15 | } 16 | 17 | if ($call->mustInitSymbolVariable()) { 18 | $symbolVariable->initVariant($context); 19 | } 20 | 21 | $context->headersManager->add('my_mandelbrot'); 22 | 23 | $symbolVariable->setDynamicTypes('bool'); 24 | 25 | $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); 26 | $context->codePrinter->output('ZVAL_BOOL(' . $symbolVariable->getRealName() . ', my_mandelbrot_to_file(' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ', ' . $resolvedParams[2] . ', ' . $resolvedParams[3] . '));'); 27 | return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/treffynnonoptimizer/optimizers/MandelbrotToMemOptimizer.php: -------------------------------------------------------------------------------- 1 | processExpectedReturn($context); 11 | 12 | $symbolVariable = $call->getSymbolVariable(); 13 | if ($symbolVariable->isNotVariableAndString()) { 14 | throw new CompilerException("Returned values by functions can only be assigned to variant variables", $expression); 15 | } 16 | 17 | if ($call->mustInitSymbolVariable()) { 18 | $symbolVariable->initVariant($context); 19 | } 20 | 21 | $context->headersManager->add('my_mandelbrot'); 22 | 23 | $symbolVariable->setDynamicTypes('string'); 24 | 25 | $resolvedParams = $call->getReadOnlyResolvedParams($expression['parameters'], $context, $expression); 26 | $context->codePrinter->output('ZVAL_STRING(' . $symbolVariable->getRealName() . ', my_mandelbrot_to_mem(' . $resolvedParams[0] . ', ' . $resolvedParams[1] . ', ' . $resolvedParams[2] . '), 1);'); 27 | return new CompiledExpression('variable', $symbolVariable->getRealName(), $expression); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /cli-php-zephir-optimizer/treffynnonoptimizer/treffynnonoptimizer/test.zep: -------------------------------------------------------------------------------- 1 | namespace Treffynnonoptimizer; 2 | 3 | class Test 4 | { 5 | public static function treffynnon_mandelbrot_to_mem(long w, long h, bool binary_output) -> string 6 | { 7 | return mandelbrot_to_mem(w, h, binary_output); 8 | } 9 | 10 | public static function treffynnon_mandelbrot_to_file(string filename, long w, long h, bool binary_output) -> bool 11 | { 12 | return mandelbrot_to_file(filename, w, h, binary_output); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /cli-php-zephir/build.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | if [[ "$ZPHP_HOME" == "" ]]; then 3 | echo "ZPHP_HOME environment variable must be set!" 4 | echo 'export ZPHP_HOME=/path/to/zephir' 5 | exit 1 6 | fi 7 | cd treffynnon 8 | $ZPHP_HOME/bin/zephir compile 9 | cd .. 10 | -------------------------------------------------------------------------------- /cli-php-zephir/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d 'extension=treffynnon/ext/modules/treffynnon.so' -d "zend_extension=opcache.so" -d "opcache.enable_cli=1" -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir/exec_no_opcache.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" /usr/bin/env php -n -d 'extension=treffynnon/ext/modules/treffynnon.so' -f test.php "$ARG" 11 | -------------------------------------------------------------------------------- /cli-php-zephir/test.php: -------------------------------------------------------------------------------- 1 | bool 5 | { 6 | int bit_num = 128, 7 | byte_acc = 0, 8 | iter = 50, 9 | y = 0, 10 | x = 0, 11 | i = 0; 12 | 13 | double Ci = 0, 14 | Cr = 0, 15 | Zr = 0, 16 | Zi = 0, 17 | Tr = 0, 18 | Ti = 0.0, 19 | yfac = 0, 20 | xfac = 0, 21 | iter_check = 4.0, 22 | Tr_and_Ti = 0.0; 23 | 24 | string curr_char = "", 25 | space = "", 26 | ochars = " .:-;!/>)|&IH%*#", 27 | pack_format = "c*"; 28 | 29 | if(bitmap) { 30 | fprintf(stream, "P4\n%d %d\n", w, h); 31 | } 32 | 33 | let yfac = (2.0 / h); 34 | let xfac = (2.0 / w); 35 | 36 | let space = ochars[0]; 37 | 38 | while(y < h) { 39 | let Ci = y * yfac - 1.0; 40 | 41 | let x = 0; 42 | while (x < w) { 43 | let Zr = 0; 44 | let Zi = 0; 45 | let Tr = 0; 46 | let Ti = 0.0; 47 | 48 | let Cr = x * xfac - 1.5; 49 | 50 | do { 51 | let i = 0; 52 | while (i < iter) { 53 | let Zi = 2.0 * Zr * Zi + Ci; 54 | let Zr = Tr - Ti + Cr; 55 | let Tr = Zr * Zr; 56 | let Ti = Zi * Zi; 57 | let Tr_and_Ti = Tr + Ti; 58 | // this would normally be written as if((Tr+Ti) > 4.0) 59 | // but must be done with variables as the Zephir compiler 60 | // doesn't understand how to do the comparison otherwise 61 | if (Tr_and_Ti > iter_check) { break; } 62 | let i += 1; 63 | } 64 | if (Tr_and_Ti > iter_check) { break; } 65 | let byte_acc += bit_num; 66 | } while (false); 67 | 68 | if(bitmap) { 69 | if (bit_num === 1) { 70 | fwrite(stream, pack(pack_format, byte_acc)); 71 | let bit_num = 128; 72 | let byte_acc = 0; 73 | } else { 74 | // Zephir doesn't understand bitwise operations in tandem with 75 | // assignment so we must either drop down to C in a CBLOCK to 76 | // perform the operation or break it into its constituent 77 | // parts. Otherwise it would be: 78 | // let bit_num >>= 1; 79 | let bit_num = bit_num >> 1; 80 | 81 | // the CBLOCK version would look like: 82 | // %{ 83 | // bit_num >>= 1; 84 | // }% 85 | } 86 | } else { 87 | if(i == iter) { 88 | fwrite(stream, space); 89 | } else { 90 | let curr_char = ochars[(i + 1) & 15]; 91 | fwrite(stream, curr_char); 92 | } 93 | } 94 | let x += 1; 95 | } 96 | if(bitmap) { 97 | if (bit_num !== 128) { 98 | fwrite(stream, pack(pack_format, byte_acc)); 99 | let bit_num = 128; 100 | let byte_acc = 0; 101 | } 102 | } else { 103 | fwrite(stream, "\n"); 104 | } 105 | let y += 1; 106 | } 107 | return true; 108 | } 109 | 110 | public static function treffynnon_mandelbrot_to_mem(int w, int h, bool binary_output) -> string 111 | { 112 | var stream; // it is a resource so we can use a static type here unfortunately in Zephir 113 | string file_open_type = "w+"; 114 | var ret = ""; // return values from PHP functions can only be assigned to variant variables so we can't use a static here either 115 | if(binary_output) { 116 | let file_open_type = "w+b"; 117 | } 118 | 119 | let stream = fopen("php://memory", file_open_type); 120 | // yoda conditions don't appear to be supported so false === stream below will not work 121 | // as Zephir appears to try to resolve the keyword false to a variable 122 | if(stream === false) { 123 | return ""; 124 | } 125 | 126 | self::write_mandelbrot_to_stream(w, h, stream, binary_output); 127 | rewind(stream); 128 | let ret = stream_get_contents(stream); 129 | fclose(stream); 130 | return ret; 131 | } 132 | 133 | public static function treffynnon_mandelbrot_to_file(string filename, int w, int h, bool binary_output) -> bool 134 | { 135 | var stream; // it is a resource so we can use a static type here unfortunately in Zephir 136 | string file_open_type = "w"; 137 | if(binary_output) { 138 | let file_open_type = 'wb'; 139 | } 140 | 141 | let stream = fopen(filename, file_open_type); 142 | if(stream === false) { 143 | return false; 144 | } 145 | 146 | return self::write_mandelbrot_to_stream(w, h, stream, binary_output); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | SEED=1000 4 | if [ "$1" != "" ]; then 5 | SEED="$1" 6 | fi 7 | 8 | ITERATIONS=1 9 | if [ "$2" != "" ]; then 10 | ITERATIONS="$2" 11 | fi 12 | 13 | TIMEFORMAT="" 14 | if [ "$3" != "" ]; then 15 | TIMEFORMAT="$3" 16 | fi 17 | 18 | # Function from SO answer by James Roth 19 | # http://stackoverflow.com/a/2990533/461813 20 | echoerr() { 21 | echo -ne "$@" 1>&2; 22 | } 23 | 24 | exec_dir() { 25 | SCRIPT="exec.sh" 26 | SETUP="setup.sh" 27 | 28 | if [ "" != "$3" ]; then 29 | SCRIPT="$3" 30 | fi 31 | 32 | if [ "" != "$4" ]; then 33 | SETUP="$4" 34 | fi 35 | 36 | echo " " 37 | echo "$1" 38 | cd "$2" 39 | if [[ -x "$SETUP" ]]; then 40 | # Pass in script name as argument for any required warm up 41 | ./$SETUP "$SCRIPT" 42 | fi 43 | 44 | for ((n=0;n<$ITERATIONS;n++)) 45 | do 46 | echo "Iterating" 47 | echoerr "\"$2\", \"$1\", $SEED, " 48 | ./$SCRIPT "$SEED" "$TIMEFORMAT" 49 | done 50 | if [[ -x "teardown.sh" ]]; then 51 | ./teardown.sh 52 | fi 53 | 54 | cd .. 55 | } 56 | 57 | echo " " 58 | echo "Treffynnon benchmarker" 59 | echo "^^^^^^^^^^^^^^^^^^^^^^" 60 | echo " " 61 | echo "################################" 62 | echo "# Command line benching #" 63 | echo "################################" 64 | echo " " 65 | echo " " 66 | echo "HHVM" 67 | echo "====" 68 | echo "## Extension" 69 | exec_dir "### No options" cli-hhvm-ext 70 | exec_dir "### JITed" cli-hhvm-ext exec_jitted.sh 71 | 72 | echo "## PHP userland code" 73 | exec_dir "### No options" cli-hhvm-php 74 | exec_dir "### JITed" cli-hhvm-php exec_jitted.sh 75 | 76 | echo "## HACK/PHP++/PHQ userland code" 77 | exec_dir "### No options" cli-hhvm-hack 78 | exec_dir "### JITed" cli-hhvm-hack exec_jitted.sh 79 | 80 | echo " " 81 | echo "PHP" 82 | echo "===" 83 | echo "## Extension" 84 | exec_dir "### No options" cli-php-ext exec_no_opcache.sh 85 | exec_dir "### OPcached" cli-php-ext 86 | 87 | echo "## PHP userland code" 88 | exec_dir "### No options" cli-php-php exec_no_opcache.sh 89 | exec_dir "### OPcached" cli-php-php 90 | 91 | echo "## QB compiled" 92 | exec_dir "### No options" cli-php-qb exec_no_opcache.sh 93 | exec_dir "### OPcached" cli-php-qb 94 | 95 | echo " " 96 | echo "C" 97 | echo "=" 98 | exec_dir "" cli-c 99 | 100 | echo " " 101 | echo "Zephir" 102 | echo "======" 103 | echo "## CBLOCK" 104 | exec_dir "### No options" cli-php-zephir-cblock exec_no_opcache.sh 105 | exec_dir "### OPcached" cli-php-zephir-cblock 106 | 107 | echo "## Optimizer" 108 | exec_dir "### No options" cli-php-zephir-optimizer exec_no_opcache.sh 109 | exec_dir "### OPcached" cli-php-zephir-optimizer 110 | 111 | echo "## Zephir Lang" 112 | exec_dir "### No options" cli-php-zephir exec_no_opcache.sh 113 | exec_dir "### OPcached" cli-php-zephir 114 | 115 | echo " " 116 | echo " " 117 | echo "################################" 118 | echo "# FCGI benchmarking #" 119 | echo "################################" 120 | echo " " 121 | echo " " 122 | echo "HHVM" 123 | echo "====" 124 | echo "## Extension" 125 | exec_dir "### No options" fcgi-hhvm-ext exec.sh setup_no_options.sh 126 | exec_dir "### JITed" fcgi-hhvm-ext 127 | 128 | echo "## PHP userland code" 129 | exec_dir "### No options" fcgi-hhvm-php exec.sh setup_no_options.sh 130 | exec_dir "### JITed" fcgi-hhvm-php 131 | 132 | echo "## HACK/PHP++/PHQ userland code" 133 | exec_dir "### No options" fcgi-hhvm-hack exec.sh setup_no_options.sh 134 | exec_dir "### JITed" fcgi-hhvm-hack 135 | 136 | echo " " 137 | echo "PHP" 138 | echo "===" 139 | echo "## Extension" 140 | exec_dir "### No options" fcgi-php-ext exec.sh setup_no_options.sh 141 | exec_dir "### OPcached" fcgi-php-ext 142 | 143 | echo "## PHP userland code" 144 | exec_dir "### No options" fcgi-php-php exec.sh setup_no_options.sh 145 | exec_dir "### OPcached" fcgi-php-php 146 | 147 | echo "## QB compiled" 148 | exec_dir "### No options" fcgi-php-qb exec.sh setup_no_options.sh 149 | exec_dir "### OPcached" fcgi-php-qb 150 | 151 | echo " " 152 | echo "Zephir" 153 | echo "======" 154 | echo "## CBLOCK" 155 | exec_dir "### No options" fcgi-php-zephir exec.sh setup_no_options.sh 156 | exec_dir "### OPcached" fcgi-php-zephir-cblock 157 | 158 | echo "## Optimizer" 159 | exec_dir "### No options" fcgi-php-zephir-optimizer exec.sh setup_no_options.sh 160 | exec_dir "### OPcached" fcgi-php-zephir-optimizer 161 | 162 | echo "## Zephir Lang" 163 | exec_dir "### No options" fcgi-php-zephir exec.sh setup_no_options.sh 164 | exec_dir "### OPcached" fcgi-php-zephir 165 | 166 | echo " " 167 | echo " " 168 | echo "###################################" 169 | echo "# Treffynnon exec script complete #" 170 | echo "###################################" 171 | echo " " 172 | -------------------------------------------------------------------------------- /fcgi-hhvm-ext/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" ../fcgicli/fcgicli "/tmp/treffynnon_bench.socket" "`pwd`/test.php" "$ARG" 11 | -------------------------------------------------------------------------------- /fcgi-hhvm-ext/setup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | H_CONFIG=$(readlink -f "`pwd`/../cli-hhvm-ext/config.hdf") 4 | H_EXT_PATH=$(readlink -f "`pwd`/../cli-hhvm-ext") 5 | $HPHP_HOME/hphp/hhvm/hhvm --mode server -c "$H_CONFIG" -v "DynamicExtensionPath=$H_EXT_PATH" -vServer.Type=fastcgi -vServer.FileSocket="/tmp/treffynnon_bench.socket" -vEval.Jit=1 > /dev/null 2>&1 & 6 | echo "Sleep for a bit to allow process to ready itself" 7 | sleep 5 8 | 9 | echo "Attempting to warm up the server" 10 | for ((n=0;n<15;n++)); do 11 | # Using a low number for the seed to make the warm up faster 12 | ./"$1" 100 > /dev/null 2>&1 13 | done 14 | -------------------------------------------------------------------------------- /fcgi-hhvm-ext/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | H_CONFIG=$(readlink -f "`pwd`/../cli-hhvm-ext/config.hdf") 4 | H_EXT_PATH=$(readlink -f "`pwd`/../cli-hhvm-ext") 5 | $HPHP_HOME/hphp/hhvm/hhvm --mode server -c "$H_CONFIG" -v "DynamicExtensionPath=$H_EXT_PATH" -vServer.Type=fastcgi -vServer.FileSocket="/tmp/treffynnon_bench.socket" -vEval.Jit=0 > /dev/null 2>&1 & 6 | echo "Sleep for a bit to allow process to ready itself" 7 | sleep 5 8 | 9 | echo "Attempting to warm up the server" 10 | for ((n=0;n<15;n++)); do 11 | # Using a low number for the seed to make the warm up faster 12 | ./"$1" 100 > /dev/null 2>&1 13 | done 14 | -------------------------------------------------------------------------------- /fcgi-hhvm-ext/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | rm www.pid -f -------------------------------------------------------------------------------- /fcgi-hhvm-ext/test.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 & 4 | echo "Sleep for a bit to allow process to ready itself" 5 | sleep 5 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done 12 | -------------------------------------------------------------------------------- /fcgi-hhvm-hack/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | $HPHP_HOME/hphp/hhvm/hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket="/tmp/treffynnon_bench.socket" -vEval.Jit=0 > /dev/null 2>&1 & 4 | echo "Sleep for a bit to allow process to ready itself" 5 | sleep 5 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done 12 | -------------------------------------------------------------------------------- /fcgi-hhvm-hack/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | rm www.pid -f -------------------------------------------------------------------------------- /fcgi-hhvm-hack/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 25 | $pack_format = 'c*'; 26 | 27 | for ($y = 0 ; $y < $h ; ++$y) { 28 | $Ci = $y * $yfac - 1.0; 29 | for ($x = 0 ; $x < $w ; ++$x) { 30 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 31 | $Cr = $x * $xfac - 1.5; 32 | do { 33 | for ($i = 0; $i < $iter; ++$i) { 34 | $Zi = 2.0 * $Zr * $Zi + $Ci; 35 | $Zr = $Tr - $Ti + $Cr; 36 | $Tr = $Zr * $Zr; 37 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 38 | } 39 | $byte_acc += $bit_num; 40 | } while (false); 41 | 42 | if($bitmap) { 43 | if ($bit_num === 1) { 44 | fwrite($stream, pack($pack_format, $byte_acc)); 45 | $bit_num = 128; 46 | $byte_acc = 0; 47 | } else { 48 | $bit_num >>= 1; 49 | } 50 | } else { 51 | if($i == $iter) { 52 | fwrite($stream, $ochars[0]); 53 | } else { 54 | fwrite($stream, $ochars[($i+1) & 15]); 55 | } 56 | } 57 | } 58 | if($bitmap) { 59 | if ($bit_num !== 128) { 60 | fwrite($stream, pack($pack_format, $byte_acc)); 61 | $bit_num = 128; 62 | $byte_acc = 0; 63 | } 64 | } else { 65 | fwrite($stream, "\n"); 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | function treffynnon_mandelbrot_to_file(string $filename, int $w, int $h, bool $binary_output): bool { 72 | $file_open_type = 'w'; 73 | if($binary_output) 74 | $file_open_type = 'wb'; 75 | 76 | $stream = fopen((string) $filename, $file_open_type); 77 | if(false === $stream) 78 | return false; 79 | 80 | write_mandelbrot_to_stream($w, $h, $stream, $binary_output); 81 | fclose($stream); 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_mem(int $w, int $h, bool $binary_output): string { 86 | $file_open_type = 'w+'; 87 | if($binary_output) 88 | $file_open_type = 'w+b'; 89 | 90 | $stream = fopen('php://memory', $file_open_type); 91 | if(false === $stream) 92 | return ''; 93 | 94 | write_mandelbrot_to_stream($w, $h, $stream, $binary_output); 95 | rewind($stream); 96 | $ret = stream_get_contents($stream); 97 | fclose($stream); 98 | return $ret; 99 | } 100 | 101 | echo treffynnon_mandelbrot_to_mem((int) $_GET['seed'], (int) $_GET['seed'], false); -------------------------------------------------------------------------------- /fcgi-hhvm-php/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | H_PHP_SCRIPT_PATH=$(readlink -f "`pwd`/../fcgi-php-php/test.php") 11 | /usr/bin/env time "$TIMEFORMAT" ../fcgicli/fcgicli "/tmp/treffynnon_bench.socket" "$H_PHP_SCRIPT_PATH" "$ARG" 12 | -------------------------------------------------------------------------------- /fcgi-hhvm-php/setup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | $HPHP_HOME/hphp/hhvm/hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket="/tmp/treffynnon_bench.socket" -vEval.Jit=1 > /dev/null 2>&1 & 4 | echo "Sleep for a bit to allow process to ready itself" 5 | sleep 5 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done 12 | -------------------------------------------------------------------------------- /fcgi-hhvm-php/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | $HPHP_HOME/hphp/hhvm/hhvm --mode server -vServer.Type=fastcgi -vServer.FileSocket="/tmp/treffynnon_bench.socket" -vEval.Jit=0 > /dev/null 2>&1 & 4 | echo "Sleep for a bit to allow process to ready itself" 5 | sleep 5 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done 12 | -------------------------------------------------------------------------------- /fcgi-hhvm-php/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | rm www.pid -f -------------------------------------------------------------------------------- /fcgi-hhvm-php/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 25 | $pack_format = 'c*'; 26 | 27 | for ($y = 0 ; $y < $h ; ++$y) { 28 | $Ci = $y * $yfac - 1.0; 29 | for ($x = 0 ; $x < $w ; ++$x) { 30 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 31 | $Cr = $x * $xfac - 1.5; 32 | do { 33 | for ($i = 0; $i < $iter; ++$i) { 34 | $Zi = 2.0 * $Zr * $Zi + $Ci; 35 | $Zr = $Tr - $Ti + $Cr; 36 | $Tr = $Zr * $Zr; 37 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 38 | } 39 | $byte_acc += $bit_num; 40 | } while (false); 41 | 42 | if($bitmap) { 43 | if ($bit_num === 1) { 44 | fwrite($stream, pack($pack_format, $byte_acc)); 45 | $bit_num = 128; 46 | $byte_acc = 0; 47 | } else { 48 | $bit_num >>= 1; 49 | } 50 | } else { 51 | if($i == $iter) { 52 | fwrite($stream, $ochars[0]); 53 | } else { 54 | fwrite($stream, $ochars[($i+1) & 15]); 55 | } 56 | } 57 | } 58 | if($bitmap) { 59 | if ($bit_num !== 128) { 60 | fwrite($stream, pack($pack_format, $byte_acc)); 61 | $bit_num = 128; 62 | $byte_acc = 0; 63 | } 64 | } else { 65 | fwrite($stream, "\n"); 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | function treffynnon_mandelbrot_to_file($filename, $w, $h, $binary_output) { 72 | $file_open_type = 'w'; 73 | if($binary_output) 74 | $file_open_type = 'wb'; 75 | 76 | $stream = fopen((string) $filename, $file_open_type); 77 | if(false === $stream) 78 | return false; 79 | 80 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 81 | fclose($stream); 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_mem($w, $h, $binary_output) { 86 | $file_open_type = 'w+'; 87 | if($binary_output) 88 | $file_open_type = 'w+b'; 89 | 90 | $stream = fopen('php://memory', $file_open_type); 91 | if(false === $stream) 92 | return ''; 93 | 94 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 95 | rewind($stream); 96 | $ret = stream_get_contents($stream); 97 | fclose($stream); 98 | return $ret; 99 | } 100 | 101 | echo treffynnon_mandelbrot_to_mem((int) $_GET['seed'], (int) $_GET['seed'], false); 102 | -------------------------------------------------------------------------------- /fcgi-php-ext/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" ../fcgicli/fcgicli "/tmp/treffynnon_bench.socket" "`pwd`/test.php" "$ARG" 11 | -------------------------------------------------------------------------------- /fcgi-php-ext/setup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "zend_extension=opcache.so" -d "extension=../cli-php-ext/modules/treffynnon.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-ext/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "extension=../cli-php-ext/modules/treffynnon.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-ext/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-ext/test.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-php/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-php/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-php/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 25 | $pack_format = 'c*'; 26 | 27 | for ($y = 0 ; $y < $h ; ++$y) { 28 | $Ci = $y * $yfac - 1.0; 29 | for ($x = 0 ; $x < $w ; ++$x) { 30 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 31 | $Cr = $x * $xfac - 1.5; 32 | do { 33 | for ($i = 0; $i < $iter; ++$i) { 34 | $Zi = 2.0 * $Zr * $Zi + $Ci; 35 | $Zr = $Tr - $Ti + $Cr; 36 | $Tr = $Zr * $Zr; 37 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 38 | } 39 | $byte_acc += $bit_num; 40 | } while (false); 41 | 42 | if($bitmap) { 43 | if ($bit_num === 1) { 44 | fwrite($stream, pack($pack_format, $byte_acc)); 45 | $bit_num = 128; 46 | $byte_acc = 0; 47 | } else { 48 | $bit_num >>= 1; 49 | } 50 | } else { 51 | if($i == $iter) { 52 | fwrite($stream, $ochars[0]); 53 | } else { 54 | fwrite($stream, $ochars[($i+1) & 15]); 55 | } 56 | } 57 | } 58 | if($bitmap) { 59 | if ($bit_num !== 128) { 60 | fwrite($stream, pack($pack_format, $byte_acc)); 61 | $bit_num = 128; 62 | $byte_acc = 0; 63 | } 64 | } else { 65 | fwrite($stream, "\n"); 66 | } 67 | } 68 | return true; 69 | } 70 | 71 | function treffynnon_mandelbrot_to_file($filename, $w, $h, $binary_output) { 72 | $file_open_type = 'w'; 73 | if($binary_output) 74 | $file_open_type = 'wb'; 75 | 76 | $stream = fopen((string) $filename, $file_open_type); 77 | if(false === $stream) 78 | return false; 79 | 80 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 81 | fclose($stream); 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_mem($w, $h, $binary_output) { 86 | $file_open_type = 'w+'; 87 | if($binary_output) 88 | $file_open_type = 'w+b'; 89 | 90 | $stream = fopen('php://memory', $file_open_type); 91 | if(false === $stream) 92 | return ''; 93 | 94 | write_mandelbrot_to_stream((int) $w, (int) $h, $stream, (bool) $binary_output); 95 | rewind($stream); 96 | $ret = stream_get_contents($stream); 97 | fclose($stream); 98 | return $ret; 99 | } 100 | 101 | echo treffynnon_mandelbrot_to_mem((int) $_GET['seed'], (int) $_GET['seed'], false); 102 | -------------------------------------------------------------------------------- /fcgi-php-qb/README.md: -------------------------------------------------------------------------------- 1 | QB 2 | == 3 | 4 | There are a couple of caveats with this implementation: 5 | 6 | 1. QB doesn't handle streams being passed as parameters so I am printing the output and catching it using `ob_start()` to simulate a memory stream. When I emailed Chung he said this would probably be the closest to the original algorithm I'd be able to get. 7 | 2. You can't echo the result of a PHP function from QB directly and you must assign it to a variable first hence the lines like `print $tmp = pack()`. You can print directly from QB functions though. 8 | -------------------------------------------------------------------------------- /fcgi-php-qb/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" ../fcgicli/fcgicli "/tmp/treffynnon_bench.socket" "`pwd`/test.php" "$ARG" 11 | -------------------------------------------------------------------------------- /fcgi-php-qb/setup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "extension=qb.so" -d "zend_extension=opcache.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-qb/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "extension=qb.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-qb/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-qb/test.php: -------------------------------------------------------------------------------- 1 | )|&IH%*#'; 40 | 41 | for ($y = 0 ; $y < $h ; ++$y) { 42 | $Ci = $y * $yfac - 1.0; 43 | for ($x = 0 ; $x < $w ; ++$x) { 44 | $Zr = 0; $Zi = 0; $Tr = 0; $Ti = 0.0; 45 | $Cr = $x * $xfac - 1.5; 46 | do { 47 | for ($i = 0; $i < $iter; ++$i) { 48 | $Zi = 2.0 * $Zr * $Zi + $Ci; 49 | $Zr = $Tr - $Ti + $Cr; 50 | $Tr = $Zr * $Zr; 51 | if (($Tr+($Ti = $Zi * $Zi)) > 4.0) break 2; 52 | } 53 | $byte_acc += $bit_num; 54 | } while (false); 55 | 56 | if($bitmap) { 57 | if ($bit_num === 1) { 58 | echo $byte_acc; 59 | $bit_num = 128; 60 | $byte_acc = 0; 61 | } else { 62 | $bit_num >>= 1; 63 | } 64 | } else { 65 | if($i == $iter) { 66 | echo $ochars[0]; 67 | } else { 68 | echo $ochars[($i+1) & 15]; 69 | } 70 | } 71 | } 72 | if($bitmap) { 73 | if ($bit_num !== 128) { 74 | echo $byte_acc; 75 | $bit_num = 128; 76 | $byte_acc = 0; 77 | } 78 | } else { 79 | echo "\n"; 80 | } 81 | } 82 | return true; 83 | } 84 | 85 | function treffynnon_mandelbrot_to_file($filename, $w, $h, $binary_output) { 86 | $file_open_type = 'w'; 87 | if($binary_output) 88 | $file_open_type = 'wb'; 89 | 90 | $stream = fopen((string) $filename, $file_open_type); 91 | if(false === $stream) 92 | return false; 93 | 94 | ob_start(); 95 | write_mandelbrot_to_stream((int) $w, (int) $h, (bool) $binary_output); 96 | fwrite($stream, ob_get_clean()); 97 | return true; 98 | } 99 | 100 | function treffynnon_mandelbrot_to_mem($w, $h, $binary_output) { 101 | ob_start(); 102 | write_mandelbrot_to_stream((int) $w, (int) $h, (bool) $binary_output); 103 | return ob_get_clean(); 104 | } 105 | 106 | echo treffynnon_mandelbrot_to_mem((int) $_GET['seed'], (int) $_GET['seed'], false); 107 | -------------------------------------------------------------------------------- /fcgi-php-zephir-cblock/exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | ARG=1000 3 | TIMEFORMAT="-v" 4 | if [ "$1" != "" ]; then 5 | ARG="$1" 6 | fi 7 | if [ "$2" != "" ]; then 8 | TIMEFORMAT="--format=$2" 9 | fi 10 | /usr/bin/env time "$TIMEFORMAT" ../fcgicli/fcgicli "/tmp/treffynnon_bench.socket" "`pwd`/test.php" "$ARG" 11 | -------------------------------------------------------------------------------- /fcgi-php-zephir-cblock/setup.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "zend_extension=opcache.so" -d "extension=../cli-php-zephir-cblock/treffynnoncblock/ext/modules/treffynnoncblock.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir-cblock/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "extension=../cli-php-zephir-cblock/treffynnoncblock/ext/modules/treffynnoncblock.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir-cblock/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-zephir-cblock/test.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir-optimizer/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d "extension=../cli-php-zephir-optimizer/treffynnonoptimizer/ext/modules/treffynnonoptimizer.so" -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir-optimizer/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-zephir-optimizer/test.php: -------------------------------------------------------------------------------- 1 | /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir/setup_no_options.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | echo "Starting FCGI process" 3 | php-cgi -n -d 'extension=../cli-php-zephir/treffynnon/ext/modules/treffynnon.so' -b /tmp/treffynnon_bench.socket & 4 | echo "Sleep for a second to allow process to ready itself" 5 | sleep 1 6 | 7 | echo "Attempting to warm up the server" 8 | for ((n=0;n<15;n++)); do 9 | # Using a low number for the seed to make the warm up faster 10 | ./"$1" 100 > /dev/null 2>&1 11 | done -------------------------------------------------------------------------------- /fcgi-php-zephir/teardown.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | pkill -9 -f /tmp/treffynnon_bench.socket 3 | rm /tmp/treffynnon_bench.socket -f 4 | -------------------------------------------------------------------------------- /fcgi-php-zephir/test.php: -------------------------------------------------------------------------------- 1 | {{ chart_title }} 2 |
3 | 8 | -------------------------------------------------------------------------------- /graph_index_template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HHVM vs Zephir vs PHP · Simon Holywell - Web developer in Brighton 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 109 | 110 | 111 |

HHVM vs Zephir vs PHP

112 |

These charts so the speed with which a benchmarking script ran the various 113 | PHP runtimes. For more information please see my 114 | related 115 | blog post and the 116 | relevant 117 | GitHub repository.

118 |

A quick guide to the terms used:

119 |
120 |
Iterations
121 |
Number of times the script is executed.
122 |
Seed
123 |
The size of the Mandelbrot set to create. The higher the seed the 124 | greater the work involved.
125 |
126 | {{ graphs }} 127 |

Copyright © 2003 - 2014 Simon Holywell. All rights reserved.

128 | 129 | 130 | -------------------------------------------------------------------------------- /reporting_collect_csv_reports.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | OUTPUT="results.csv" 4 | SEED=1000 5 | ITERATIONS=10 6 | if [ "$1" != "" ]; then 7 | SEED="$1" 8 | fi 9 | if [ "$2" != "" ]; then 10 | ITERATIONS="$2" 11 | fi 12 | if [ "$3" != "" ]; then 13 | OUTPUT="$3" 14 | fi 15 | 16 | # Print CSV headers out 17 | CSV_HEADERS=' 18 | 19 | Dir, 20 | Title, 21 | Seed, 22 | Time: Elapsed real time (in [hours:]minutes:seconds), 23 | Time: Elapsed real time (in seconds) (Not in tcsh), 24 | Time: Total number of CPU-seconds that the process spent in kernel mode, 25 | Time: Total number of CPU-seconds that the process spent in user mode, 26 | "Percentage of the CPU that this job got, computed as (%U + %S) / %E", 27 | "Mem: Maximum resident set size of the process during its lifetime, in Kbytes", 28 | "Mem: Average resident set size of the process, in Kbytes (Not in tcsh)", 29 | "Mem: Average total (data+stack+text) memory use of the process, in Kbytes", 30 | "Mem: Average size of the process unshared data area, in Kbytes", 31 | "Mem: Average size of the process unshared stack space, in Kbytes (Not in tcsh.)", 32 | "Mem: Average size of the process shared text space, in Kbytes", 33 | "Mem: System page size, in bytes. This is a per-system constant, but varies between systems (Not in tcsh.)", 34 | Mem: Number of major page faults that occurred while the process was running. These are faults where the page has to be read in from disk, 35 | "Mem: Number of minor, or recoverable, page faults. These are faults for pages that are not valid but which have not yet been claimed by other virtual pages. Thus the data in the page is still valid but the system tables must be updated.", 36 | Mem: Number of times the process was swapped out of main memory, 37 | Mem: Number of times the process was context-switched involuntarily (because the time slice expired), 38 | "Mem: Number of waits: times that the program was context-switched voluntarily, for instance while waiting for an I/O operation to complete", 39 | I/O: Number of file system inputs by the process, 40 | I/O: Number of file system outputs by the process, 41 | I/O: Number of socket messages received by the process, 42 | I/O: Number of socket messages sent by the process, 43 | I/O: Number of signals delivered to the process, 44 | I/O: Name and command-line arguments of the command being timed (Not in tcsh.), 45 | I/O: Exit status of the command (Not in tcsh.) 46 | 47 | ' 48 | 49 | # Strip new lines from the headers 50 | CSV_HEADERS=`echo "$CSV_HEADERS" | tr -d '\n'` 51 | 52 | echo "$CSV_HEADERS" > "$OUTPUT" 53 | 54 | # See: http://linux.die.net/man/1/time 55 | TIMEFORMAT='%E, %e, %S, %U, %P, %M, %t, %K, %D, %p, %X, %Z, %F, %R, %W, %c, %w, %I, %O, %r, %s, %k, "%C", %x' 56 | 57 | # Strip spaces from the format string to reduce filesize 58 | TIMEFORMAT=`echo "$TIMEFORMAT" | tr -d ' '` 59 | echo "Seed: $SEED" 60 | echo "Iterations: $ITERATIONS" 61 | ./exec.sh "$SEED" "$ITERATIONS" "$TIMEFORMAT" > /dev/null 2>> "$OUTPUT" -------------------------------------------------------------------------------- /reporting_exec.sh: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env bash 2 | 3 | iITERATIONS=20 4 | 5 | if [ "$1" != "" ]; then 6 | iITERATIONS="$1" 7 | fi 8 | 9 | iSEEDS=(100 200 1000 2000 5000) 10 | 11 | for iSEED in ${iSEEDS[*]}; do 12 | OUTPUT="results_${iITERATIONS}x${iSEED}.csv" 13 | echo "$OUTPUT" 14 | if [ ! -e "$OUTPUT" ]; then 15 | echo "./reporting_collect_csv_reports.sh $iSEED $iITERATIONS $OUTPUT" 16 | ./reporting_collect_csv_reports.sh "$iSEED" $iITERATIONS "$OUTPUT" 17 | fi 18 | done 19 | 20 | for file in results_*; do /usr/bin/env php -n -f reporting_parse_and_compile_csv.php "$file"; done 21 | 22 | PARSED_FILES="" 23 | for file in parsed_*; do PARSED_FILES="$PARSED_FILES $file"; done 24 | /usr/bin/env php -n -f reporting_generate_charts.php "$file"; -------------------------------------------------------------------------------- /reporting_generate_charts.php: -------------------------------------------------------------------------------- 1 | $records) { 35 | if($lang === 'Header') { 36 | $output[$lang] = $records; 37 | continue; 38 | } 39 | $num_records = count($records); 40 | for($i = 0; $i < $columns; $i++) { 41 | $column = array_column($records, $i); 42 | if(preg_match('/[a-z]+/i', $column[0])) { 43 | $output[$lang][$i] = ucwords(trim(str_replace( 44 | array('#', '-', 'php php', 'hhvm', 'php'), 45 | array('', ' ', 'PHP', 'HHVM', 'PHP'), 46 | $column[0] 47 | ))); 48 | } else { 49 | $output[$lang][$i] = array_sum($column) / $num_records; 50 | } 51 | } 52 | } 53 | unset($column, $tmp); 54 | 55 | if(($fh = fopen($out_filename, 'w')) !== false) { 56 | foreach($output as $line) { 57 | foreach($line as $key => $field) { 58 | if(is_string($field)) { 59 | $line[$key] = '"' . $field . '"'; 60 | } 61 | } 62 | fwrite($fh, implode(',', $line) . "\n", 2000); 63 | } 64 | } 65 | fclose($fh); 66 | 67 | echo "Complete.\n"; 68 | echo "Exported to: " . ((realpath($out_filename)) ?: "Error writing file.") . "\n"; 69 | 70 | 71 | /** 72 | * This file is part of the array_column library 73 | * 74 | * For the full copyright and license information, please view the LICENSE 75 | * file that was distributed with this source code. 76 | * 77 | * @copyright Copyright (c) 2013 Ben Ramsey 78 | * @license http://opensource.org/licenses/MIT MIT 79 | */ 80 | 81 | if (!function_exists('array_column')) { 82 | 83 | /** 84 | * Returns the values from a single column of the input array, identified by 85 | * the $columnKey. 86 | * 87 | * Optionally, you may provide an $indexKey to index the values in the returned 88 | * array by the values from the $indexKey column in the input array. 89 | * 90 | * @param array $input A multi-dimensional array (record set) from which to pull 91 | * a column of values. 92 | * @param mixed $columnKey The column of values to return. This value may be the 93 | * integer key of the column you wish to retrieve, or it 94 | * may be the string key name for an associative array. 95 | * @param mixed $indexKey (Optional.) The column to use as the index/keys for 96 | * the returned array. This value may be the integer key 97 | * of the column, or it may be the string key name. 98 | * @return array 99 | */ 100 | function array_column($input = null, $columnKey = null, $indexKey = null) 101 | { 102 | // Using func_get_args() in order to check for proper number of 103 | // parameters and trigger errors exactly as the built-in array_column() 104 | // does in PHP 5.5. 105 | $argc = func_num_args(); 106 | $params = func_get_args(); 107 | 108 | if ($argc < 2) { 109 | trigger_error("array_column() expects at least 2 parameters, {$argc} given", E_USER_WARNING); 110 | return null; 111 | } 112 | 113 | if (!is_array($params[0])) { 114 | trigger_error('array_column() expects parameter 1 to be array, ' . gettype($params[0]) . ' given', E_USER_WARNING); 115 | return null; 116 | } 117 | 118 | if (!is_int($params[1]) 119 | && !is_float($params[1]) 120 | && !is_string($params[1]) 121 | && $params[1] !== null 122 | && !(is_object($params[1]) && method_exists($params[1], '__toString')) 123 | ) { 124 | trigger_error('array_column(): The column key should be either a string or an integer', E_USER_WARNING); 125 | return false; 126 | } 127 | 128 | if (isset($params[2]) 129 | && !is_int($params[2]) 130 | && !is_float($params[2]) 131 | && !is_string($params[2]) 132 | && !(is_object($params[2]) && method_exists($params[2], '__toString')) 133 | ) { 134 | trigger_error('array_column(): The index key should be either a string or an integer', E_USER_WARNING); 135 | return false; 136 | } 137 | 138 | $paramsInput = $params[0]; 139 | $paramsColumnKey = ($params[1] !== null) ? (string) $params[1] : null; 140 | 141 | $paramsIndexKey = null; 142 | if (isset($params[2])) { 143 | if (is_float($params[2]) || is_int($params[2])) { 144 | $paramsIndexKey = (int) $params[2]; 145 | } else { 146 | $paramsIndexKey = (string) $params[2]; 147 | } 148 | } 149 | 150 | $resultArray = array(); 151 | 152 | foreach ($paramsInput as $row) { 153 | 154 | $key = $value = null; 155 | $keySet = $valueSet = false; 156 | 157 | if ($paramsIndexKey !== null && array_key_exists($paramsIndexKey, $row)) { 158 | $keySet = true; 159 | $key = (string) $row[$paramsIndexKey]; 160 | } 161 | 162 | if ($paramsColumnKey === null) { 163 | $valueSet = true; 164 | $value = $row; 165 | } elseif (is_array($row) && array_key_exists($paramsColumnKey, $row)) { 166 | $valueSet = true; 167 | $value = $row[$paramsColumnKey]; 168 | } 169 | 170 | if ($valueSet) { 171 | if ($keySet) { 172 | $resultArray[$key] = $value; 173 | } else { 174 | $resultArray[] = $value; 175 | } 176 | } 177 | 178 | } 179 | 180 | return $resultArray; 181 | } 182 | 183 | } 184 | --------------------------------------------------------------------------------