├── .htaccess ├── .user.ini ├── CHANGELOG.md ├── LICENSE ├── README.en.md ├── README.md ├── UUID.php ├── bench.php ├── browser.png ├── common.inc ├── compression-brotli.inc ├── compression-bz2.inc ├── compression-lz4.inc ├── compression-snappy.inc ├── compression-zlib.inc ├── igbinary.inc ├── intl.inc ├── kv-apcu.inc ├── kv-memcache.inc ├── kv-memory.inc ├── kv-redis.inc ├── kv-shmop.inc ├── kv-sqlite3-devshm-file.inc ├── kv-sqlite3-generic-file.inc ├── kv-sqlite3-memory-file.inc ├── kv-xcache.inc ├── kvstorage-apcu.inc ├── kvstorage-mem.inc ├── kvstorage-memcache.inc ├── kvstorage-redis.inc ├── kvstorage-shmop.inc ├── kvstorage-sqlite3.inc ├── kvstorage-xcache.inc ├── memcache-conn.ini ├── memcache.inc ├── mod-ctype-isdigit.inc ├── mod-gd-empty-avif.inc ├── mod-gd-empty-gif.inc ├── mod-gd-empty-jpg.inc ├── mod-gd-empty-png.inc ├── mod-gd-empty-webp.inc ├── mod-iconv.inc ├── mod-session.inc ├── mod-sodium.inc ├── mod-uuid.inc ├── msgpack.inc ├── php-options.php ├── php-uuid.inc ├── php5.inc ├── php7.inc ├── php8.inc ├── redis-conn.ini ├── redis.inc ├── sqlite3.inc └── test.xml /.htaccess: -------------------------------------------------------------------------------- 1 | # Need mod_env mod_rewrite mod_php458 2 | #https://stackoverflow.com/a/49031283/29314471 3 | 4 | SetEnv PHP_IS_ENABLED yes 5 | 6 | 7 | SetEnv PHP_IS_ENABLED yes 8 | 9 | 10 | SetEnv PHP_IS_ENABLED yes 11 | 12 | 13 | SetEnv PHP_IS_ENABLED yes 14 | 15 | 16 | php_flag display_errors 0 17 | php_flag implicit_flush 1 18 | 19 | php_flag opcache.enable 0 20 | php_flag xcache.cacher 0 21 | php_flag apc.enable 0 22 | 23 | # still - xdebug slow things 24 | php_flag xdebug.default_enable 0 25 | php_flag xdebug.show_exception_trace 0 26 | php_flag xdebug.remote_autostart 0 27 | php_flag xdebug.remote_enable 0 28 | php_value xdebug.mode off 29 | 30 | php_value output_bufering 0 31 | php_value max_execution_time 600 32 | php_value memory_limit 130M 33 | php_value mbstring.internal_encoding UTF-8 34 | php_value mbstring.func_overload 0 35 | 36 | php_value date.timezone "Europe/Moscow" 37 | -------------------------------------------------------------------------------- /.user.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | display_errors = 0 3 | implicit_flush = 1 4 | 5 | opcache.enable = 0 6 | opcache.enable_cli = 0 7 | 8 | xcache.cacher = 0 9 | 10 | apc.enable = 0 11 | apc.enable_cli = 0 12 | 13 | ; still - xdebug slow things 14 | xdebug.default_enable = 0 15 | xdebug.show_exception_trace = 0 16 | xdebug.remote_autostart = 0 17 | xdebug.remote_enable = 0 18 | xdebug.mode = off 19 | 20 | output_bufering = 0 21 | max_execution_time = 600 22 | error_log = "" 23 | memory_limit = 130M 24 | mbstring.internal_encoding = UTF-8 25 | mbstring.func_overload = 0 26 | 27 | date.timezone = Europe/Moscow 28 | 29 | open_basedir = "" 30 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # ChangeLog 2 | 3 | @ 2025-06-07, v1.0.65 4 | 5 | * Added simple test for session 6 | * Added simple test for iconv 7 | 8 | @ 2025-06-06, v1.0.64 9 | 10 | * Added simple tests for sodium 11 | * Added simple test for ctype 12 | 13 | @ 2025-06-04, v1.0.63 14 | 15 | * Added simple gd tests saving various formats of images: gif, png, jpg, webp, avif 16 | 17 | @ 2025-06-04, v1.0.62 18 | 19 | * Added simple key-value tests: sqlite3 20 | 21 | @ 2025-06-02, v1.0.61 22 | 23 | * Added simple key-value tests:memory and xcache, apcu, shmop, memcache, redis 24 | * Test selected-run by pattern now not exact name 25 | 26 | @ 2025-05-30, v1.0.60 27 | 28 | * Added ability to skip tests by name pattern 29 | 30 | @ 2025-05-29, v1.0.59 31 | 32 | * Added support of module uuid 33 | 34 | @ 2025-03-20, v1.0.58 35 | 36 | * Добавлена поддержка php 8.3 и 8.4 37 | * Добавлена поддержка отдельного модуля zlib 38 | * Добавлена поддержка сжатия snappy 39 | 40 | @ 2023-09-22, v1.0.57 41 | 42 | * Добавлены тесты gd & imagick - ктобыстрее рисует простой qrcode 43 | 44 | @ 2023-09-14, v1.0.56 45 | 46 | * Добавлены тесты методов сжатия: zlib, bz2, lz4, zstd, brotli 47 | 48 | @ 2023-09-14, v1.0.55 49 | 50 | * Добавлены тесты msgpack 51 | 52 | @ 2023-09-14, v1.0.54 53 | 54 | * Добавлены тесты igbinary 55 | 56 | @ 2023-06-05, v1.0.52.1 57 | 58 | * Исправлен вывод даты звершения работы скрипта - выравнивание даты 59 | 60 | @ 2023-05-11, v1.0.52 61 | 62 | * Вывод названия сервера, даты-времени завершения работы, 63 | * обновление вывода в формате JSON, machine 64 | 65 | @ 2023-02-17, v1.0.51 66 | 67 | * Добавили поддержку php-8.2 68 | 69 | @ 2022-05-04, v1.0.50 70 | 71 | * Быстрое исправление кода - переместил получение версии PHP выше 72 | 73 | @ 2022-05-04, v1.0.49 74 | 75 | * Добавлен вывод информации и сообщений в цветном режиме 76 | 77 | @ 2022-05-04, v1.0.48 78 | 79 | * Переделан порядок инициализации переменных из командной строки 80 | * Добавлен вывод в машино-читаемом формате, без лишних данных, без преобразования формата чисел 81 | * Добавлен вывод в JSON-формате, без лишних данных, без преобразования формата чисел 82 | 83 | @ 2022-05-03, v1.0.47 84 | 85 | * Улучшен вывод предупреждения про xdebug 86 | * Если включен xdebug - не падаем, а пробуем провести тесты с ним 87 | * Добавлены еще параметры для xdebug в .htaccess и .user.ini 88 | 89 | @ 2022-05-02, v1.0.46 90 | 91 | * Добавлен простой тест - генерация phpinfo. 92 | * Упоминание mbstring.func_overload перенесено ниже, в параметры php. 93 | 94 | @ 2021-12-19, v1.0.45 95 | 96 | * Добавлен режим отладки, когда выводится больше информации о внутренних действиях. 97 | Плюс включается вывод всех-всех ошибок. 98 | * Убран вызов команды `taskset`. Если нужно - в консоли можно вызвать самому. 99 | * Добавлены примеры в README для вызова разных команд. 100 | * Немного переделан расчет пределов памяти для скрипта, добавлен выход если памяти совсем мало. 101 | * Выводим еще больше скрытого текста для браузера для сброса буферов. 102 | * Лимит памяти понижен до 130Мб. Но надо учитывать, что php выделяет память блоками по 2^x Мб. 103 | И чем больше ему надо - тем больше он запросит. 104 | * Не выходим, если mbstring.func_overload не равно 0, даем посмотреть на результат. 105 | * Добавлено нахождение xCache, APC, eaccelerator. 106 | * Поправлено нахождение полного использования памяти в тестах с массивами. 107 | И добавлено принудительное освобождение памяти при завершении теста. 108 | * Добавлен обход ошибок ограничений, вызванных установленным параметром `open_basedir`. 109 | * Изменены названия нескольких тестов, в соответствии с тем, что тестируется. 110 | 111 | @ 2021-12-06, v1.0.44 112 | 113 | * Тестирование классов DateTime, работает начиная с php-5.3 114 | * Тестирование классов модуля intl, 115 | - intlCalendar работает начиная с php-5.5, 116 | - остальные классы - с php-5.3, или php-5.2 + модуль из pecl 117 | * Обновлены кол-ва итераций в тестах и времена выполнения 118 | * Добавлена опция для отключения использования `taskset` для привязки к одному ядру процессора 119 | 120 | @ 2021-11-26, v1.0.43 121 | 122 | * Добавлена поддержка php-8.1 123 | * Исправлен тест 14-array-unset - php-8.1 ругался на несуществующие индексы 124 | * Обновлены кол-ва итераций в тестах и времена выполнения 125 | * Исправлена проверка на загрузку xdebug 126 | 127 | @ 2021-11-21, v1.0.42 128 | 129 | * Добавлены тесты xml обработчиков: simplexml, dom 130 | * Добавлен вывод версий библиотек, если известны 131 | * Обновлены кол-ва итераций в тестах и времена выполнения 132 | 133 | @ 2021-10-19, v1.0.41 134 | 135 | * Добавлена проверка на наличие `common.inc` в одном каталоге с `bench.php` 136 | 137 | @ 2021-10-19, v1.0.40 138 | 139 | * Отказываемся работать, если включен opcache 140 | * Чуть более правильные расчеты при ограничениях по времени выполнения 141 | * Выводим больше текста при работе в браузере, чтобы буферы nginx/proxy быстрее сбрасывались 142 | * Обновлен вывод системной информации 143 | 144 | @ 2021-06-21, v1.0.39 145 | 146 | * Отказываемся работать, если включен mbstring.func_overload 147 | 148 | @ 2021-06-10, v1.0.38 149 | 150 | * Разделение вывода на cli (text) и html 151 | * Делаем больше flush - быстрее появится текст в браузере 152 | 153 | @ 2020-11-26, v1.0.37 154 | 155 | * ChangeLog вынесен в отдельный файл 156 | * Убрали функцию pi из math теста - она не принимает аргумент в php-8 157 | * Тесты модуля xmlrpc были удалены из-за отсутствия модуля в php-8 158 | * Поддержка php-8 159 | 160 | @ 2020-02-22, v1.0.36 161 | 162 | * Добавлен вывод кол-ва доступных ядрер. 163 | 164 | @ 2019-12-20, v1.0.35 165 | 166 | * Добавлена поддержка php-7.4. 167 | 168 | @ 2019-05-10, v1.0.34 169 | 170 | * Поправлено определение модели CPU и частота в MHz для процессоров ARM. 171 | 172 | @ 2019-05-01, v1.0.33 173 | 174 | * Новый тест для классов - доступ в данным через публичные свойства, 175 | геттеры-сеттеры, магические методы. 176 | * Детектирование xdebug - ругаемся и выходим 177 | * Вывод информации об операционной системе, если доступно 178 | 179 | @ 2018-08-08, v1.0.32 180 | 181 | * Были неправы - stdClass есть в php-4 тоже 182 | 183 | @ 2018-08-08, v1.0.31 184 | 185 | * Исправили тесты с различной сериализацией - объекты есть только в php-5+ 186 | 187 | @ 2018-08-08, v1.0.30 188 | 189 | * Добавили в некоторых тестах сериализации к объекту тестирования поля с разными типами данных 190 | * Поправили тесты xmlrpc - в php-7.2+libxmlrpc-epi проблемы со строками с html-тегами 191 | 192 | @ 2018-08-08, v1.0.29 193 | 194 | * Добавили параметр -L для вывода списка тестов 195 | * Добавили параметр -T для запуска только конкретных тестов 196 | * Добавили параметр -I для вывода только информации о системе без запуска тестов 197 | 198 | @ 2018-08-08, v1.0.28.1 199 | 200 | * Поправили вывод секунд - нужно на один символ больше места 201 | * Немного поменяли вывод информации 202 | 203 | @ 2018-08-07, v1.0.28 204 | 205 | * Поправили пересчет размеров в единицы байт, при 0 происходила мат.ошибка 206 | 207 | @ 2018-08-07, v1.0.27 208 | 209 | * Добавили новый параметр, отключающий пересчет ограничений по времени для тестов 210 | 211 | @ 2018-08-07, v1.0.26 212 | 213 | * Добавили вывод общего кол-ва операций в секунду, и операций в секунду на МГц 214 | * Добавили вывод включенных необходимых модулей 215 | 216 | @ 2018-08-06, v1.0.25 217 | 218 | * Добавили тестирование xmlrpc (xml) 219 | * Добавили вывод предупреждений, если не все необходимые модули php установлены 220 | 221 | @ 2017-09-04, v1.0.24 222 | 223 | * Поправили пересчет времени тестов, если процессор Atom или ARM 224 | 225 | @ 2017-09-04, v1.0.23 226 | 227 | * Обновили тест на работу с try-catch блоком - отдельные под-тесты: без блока, блок без exception, и с exception 228 | * Добавили пересчет времени тестов, если процессор Atom или ARM - они реально медленные 229 | 230 | @ 2017-06-03, v1.0.22 231 | 232 | * Добавили тесты производительности новых операций в php-7 233 | * Вынесли инициализацию переменных за счетчики времени в тестах 234 | * Обновили счетчики времени для разных версий php 235 | * Тест array_range - насколько сильно влияет на следующий тест array_unset 236 | 237 | @ 2017-05-25, v1.0.21 238 | 239 | * Добавили тесты производительности конвертации простых типов: 240 | `string => (int)`, `string => intval()` 241 | 242 | @ 2017-05-19, v1.0.20 243 | 244 | * Поддержва длинных опций ком.строки только в php-5.3+ 245 | * Добавили проверку форматирования строк - производительность сбора `''` строки с числами, 246 | или `""` строки с форматированием чисел внутри. 247 | * Очищаем данные после теста строк, массивов - меньше занятой памяти 248 | 249 | @ 2017-05-19, v1.0.19 250 | 251 | * Попытка принудительно включить небуферизированный вывод 252 | * Спец-заголовок для nginx для отключения буферизации 253 | * Возможность загрузить основные тесты без файла php5.inc с тестом try/Exception/catch 254 | 255 | @ 2017-05-18, v1.0.18 256 | 257 | * Проверка на совместимую версию php 258 | * Получение значений для настроек php - `max_execution_time` и `memory_limit` - из 259 | GET / getenv / getopt. 260 | 261 | @ 2017-05-18, v1.0.17 262 | 263 | * Попытка укладываться в max_execution_time 264 | Т.к. зависимость от hardware не линейная - много hack-ов. 265 | Может не всегда срабатывать. 266 | 267 | @ 2017-05-18, v1.0.16 268 | 269 | * Сделали поиск доступных алгоритмов хеширования для crypt() 270 | * По-умолчанию считаем, что доступен для всех MD5 271 | 272 | @ 2017-05-17, v1.0.15 273 | 274 | * Поправили работу скрипта с php-7.x - больше ограничений по памяти 275 | * Добавили вывод используемой памяти (@ryr) 276 | 277 | @ 2017-05-06, v1.0.14 278 | 279 | * Изменили работу скрипта, если доступно памяти менее 256Мб 280 | 281 | @ 2017-05-06, v1.0.13 282 | 283 | * Поправили немного code-style (@ryr) 284 | * Добавили больше данных в тесты сериализации 285 | 286 | @ 2017-04-21, v1.0.12 287 | 288 | * Правильная конвертация значений в единицы SI. 289 | * Считаем операции в секунду на МГц. 290 | * Обновил вывод - добавил заголовок столбцам 291 | 292 | @ 2017-04-20, v1.0.11 293 | 294 | * Нагружаем процессор, чтобы определить MHz только если разница между 295 | значениями 'cpu MHz' и 'bogomips/2' большая. 296 | 297 | @ 2017-04-20, v1.0.10 298 | 299 | * Тесты массивов теперь всегда включены, они больше не съедают много памяти 300 | * Добавлено определение CPU на Linux-системах, добавлен вывод операций на МГц 301 | * В выводе uname осталена только необходимая для сравнения информация 302 | * Обновлен README 303 | 304 | @ 2017-04-06, v1.0.9 305 | 306 | * Поправлен подсчет операций в секунду для теста массивов 307 | 308 | @ 2017-04-06, v1.0.8 309 | 310 | * Тесты, которых нет в php-4.4 вынесены в отдельный подключаемый файл 311 | 312 | @ 2017-04-06, v1.0.7 313 | 314 | * Изменены названия функций-тестов для сортировки перед запуском 315 | * Обновлено форматирование вывода результатов тестов 316 | * Добавлены и обновлены тесты: 317 | - обращение к определенныи и неопределенным переменным/ключам массива 318 | - исключения (exceptions) 319 | - к хешированию добавлен тест crypt 320 | - тест массивов разбит на три уровня - время выполнения то же, памяти занимает меньше 321 | 322 | @ 2015-07-16, v1.0.6 323 | 324 | * Добавлены тесты: preg & serialize 325 | 326 | @ 2015-07-02, v1.0.5 327 | 328 | * Добавлен тест простейшего копирования строк 329 | 330 | @ 2015-07-02, v1.0.4 331 | 332 | * Добавлено увеличение лимита по памяти и времени выполнения 333 | 334 | @ 2015-07-02, v1.0.3 335 | 336 | * Исправлено определение доступных функций, сделан пропуск тестов для них 337 | 338 | @ 2015-07-02, v1.0.2 339 | 340 | * Добавлено еще больше функций, теперь требуется наличие mbstring и json модулей 341 | * Потребление памяти увеличено из-за тестирования массивов - нужно более 1Гб 342 | 343 | @ 2015-07-01, v1.0.1 344 | 345 | * Добавлен вывод потребления памяти 346 | * Добавлены новые функции, увеличен размер проверочной строки 347 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2015-2019 RuSoft 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.en.md: -------------------------------------------------------------------------------- 1 | # A simple PHP script to test speed 2 | 3 | Works with all versions of PHP: from 4.3 to 8.4 4 | 5 | ## Dependencies 6 | 7 | Required modules for full php testing: 8 | 9 | - pcre 10 | - mbstring 11 | - json 12 | - dom 13 | - simplexml 14 | - intl 15 | - optional: 16 | - gd 17 | - imagick 18 | - zlib 19 | - bz2 20 | - brotli 21 | - lz4 22 | - snappy 23 | - zstd 24 | - igbinary 25 | - msgpack 26 | - uuid 27 | - memcache 28 | - redis 29 | - sqlite3 30 | 31 | Usually they are already installed or "compiled" in php. 32 | 33 | How to check it: 34 | 35 | - in console: `php -m` 36 | - or via function `phpinfo()` output 37 | 38 | ### Modules affecting test results 39 | 40 | - xdebug - can slow down most of the tests by half, and some related to error handling - by 10! 41 | - opcache - can cache the execution of functions, or throw out "not affecting execution" pieces of code 42 | - other opcode accelerators: xcache, apc, eaccelerator, etc. 43 | 44 | ## Startup 45 | 46 | ### 0. Files 47 | 48 | You need to put these files in one directory: `bench.php`, `common.inc`, `php5.inc`, `php7.inc`, `php8.inc`, `igbinary.inc`, `intl.inc`, `msgpack.inc`, `compression-*.inc`, `php-options.php`, `php-gd-imagick-common.inc`, `php-gd.inc`, `php-imagick.inc`, `test.xml`, `UUID.php`. 49 | 50 | ### 1. Through the console 51 | 52 | Command: 53 | ``` 54 | Usage: bench.php [-h|--help] [-x|--debug] [-C|--dont-use-colors] [-J|--print-json] [-M|--print-machine] [-d|--dont-recalc] [-D|--dumb-test-print] [-L|--list-tests] [-I|--system-info] [-S|--do-not-task-set] [-m|--memory-limit=130] [-t|--time-limit=600] [-T|--run-test=name1 ...] 55 | 56 | -h|--help - print this help and exit 57 | -x|--debug - enable debug mode, raise output level 58 | -C|--dont-use-colors - disable printing html-span or color sequences for capable terminal: xterm, *-color, *-256color. And not in JSON/machine mode. 59 | -J|--print-json - enable printing only in JSON format, useful for automated tests. disables print-machine. 60 | -M|--print-machine - enable printing only in machine parsable format, useful for automated tests. disables print-json. 61 | -d|--dont-recalc - do not recalculate test times / operations count even if memory of execution time limits are low 62 | -D|--dumb-test-print - print dumb test time, for debug purpose 63 | -L|--list-tests - output list of available tests and exit 64 | -I|--system-info - output system info but do not run tests and exit 65 | -m|--memory-limit - set memory_limit value in Mb, defaults to 130 (Mb) 66 | -t|--time-limit - set max_execution_time value in seconds, defaults to 600 (sec) 67 | -T|--run-test - run selected test, test names from --list-tests output, can be defined multiple times 68 | -S|--skip-test - skip selected test, test names pattern from --list-tests output, can be defined multiple times 69 | ``` 70 | Example: `php bench.php -m=64 -t=30` 71 | 72 | The second option for passing values ​​for parameters is environment variables: 73 | ``` 74 | env PHP_MEMORY_LIMIT=64 PHP_TIME_LIMIT=30 php bench.php 75 | ``` 76 | 77 | Available variables: 78 | 79 | - PHP_TIME_LIMIT= 80 | - PHP_DEBUG_MODE=0/1 81 | - DONT_USE_COLORS=0/1 82 | - PRINT_JSON=0/1 83 | - PRINT_MACHINE=0/1 84 | - PHP_MEMORY_LIMIT=<Мб> 85 | - DONT_RECALCULATE_LIMITS=0/1 86 | - LIST_TESTS=0/1 87 | - SYSTEM_INFO=0/1 88 | - RUN_TESTS=test1,test2,... 89 | - SKIP_TESTS=test1,test2,... 90 | 91 | #### Extras (Utilities in Linux) 92 | 93 | - You can set the priority of a process with the command `nice` - от -20 (high) до 19 (low). For example, priority 5: `nice -5 php bench.php`. Read `man nice`. 94 | - You can set I/O priority with the command `ionice`. Example: `ionice -c3 php bench.php`. Read `man ionice`. 95 | - You can bind script execution to the processor core with the command `taskset`. Example: `taskset -c -p 0 php bench.php`. Read `man taskset`. 96 | - Вы можете комбинировать команды: `taskset -c -p 0 nice -10 ionice -c3 php bench.php`. 97 | 98 | ### 2. Through web servers (apache + php) 99 | 100 | Just put in any php directory of the site available for execution, for example, in the root. 101 | 102 | Then the script can be called with parameters, as from the console: 103 | `curl http://www.example.com/bench.php?memory_limit=64&time_limit=30` 104 | or via browser. 105 | 106 | Available options: 107 | 108 | - time_limit=Секунды 109 | - debug_mode=0/1 110 | - dont_use_colors=0/1 111 | - print_json=0/1 112 | - print_machine=0/1 113 | - memory_limit=Мб 114 | - dont_recalculate_limits=0/1 115 | - list_tests=0/1 116 | - system_info=0/1 117 | - run_tests=test1,test2,... 118 | - skip_tests=test1,test2,... 119 | 120 | ### Accounting for hosting options 121 | 122 | On many hostings, the `memory_limit` and `max_execution_time` parameters can be hardcoded. 123 | 124 | In this case, the script will not be able to set the parameter values passed to it, at least not above the limits. 125 | 126 | The script execution time will be recalculated according to the smallest resulting values. 127 | 128 | ### Other platforms 129 | 130 | For example, on Raspberry Pi 2B, 3B and other similar boards, the execution speed is so slow, 131 | that you have to specify the `-d -t 3600` options to make all the tests pass. 132 | 133 | This applies to all ARM, MIPS, etc. As well as old AMD and Intel processors like Celeron, Atom, Duron, etc. 134 | 135 | ## Example script output 136 | 137 | ### Generic format 138 | 139 | ``` 140 | <<< WARNING >>> You need to disable Xdebug extension! It greatly slow things down! And mess with PHP internals. 141 | <<< WARNING >>> Execution time limit not droppped to '600' seconds! 142 | Script will have only '0' seconds to run. 143 | <<< WARNING >>> Extension 'xdebug' loaded! It will affect results and slow things greatly! Even if not enabled! 144 | <<< WARNING >>> Set xdebug.mode in php.ini / VHost or FPM config / php_admin_value or via cmd '-dxdebug.mode=off' option of PHP executable. 145 | 146 | ------------------------------------------------------------------------------------------- 147 | | PHP BENCHMARK SCRIPT | 148 | ------------------------------------------------------------------------------------------- 149 | Start : 2022-05-03 18:22:49 150 | Server : Linux/5.4.0-104-lowlatency x86_64 151 | Platform : Linux 152 | System : Ubuntu 18.04.6 LTS 153 | CPU : 154 | model : Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz 155 | cores : 4 156 | available : 4 157 | MHz : 3600 MHz 158 | Benchmark version : 1.0.57 159 | PHP version : 7.4.29-SergeyD/6.1 160 | PHP time limit : 0 sec 161 | Setup time limit : 600 sec 162 | PHP memory limit : 128M 163 | Setup memory limit : 130 Mb 164 | Crypt hash algo : MD5 165 | Loaded modules 166 | -useful-> 167 | json : yes 168 | mbstring : yes; 169 | pcre : yes; version: 10.39 2021-10-29 170 | simplexml : yes; libxml version: 2.9.4 171 | dom : yes 172 | intl : yes; icu version: 66.1 173 | -optional-> 174 | gd : yes: version: 2.2.5 175 | imagick : yes: version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org 176 | -alternative-> 177 | igbinary : yes 178 | msgpack : yes 179 | jsond : no 180 | jsond as json >> : no 181 | -compression-> 182 | zlib : yes 183 | bz2 : yes 184 | lz4 : yes 185 | zstd : yes 186 | brotli : yes 187 | -affecting-> 188 | opcache : yes; enabled: 0 189 | xcache : no; enabled: 0 190 | apc : no; enabled: 0 191 | eaccelerator : no; enabled: 0 192 | xdebug : yes, enabled: 1, mode: 'develop' 193 | PHP parameters 194 | open_basedir : is empty? yes 195 | mb.func_overload : 0 196 | ------------------------------------------------------------------------------------------- 197 | TEST NAME : SECONDS | OP/SEC | OP/SEC/MHz | MEMORY 198 | ------------------------------------------------------------------------------------------- 199 | 01_math : 2.958 sec | 676.22 kOp/s | 178.48 Ops/MHz | 4 Mb 200 | 02_string_concat : 1.683 sec | 14.86 MOp/s | 3.92 kOps/MHz | 89.83 Mb 201 | 03_1_string_number_concat : 1.544 sec | 3.24 MOp/s | 854.83 Ops/MHz | 4 Mb 202 | 03_2_string_number_format : 1.348 sec | 3.71 MOp/s | 979.33 Ops/MHz | 4 Mb 203 | 04_string_simple_functions : 1.320 sec | 984.64 kOp/s | 259.88 Ops/MHz | 4 Mb 204 | 05_string_multibyte : 1.061 sec | 122.47 kOp/s | 32.32 Ops/MHz | 4 Mb 205 | 06_string_manipulation : 2.397 sec | 542.37 kOp/s | 143.15 Ops/MHz | 4 Mb 206 | 07_regex : 2.035 sec | 638.84 kOp/s | 168.61 Ops/MHz | 4 Mb 207 | 08_1_hashing : 2.030 sec | 640.31 kOp/s | 169.00 Ops/MHz | 4 Mb 208 | 08_2_crypt : 8.698 sec | 1.15 kOp/s | 0.30 Ops/MHz | 4 Mb 209 | 09_json_encode : 2.322 sec | 559.91 kOp/s | 147.78 Ops/MHz | 4 Mb 210 | 10_json_decode : 3.556 sec | 365.54 kOp/s | 96.48 Ops/MHz | 4 Mb 211 | 11_igb_serialize : 2.894 sec | 449.19 kOp/s | 124.78 Ops/MHz | 3 Mb 212 | 11_msgpack_pack : 2.054 sec | 633.01 kOp/s | 175.84 Ops/MHz | 3 Mb 213 | 11_serialize : 3.727 sec | 348.79 kOp/s | 96.89 Ops/MHz | 3 Mb 214 | 12_igb_unserialize : 2.123 sec | 612.31 kOp/s | 170.09 Ops/MHz | 3 Mb 215 | 12_msgpack_unpack : 2.657 sec | 489.30 kOp/s | 135.92 Ops/MHz | 3 Mb 216 | 12_unserialize : 3.226 sec | 402.91 kOp/s | 111.92 Ops/MHz | 3 Mb 217 | 11_serialize : 1.551 sec | 838.30 kOp/s | 221.25 Ops/MHz | 4 Mb 218 | 12_unserialize : 1.677 sec | 774.97 kOp/s | 204.54 Ops/MHz | 4 Mb 219 | 13_array_fill : 3.740 sec | 24.07 MOp/s | 6.35 kOps/MHz | 24 Mb 220 | 14_array_range : 2.007 sec | 74.74 kOp/s | 19.73 Ops/MHz | 24 Mb 221 | 14_array_unset : 2.833 sec | 31.77 MOp/s | 8.38 kOps/MHz | 24 Mb 222 | 15_clean_loops : 1.342 sec | 298.14 MOp/s | 78.69 kOps/MHz | 4 Mb 223 | 16_loop_ifelse : 1.992 sec | 50.20 MOp/s | 13.25 kOps/MHz | 4 Mb 224 | 17_loop_ternary : 3.057 sec | 32.71 MOp/s | 8.63 kOps/MHz | 4 Mb 225 | 18_1_loop_defined_access : 1.017 sec | 49.15 MOp/s | 12.97 kOps/MHz | 4 Mb 226 | 18_2_loop_undefined_access : 4.729 sec | 10.57 MOp/s | 2.79 kOps/MHz | 4 Mb 227 | 19_type_functions : 1.152 sec | 3.47 MOp/s | 916.65 Ops/MHz | 4 Mb 228 | 20_type_casting : 1.178 sec | 3.39 MOp/s | 895.86 Ops/MHz | 4 Mb 229 | 21_0_loop_exception_none : 0.204 sec | 48.94 MOp/s | 12.92 kOps/MHz | 4 Mb 230 | 21_1_loop_exception_try : 0.212 sec | 47.21 MOp/s | 12.46 kOps/MHz | 4 Mb 231 | 21_2_loop_exception_catch : 3.214 sec | 3.11 MOp/s | 821.23 Ops/MHz | 4 Mb 232 | 22_loop_null_op : 1.266 sec | 47.41 MOp/s | 12.51 kOps/MHz | 4 Mb 233 | 23_loop_spaceship_op : 1.202 sec | 49.93 MOp/s | 13.18 kOps/MHz | 4 Mb 234 | 26_1_class_public_properties : 0.133 sec | 75.10 MOp/s | 19.82 kOps/MHz | 4 Mb 235 | 26_2_class_getter_setter : 0.425 sec | 23.54 MOp/s | 6.21 kOps/MHz | 4 Mb 236 | 26_3_class_magic_methods : 1.189 sec | 8.41 MOp/s | 2.22 kOps/MHz | 4 Mb 237 | 27_simplexml : 4.121 sec | 12.13 kOp/s | 3.20 Ops/MHz | 4 Mb 238 | 28_domxml : 4.228 sec | 11.83 kOp/s | 3.12 Ops/MHz | 4 Mb 239 | 29_datetime : 0.571 sec | 875.87 kOp/s | 231.17 Ops/MHz | 4 Mb 240 | 30_intl_number_format : 0.826 sec | 24.22 kOp/s | 6.39 Ops/MHz | 4 Mb 241 | 31_intl_message_format : 4.236 sec | 47.22 kOp/s | 12.46 Ops/MHz | 4 Mb 242 | 32_intl_calendar : 0.844 sec | 355.34 kOp/s | 93.79 Ops/MHz | 4 Mb 243 | 33_phpinfo_generate : 1.440 sec | 6.95 kOp/s | 1.83 Ops/MHz | 4 Mb 244 | 34_gd_qrcode : 0.923 sec | 1.08 kOp/s | 0.30 Ops/MHz | 4 Mb 245 | 35_imagick_qrcode : 2.839 sec | 352.18 Op/s | 0.10 Ops/MHz | 4 Mb 246 | 36_brotli_compress : 5.012 sec | 199.50 kOp/s | 51.47 Ops/MHz | 3 Mb 247 | 36_bzip2_compress : 22.065 sec | 22.66 kOp/s | 5.85 Ops/MHz | 3 Mb 248 | 36_gzip_compress : 52.977 sec | 94.38 kOp/s | 24.35 Ops/MHz | 3 Mb 249 | 36_lz4_compress : 0.378 sec | 1.32 MOp/s | 341.52 Ops/MHz | 3 Mb 250 | 36_zlib_compress : 51.905 sec | 96.33 kOp/s | 24.85 Ops/MHz | 3 Mb 251 | 36_zstd_compress : 27.937 sec | 178.98 kOp/s | 46.17 Ops/MHz | 3 Mb 252 | ------------------------------------------------------------------------------------------- 253 | Total time: : 81.337 sec | 13.73 MOp/s | 3.62 kOps/MHz | 254 | Current PHP memory usage: : 4 Mb 255 | Peak PHP memory usage: : 86.58 Mb 256 | ``` 257 | 258 | ### JSON-format 259 | 260 | Command: `php74 -derror_log= -dxdebug.mode=off bench.php -T 01_math -T 33_phpinfo_generate -J` 261 | ``` 262 | { 263 | "php_benchmark_script": "1.0.51", 264 | "start": "2022-05-03 22:11:19", 265 | "server": "Linux/5.4.0-104-lowlatency x86_64", 266 | "system": "Ubuntu 18.04.6 LTS", 267 | "php_version": "7.4.29-SergeyD/6.1", 268 | "results": { 269 | "columns": [ "test_name", "seconds", "op\/sec", "op\/sec\/MHz", "memory" ], 270 | "rows": [ 271 | [ "01_math", 3.4119508266449, 586174.91916397, 162.82636643444, 4194304 ], 272 | [ "33_phpinfo_generate", 3.6402199268341, 2747.0867697538, 0.76307965826494, 4194304 ], 273 | null 274 | ] 275 | }, 276 | "total": { "seconds": 7.052170753479, "op\/sec":285018.62338039, "op\/sec\/MHz":79.171839827885 }, 277 | "messages_count": 0, 278 | "end":true 279 | } 280 | ``` 281 | 282 | ### Machine-parsable format 283 | 284 | Command: `php74 -derror_log= -dxdebug.mode=off bench.php -T 01_math -T 33_phpinfo_generate -M` 285 | ``` 286 | PHP_BENCHMARK_SCRIPT: 1.0.51 287 | START: 2022-05-03 22:11:52 288 | SERVER: Linux/5.4.0-104-lowlatency x86_64 289 | SYSTEM: Ubuntu 18.04.6 LTS 290 | PHP_VERSION: 7.4.29-SergeyD/6.1 291 | TEST_NAME: SECONDS, OP/SEC, OP/SEC/MHz, MEMORY 292 | 01_math: 3.3808300495148, 591570.70030392, 164.32519452887, 4194304 293 | 33_phpinfo_generate: 3.6759581565857, 2720.3791702809, 0.75566088063359, 4194304 294 | TOTAL: 7.0567882061005, 284832.12777484, 79.120035493011 295 | ``` 296 | 297 | ### In web-browser 298 | 299 | Link like: http://sergey.home.lan/bench/bench.php?system_info=1 300 | ![System information](browser.png "System information") 301 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Простой скрипт проверки быстродействия PHP 2 | 3 | Работает со всеми версиями ПХП: от 4.3 до 8.4 4 | 5 | ## Зависимости 6 | 7 | Необходимые модули для полного тестирования php: 8 | 9 | - pcre 10 | - mbstring 11 | - json 12 | - dom 13 | - simplexml 14 | - intl 15 | - optional: 16 | - gd 17 | - imagick 18 | - brotli 19 | - zlib 20 | - bz2 21 | - zstd 22 | - lz4 23 | - snappy 24 | - igbinary 25 | - msgpack 26 | - uuid 27 | - memcache 28 | - redis 29 | - sqlite3 30 | 31 | Обычно они уже установлены или "вкомпилированны" в php. 32 | 33 | Проверить наличие: 34 | 35 | - в консоли `php -m` 36 | - или через вывод функции `phpinfo()` 37 | 38 | ### Модули, влияющие на результаты тестов 39 | 40 | - xdebug - может замедлить работу большей части тестов в два раза, а некоторых, связанных с обработкой ошибок - в 10! 41 | - opcache - может закешировать выполнение функций, или выкинуть "не влияющие на выполнение" куски кода 42 | - другие ускорители оп-кода: xcache, apc, eaccelerator и т.п. 43 | 44 | ## Запуск 45 | 46 | ### 0. Файлы 47 | 48 | Нужно положить в один каталог файлы: `bench.php`, `common.inc`, `php5.inc`, `php7.inc`, `php8.inc`, `igbinary.inc`, `intl.inc` `msgpack.inc`, `compression-*.inc`, `php-options.php`, `php-gd-imagick-common.inc`, `php-gd.inc`, `php-imagick.inc`, `test.xml`, `UUID.php`. 49 | 50 | ### 1. Через консоль 51 | 52 | Команда: 53 | ``` 54 | Usage: bench.php [-h|--help] [-x|--debug] [-C|--dont-use-colors] [-J|--print-json] [-M|--print-machine] [-d|--dont-recalc] [-D|--dumb-test-print] [-L|--list-tests] [-I|--system-info] [-S|--do-not-task-set] [-m|--memory-limit=130] [-t|--time-limit=600] [-T|--run-test=name1 ...] 55 | 56 | -h|--help - print this help and exit 57 | -x|--debug - enable debug mode, raise output level 58 | -C|--dont-use-colors - disable printing html-span or color sequences for capable terminal: xterm, *-color, *-256color. And not in JSON/machine mode. 59 | -J|--print-json - enable printing only in JSON format, useful for automated tests. disables print-machine. 60 | -M|--print-machine - enable printing only in machine parsable format, useful for automated tests. disables print-json. 61 | -d|--dont-recalc - do not recalculate test times / operations count even if memory of execution time limits are low 62 | -D|--dumb-test-print - print dumb test time, for debug purpose 63 | -L|--list-tests - output list of available tests and exit 64 | -I|--system-info - output system info but do not run tests and exit 65 | -m|--memory-limit - set memory_limit value in Mb, defaults to 130 (Mb) 66 | -t|--time-limit - set max_execution_time value in seconds, defaults to 600 (sec) 67 | -T|--run-test - run selected test, test names from --list-tests output, can be defined multiple times 68 | -S|--skip-test - skip selected test, test names pattern from --list-tests output, can be defined multiple times 69 | ``` 70 | Например: `php bench.php -m=64 -t=30` 71 | 72 | Второй вариант передачи значений для параметров - переменные окружения: 73 | ``` 74 | env PHP_MEMORY_LIMIT=64 PHP_TIME_LIMIT=30 php bench.php 75 | ``` 76 | 77 | Доступные переменные: 78 | 79 | - PHP_TIME_LIMIT=<Секунды> 80 | - PHP_DEBUG_MODE=0/1 81 | - DONT_USE_COLORS=0/1 82 | - PRINT_JSON=0/1 83 | - PRINT_MACHINE=0/1 84 | - PHP_MEMORY_LIMIT=<Мб> 85 | - DONT_RECALCULATE_LIMITS=0/1 86 | - LIST_TESTS=0/1 87 | - SYSTEM_INFO=0/1 88 | - RUN_TESTS=test1,test2,... 89 | - SKIP_TESTS=test1,test2,... 90 | 91 | #### Дополнительно (утилиты в Linux) 92 | 93 | - Вы можете установить приоритет процесса с помощью команды `nice` - от -20 (высокий) до 19 (низкий). Пример, приоритет 5: `nice -5 php bench.php`. Смотрите `man nice`. 94 | - Вы можете установить приоритет ввода-вывода с помощью команды `ionice`. Пример: `ionice -c3 php bench.php`. Смотрите `man ionice`. 95 | - Вы можете привязать выполнение скрипта к ядру процессора с помощью команды `taskset`. Пример: `taskset -c -p 0 php bench.php`. Смотрите `man taskset`. 96 | - Вы можете комбинировать команды: `taskset -c -p 0 nice -10 ionice -c3 php bench.php`. 97 | 98 | ### 2. Через веб-сервера (apache + php) 99 | 100 | Просто положите в любую доступную для выполнения php директорию сайта, например в корень. 101 | 102 | Потом скрипт можно будет вызывать с параметрами, как из консоли: 103 | `curl http://www.example.com/bench.php?memory_limit=64&time_limit=30` 104 | или через браузер. 105 | 106 | Доступные параметры: 107 | 108 | - time_limit=Секунды 109 | - debug_mode=0/1 110 | - dont_use_colors=0/1 111 | - print_json=0/1 112 | - print_machine=0/1 113 | - memory_limit=Мб 114 | - dont_recalculate_limits=0/1 115 | - list_tests=0/1 116 | - system_info=0/1 117 | - run_tests=test1,test2,... 118 | - skip_tests=test1,test2,... 119 | 120 | ### Учет параметров хостинга 121 | 122 | На многих хостингах параметры `memory_limit` и `max_execution_time` могут быть жестко зафиксированы. 123 | 124 | В этом случае скрипт не сможет установить переданные в него значения параметров, 125 | по крайней мере не выше лимитов. 126 | 127 | Пересчет времени выполнения скрипта будет произведен по наименьшим результирующим значениям. 128 | 129 | ### Другие платформы 130 | 131 | Например, на Raspberry Pi 2B, 3B и других подобных платах скорость выполнения настолько медленная, 132 | что приходится указвать параметры `-d -t 3600`, чтобы прошли все тесты. 133 | 134 | Это касается всех ARM, MIPS и т.п. А так же старых процессоров AMD и Intel, как Celeron, Atom, Duron и т.п. 135 | 136 | ## Пример вывода скрипта 137 | 138 | ### Обычный режим 139 | 140 | ``` 141 | <<< WARNING >>> You need to disable Xdebug extension! It greatly slow things down! And mess with PHP internals. 142 | <<< WARNING >>> Execution time limit not droppped to '600' seconds! 143 | Script will have only '0' seconds to run. 144 | <<< WARNING >>> Extension 'xdebug' loaded! It will affect results and slow things greatly! Even if not enabled! 145 | <<< WARNING >>> Set xdebug.mode in php.ini / VHost or FPM config / php_admin_value or via cmd '-dxdebug.mode=off' option of PHP executable. 146 | 147 | ------------------------------------------------------------------------------------------- 148 | | PHP BENCHMARK SCRIPT | 149 | ------------------------------------------------------------------------------------------- 150 | Start : 2022-05-03 18:22:49 151 | Server : Linux/5.4.0-104-lowlatency x86_64 152 | Platform : Linux 153 | System : Ubuntu 18.04.6 LTS 154 | CPU : 155 | model : Intel(R) Core(TM) i5-6600K CPU @ 3.50GHz 156 | cores : 4 157 | available : 4 158 | MHz : 3600 MHz 159 | Benchmark version : 1.0.57 160 | PHP version : 7.4.29-SergeyD/6.1 161 | PHP time limit : 0 sec 162 | Setup time limit : 600 sec 163 | PHP memory limit : 128M 164 | Setup memory limit : 130 Mb 165 | Crypt hash algo : MD5 166 | Loaded modules 167 | -useful-> 168 | json : yes 169 | mbstring : yes; 170 | pcre : yes; version: 10.39 2021-10-29 171 | simplexml : yes; libxml version: 2.9.4 172 | dom : yes 173 | intl : yes; icu version: 66.1 174 | -optional-> 175 | gd : yes: version: 2.2.5 176 | imagick : yes: version: ImageMagick 6.9.7-4 Q16 x86_64 20170114 http://www.imagemagick.org 177 | -alternative-> 178 | igbinary : yes 179 | msgpack : yes 180 | jsond : no 181 | jsond as json >> : no 182 | -compression-> 183 | zlib : yes 184 | bz2 : yes 185 | lz4 : yes 186 | zstd : yes 187 | brotli : yes 188 | -affecting-> 189 | opcache : yes; enabled: 0 190 | xcache : no; enabled: 0 191 | apc : no; enabled: 0 192 | eaccelerator : no; enabled: 0 193 | xdebug : yes, enabled: 1, mode: 'develop' 194 | PHP parameters 195 | open_basedir : is empty? yes 196 | mb.func_overload : 0 197 | ------------------------------------------------------------------------------------------- 198 | TEST NAME : SECONDS | OP/SEC | OP/SEC/MHz | MEMORY 199 | ------------------------------------------------------------------------------------------- 200 | 01_math : 2.958 sec | 676.22 kOp/s | 178.48 Ops/MHz | 4 Mb 201 | 02_string_concat : 1.683 sec | 14.86 MOp/s | 3.92 kOps/MHz | 89.83 Mb 202 | 03_1_string_number_concat : 1.544 sec | 3.24 MOp/s | 854.83 Ops/MHz | 4 Mb 203 | 03_2_string_number_format : 1.348 sec | 3.71 MOp/s | 979.33 Ops/MHz | 4 Mb 204 | 04_string_simple_functions : 1.320 sec | 984.64 kOp/s | 259.88 Ops/MHz | 4 Mb 205 | 05_string_multibyte : 1.061 sec | 122.47 kOp/s | 32.32 Ops/MHz | 4 Mb 206 | 06_string_manipulation : 2.397 sec | 542.37 kOp/s | 143.15 Ops/MHz | 4 Mb 207 | 07_regex : 2.035 sec | 638.84 kOp/s | 168.61 Ops/MHz | 4 Mb 208 | 08_1_hashing : 2.030 sec | 640.31 kOp/s | 169.00 Ops/MHz | 4 Mb 209 | 08_2_crypt : 8.698 sec | 1.15 kOp/s | 0.30 Ops/MHz | 4 Mb 210 | 09_json_encode : 2.322 sec | 559.91 kOp/s | 147.78 Ops/MHz | 4 Mb 211 | 10_json_decode : 3.556 sec | 365.54 kOp/s | 96.48 Ops/MHz | 4 Mb 212 | 11_igb_serialize : 2.894 sec | 449.19 kOp/s | 124.78 Ops/MHz | 3 Mb 213 | 11_msgpack_pack : 2.054 sec | 633.01 kOp/s | 175.84 Ops/MHz | 3 Mb 214 | 11_serialize : 3.727 sec | 348.79 kOp/s | 96.89 Ops/MHz | 3 Mb 215 | 12_igb_unserialize : 2.123 sec | 612.31 kOp/s | 170.09 Ops/MHz | 3 Mb 216 | 12_msgpack_unpack : 2.657 sec | 489.30 kOp/s | 135.92 Ops/MHz | 3 Mb 217 | 12_unserialize : 3.226 sec | 402.91 kOp/s | 111.92 Ops/MHz | 3 Mb 218 | 11_serialize : 1.551 sec | 838.30 kOp/s | 221.25 Ops/MHz | 4 Mb 219 | 12_unserialize : 1.677 sec | 774.97 kOp/s | 204.54 Ops/MHz | 4 Mb 220 | 13_array_fill : 3.740 sec | 24.07 MOp/s | 6.35 kOps/MHz | 24 Mb 221 | 14_array_range : 2.007 sec | 74.74 kOp/s | 19.73 Ops/MHz | 24 Mb 222 | 14_array_unset : 2.833 sec | 31.77 MOp/s | 8.38 kOps/MHz | 24 Mb 223 | 15_clean_loops : 1.342 sec | 298.14 MOp/s | 78.69 kOps/MHz | 4 Mb 224 | 16_loop_ifelse : 1.992 sec | 50.20 MOp/s | 13.25 kOps/MHz | 4 Mb 225 | 17_loop_ternary : 3.057 sec | 32.71 MOp/s | 8.63 kOps/MHz | 4 Mb 226 | 18_1_loop_defined_access : 1.017 sec | 49.15 MOp/s | 12.97 kOps/MHz | 4 Mb 227 | 18_2_loop_undefined_access : 4.729 sec | 10.57 MOp/s | 2.79 kOps/MHz | 4 Mb 228 | 19_type_functions : 1.152 sec | 3.47 MOp/s | 916.65 Ops/MHz | 4 Mb 229 | 20_type_casting : 1.178 sec | 3.39 MOp/s | 895.86 Ops/MHz | 4 Mb 230 | 21_0_loop_exception_none : 0.204 sec | 48.94 MOp/s | 12.92 kOps/MHz | 4 Mb 231 | 21_1_loop_exception_try : 0.212 sec | 47.21 MOp/s | 12.46 kOps/MHz | 4 Mb 232 | 21_2_loop_exception_catch : 3.214 sec | 3.11 MOp/s | 821.23 Ops/MHz | 4 Mb 233 | 22_loop_null_op : 1.266 sec | 47.41 MOp/s | 12.51 kOps/MHz | 4 Mb 234 | 23_loop_spaceship_op : 1.202 sec | 49.93 MOp/s | 13.18 kOps/MHz | 4 Mb 235 | 26_1_class_public_properties : 0.133 sec | 75.10 MOp/s | 19.82 kOps/MHz | 4 Mb 236 | 26_2_class_getter_setter : 0.425 sec | 23.54 MOp/s | 6.21 kOps/MHz | 4 Mb 237 | 26_3_class_magic_methods : 1.189 sec | 8.41 MOp/s | 2.22 kOps/MHz | 4 Mb 238 | 27_simplexml : 4.121 sec | 12.13 kOp/s | 3.20 Ops/MHz | 4 Mb 239 | 28_domxml : 4.228 sec | 11.83 kOp/s | 3.12 Ops/MHz | 4 Mb 240 | 29_datetime : 0.571 sec | 875.87 kOp/s | 231.17 Ops/MHz | 4 Mb 241 | 30_intl_number_format : 0.826 sec | 24.22 kOp/s | 6.39 Ops/MHz | 4 Mb 242 | 31_intl_message_format : 4.236 sec | 47.22 kOp/s | 12.46 Ops/MHz | 4 Mb 243 | 32_intl_calendar : 0.844 sec | 355.34 kOp/s | 93.79 Ops/MHz | 4 Mb 244 | 33_phpinfo_generate : 1.440 sec | 6.95 kOp/s | 1.83 Ops/MHz | 4 Mb 245 | 34_gd_qrcode : 0.923 sec | 1.08 kOp/s | 0.30 Ops/MHz | 4 Mb 246 | 35_imagick_qrcode : 2.839 sec | 352.18 Op/s | 0.10 Ops/MHz | 4 Mb 247 | 36_brotli_compress : 5.012 sec | 199.50 kOp/s | 51.47 Ops/MHz | 3 Mb 248 | 36_bzip2_compress : 22.065 sec | 22.66 kOp/s | 5.85 Ops/MHz | 3 Mb 249 | 36_gzip_compress : 52.977 sec | 94.38 kOp/s | 24.35 Ops/MHz | 3 Mb 250 | 36_lz4_compress : 0.378 sec | 1.32 MOp/s | 341.52 Ops/MHz | 3 Mb 251 | 36_zlib_compress : 51.905 sec | 96.33 kOp/s | 24.85 Ops/MHz | 3 Mb 252 | 36_zstd_compress : 27.937 sec | 178.98 kOp/s | 46.17 Ops/MHz | 3 Mb 253 | ------------------------------------------------------------------------------------------- 254 | Total time: : 81.337 sec | 13.73 MOp/s | 3.62 kOps/MHz | 255 | Current PHP memory usage: : 4 Mb 256 | Peak PHP memory usage: : 86.58 Mb 257 | ``` 258 | 259 | ### JSON-формат 260 | 261 | Команда: `php74 -derror_log= -dxdebug.mode=off bench.php -T 01_math -T 33_phpinfo_generate -J` 262 | ``` 263 | { 264 | "php_benchmark_script": "1.0.48-dev", 265 | "start": "2022-05-03 22:11:19", 266 | "server": "Linux/5.4.0-104-lowlatency x86_64", 267 | "system": "Ubuntu 18.04.6 LTS", 268 | "php_version": "7.4.29-SergeyD/6.1", 269 | "results": { 270 | "columns": [ "test_name", "seconds", "op\/sec", "op\/sec\/MHz", "memory" ], 271 | "rows": [ 272 | [ "01_math", 3.4119508266449, 586174.91916397, 162.82636643444, 4194304 ], 273 | [ "33_phpinfo_generate", 3.6402199268341, 2747.0867697538, 0.76307965826494, 4194304 ], 274 | null 275 | ] 276 | }, 277 | "total": { "seconds": 7.052170753479, "op\/sec":285018.62338039, "op\/sec\/MHz":79.171839827885 }, 278 | "messages_count": 0, 279 | "end":true 280 | } 281 | ``` 282 | 283 | ### Машино-читаемый формат 284 | 285 | Команда: `php74 -derror_log= -dxdebug.mode=off bench.php -T 01_math -T 33_phpinfo_generate -M` 286 | ``` 287 | PHP_BENCHMARK_SCRIPT: 1.0.48-dev 288 | START: 2022-05-03 22:11:52 289 | SERVER: Linux/5.4.0-104-lowlatency x86_64 290 | SYSTEM: Ubuntu 18.04.6 LTS 291 | PHP_VERSION: 7.4.29-SergeyD/6.1 292 | TEST_NAME: SECONDS, OP/SEC, OP/SEC/MHz, MEMORY 293 | 01_math: 3.3808300495148, 591570.70030392, 164.32519452887, 4194304 294 | 33_phpinfo_generate: 3.6759581565857, 2720.3791702809, 0.75566088063359, 4194304 295 | TOTAL: 7.0567882061005, 284832.12777484, 79.120035493011 296 | ``` 297 | 298 | ### В браузере 299 | 300 | Ссылка вида: http://sergey.home.lan/bench/bench.php?system_info=1 301 | ![Информация о системе](browser.png "Информация о системе") 302 | -------------------------------------------------------------------------------- /UUID.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /bench.php: -------------------------------------------------------------------------------- 1 | '; 27 | 28 | // Used in hacks/fixes checks 29 | $phpversion = explode('.', PHP_VERSION); 30 | 31 | $messagesCnt = 0; 32 | $rawValues4json = false; 33 | $totalOps = 0; 34 | 35 | if (php_sapi_name() == 'cli') { 36 | // Terminal color sequence 37 | $colorReset = "\033[0m"; 38 | $colorRed = "\033[31m"; 39 | $colorGreen = "\033[32m"; 40 | $colorYellow = "\033[33m"; 41 | $colorGray = "\033[30m"; 42 | 43 | $term = getenv('TERM'); 44 | if (in_array($term, array('xterm', 'urxvt', 'linux', 'screen'))) { 45 | // Concrete terms, or limited terms 46 | // pass 47 | } else if (strpos($term, '-color') !== false) { 48 | // Special string 49 | // pass 50 | } else if (strpos($term, '-256color') !== false) { 51 | // Special string 52 | // pass 53 | } else { 54 | // not pass 55 | $colorReset = ''; 56 | $colorRed = ''; 57 | $colorGreen = ''; 58 | $colorYellow = ''; 59 | $colorGray = ''; 60 | } 61 | } else { 62 | // Html colors 63 | $colorReset = ''; // just closing tag 64 | $colorRed = ''; 65 | $colorGreen = ''; 66 | $colorYellow = ''; 67 | $colorGray = ''; 68 | } 69 | 70 | /** ------------------------------- Main Defaults ------------------------------- */ 71 | 72 | $has_igb = "{$colorYellow}no{$colorReset}"; 73 | if (extension_loaded('igbinary')) { 74 | $has_igb = "{$colorGreen}yes{$colorReset}"; 75 | @include("igbinary.inc"); 76 | } 77 | 78 | $has_msg = "{$colorYellow}no{$colorReset}"; 79 | if (extension_loaded('msgpack')) { 80 | $has_msg = "{$colorGreen}yes{$colorReset}"; 81 | @include("msgpack.inc"); 82 | } 83 | 84 | if (extension_loaded('zstd')) { 85 | @include_once("compression-zstd.inc"); 86 | } 87 | if (extension_loaded('lz4')) { 88 | @include_once("compression-lz4.inc"); 89 | } 90 | if (extension_loaded('brotli')) { 91 | @include_once("compression-brotli.inc"); 92 | } 93 | if (extension_loaded('snappy')) { 94 | @include_once("compression-snappy.inc"); 95 | } 96 | if (extension_loaded('bz2')) { 97 | @include_once("compression-bz2.inc"); 98 | } 99 | if (extension_loaded('zlib')) { 100 | @include_once("compression-zlib.inc"); 101 | } 102 | if (extension_loaded('intl')) { 103 | @include_once("intl.inc"); 104 | } 105 | if (extension_loaded('ctype')) { 106 | @include_once("mod-ctype-isdigit.inc"); 107 | } 108 | if (extension_loaded('iconv')) { 109 | @include_once("mod-iconv.inc"); 110 | } 111 | if (extension_loaded('session')) { 112 | @include_once("mod-session.inc"); 113 | } 114 | if (file_exists('UUID.php') && PHP_VERSION >= '5.0.0') { 115 | @include_once("php-uuid.inc"); 116 | } 117 | if ( PHP_VERSION >= '5.0.0') { 118 | 119 | if (file_exists('kvstorage-mem.inc')) { 120 | @include_once("kv-memory.inc"); 121 | } 122 | if (file_exists('kvstorage-xcache.inc') && extension_loaded('xCache')) { 123 | @include_once("kv-xcache.inc"); 124 | } 125 | if (file_exists('kvstorage-apcu.inc') && extension_loaded('apcu')) { 126 | @include_once("kv-apcu.inc"); 127 | } 128 | if (file_exists('kvstorage-shmop.inc') && extension_loaded('shmop')) { 129 | @include_once("kv-shmop.inc"); 130 | } 131 | if (file_exists('kvstorage-memcache.inc') && extension_loaded('memcache')) { 132 | @include_once("kv-memcache.inc"); 133 | } 134 | if (file_exists('kvstorage-redis.inc') && extension_loaded('redis')) { 135 | @include_once("kv-redis.inc"); 136 | } 137 | }// php>=5.0 138 | if ( PHP_VERSION >= '5.3.0') { 139 | if (file_exists('kvstorage-sqlite3.inc') && extension_loaded('sqlite3')) { 140 | @include_once("kv-sqlite3-generic-file.inc"); 141 | @include_once("kv-sqlite3-devshm-file.inc"); 142 | @include_once("kv-sqlite3-memory-file.inc"); 143 | } 144 | }// php>=5.3 145 | if ( PHP_VERSION >= '7.2.0') { 146 | if (file_exists('mod-sodium.inc') && extension_loaded('sodium')) { 147 | @include_once("mod-sodium.inc"); 148 | } 149 | }// php>=5.3 150 | 151 | if (extension_loaded('uuid')) { 152 | @include_once("mod-uuid.inc"); 153 | } 154 | if (extension_loaded('gd')) { 155 | @include_once("php-gd-imagick-common.inc"); 156 | @include_once("php-gd.inc"); 157 | @include_once("mod-gd-empty-gif.inc"); 158 | @include_once("mod-gd-empty-png.inc"); 159 | @include_once("mod-gd-empty-jpg.inc"); 160 | @include_once("mod-gd-empty-webp.inc"); 161 | @include_once("mod-gd-empty-avif.inc"); 162 | } 163 | if (extension_loaded('imagick')) { 164 | @include_once("php-gd-imagick-common.inc"); 165 | @include_once("php-imagick.inc"); 166 | } 167 | 168 | $originMemoryLimit = @ini_get('memory_limit'); 169 | $originTimeLimit = @ini_get('max_execution_time'); 170 | 171 | /* Default execution time limit in seconds */ 172 | $defaultTimeLimit = 600; 173 | /* 174 | Default PHP memory limit in Mb. 175 | It's for ALL PHP structures! 176 | Memory allocator works with blocks by X_Mb. 177 | Some we need a little more. 178 | */ 179 | $defaultMemoryLimit = 130; 180 | 181 | $useColors = 1; 182 | 183 | $debugMode = 0; 184 | 185 | $printJson = 0; 186 | 187 | $printMachine = 0; 188 | 189 | $recalculateLimits = 1; 190 | 191 | $printDumbTest = 0; 192 | 193 | $outputTestsList = 0; 194 | 195 | $showOnlySystemInfo = 0; 196 | 197 | $selectedTests = array();// exact names 198 | $skipTests = array();// patterns to match names 199 | 200 | 201 | /* ----------------- Fetch environ or GET params */ 202 | 203 | if ($t = (int)getenv('PHP_TIME_LIMIT')) { 204 | $defaultTimeLimit = $t; 205 | } 206 | if (isset($_GET['time_limit']) && $t = (int)$_GET['time_limit']) { 207 | $defaultTimeLimit = $t; 208 | } 209 | 210 | if ($x = (int)getenv('DONT_USE_COLORS')) { 211 | $useColors = $x == 0; 212 | } 213 | if (isset($_GET['dont_use_colors']) && $x = (int)$_GET['dont_use_colors']) { 214 | $useColors = $x == 0; 215 | } 216 | 217 | if ($x = (int)getenv('PHP_DEBUG_MODE')) { 218 | $debugMode = $x; 219 | } 220 | if (isset($_GET['debug_mode']) && $x = (int)$_GET['debug_mode']) { 221 | $debugMode = $x; 222 | } 223 | 224 | if ($x = (int)getenv('PRINT_JSON')) { 225 | $printJson = $x; 226 | } 227 | if (isset($_GET['print_json']) && $x = (int)$_GET['print_json']) { 228 | $printJson = $x; 229 | } 230 | if ($printJson) $printMachine = 0; 231 | 232 | if ($x = (int)getenv('PRINT_MACHINE')) { 233 | $printMachine = $x; 234 | } 235 | if (isset($_GET['print_machine']) && $x = (int)$_GET['print_machine']) { 236 | $printMachine = $x; 237 | } 238 | if ($printMachine) $printJson = 0; 239 | 240 | if ($m = (int)getenv('PHP_MEMORY_LIMIT')) { 241 | $defaultMemoryLimit = $m; 242 | } 243 | if (isset($_GET['memory_limit']) && $m = (int)$_GET['memory_limit']) { 244 | $defaultMemoryLimit = $m; 245 | } 246 | 247 | if ((int)getenv('DONT_RECALCULATE_LIMITS')) { 248 | $recalculateLimits = 0; 249 | } 250 | if (isset($_GET['dont_recalculate_limits']) && (int)$_GET['dont_recalculate_limits']) { 251 | $recalculateLimits = 0; 252 | } 253 | 254 | if ((int)getenv('PRINT_DUMB_TEST')) { 255 | $printDumbTest = 1; 256 | } 257 | if (isset($_GET['print_dumb_test']) && (int)$_GET['print_dumb_test']) { 258 | $printDumbTest = 1; 259 | } 260 | 261 | if ((int)getenv('LIST_TESTS')) { 262 | $outputTestsList = 1; 263 | } 264 | if (isset($_GET['list_tests']) && (int)$_GET['list_tests']) { 265 | $outputTestsList = 1; 266 | } 267 | 268 | if ((int)getenv('SYSTEM_INFO')) { 269 | $showOnlySystemInfo = 1; 270 | } 271 | if (isset($_GET['system_info']) && (int)$_GET['system_info']) { 272 | $showOnlySystemInfo = 1; 273 | } 274 | 275 | if ($r = getenv('RUN_TESTS')) { 276 | $selectedTests = explode(',', $r); 277 | } 278 | if (!empty($_GET['run_tests'])) { 279 | $selectedTests = explode(',', $_GET['run_tests']); 280 | } 281 | 282 | if ($r = getenv('SKIP_TESTS')) { 283 | $skipTests = explode(',', $r); 284 | } 285 | if (!empty($_GET['skip_tests'])) { 286 | $skipTests = explode(',', $_GET['skip_tests']); 287 | } 288 | 289 | 290 | 291 | /* common functions */ 292 | 293 | function print_pre($msg) { 294 | global $printJson, $printMachine, $messagesCnt; 295 | if ($printMachine) { 296 | print($msg); 297 | } else if ($printJson) { 298 | $msg = trim(str_replace("\n", " ", $msg)); 299 | if (function_exists('json_encode')) { 300 | $msg = json_encode($msg); 301 | } else { 302 | $msg = '"'.$msg.'"'; 303 | } 304 | print('"message_'.$messagesCnt.'": '.$msg.','.PHP_EOL); 305 | } else { 306 | if (php_sapi_name() != 'cli') { 307 | print('
'.$msg.'
'); 308 | } else { 309 | print($msg); 310 | } 311 | } 312 | flush(); 313 | $messagesCnt++; 314 | } 315 | 316 | function print_norm($msg) { 317 | global $printJson, $messagesCnt; 318 | if ($printJson) { 319 | $msg = trim(str_replace("\n", " ", $msg)); 320 | if (function_exists('json_encode')) { 321 | $msg = json_encode($msg); 322 | } else { 323 | $msg = '"'.$msg.'"'; 324 | } 325 | print('"message_'.$messagesCnt.'": '.$msg.','.PHP_EOL); 326 | } else { 327 | print($msg); 328 | } 329 | flush(); 330 | $messagesCnt++; 331 | } 332 | 333 | 334 | if (!function_exists('gethostname')) { 335 | // 5.3.0+ only 336 | function gethostname() { 337 | ob_start(); 338 | $last_str = system(`hostname -f`, $errcode); 339 | ob_end_clean(); 340 | if ($last_str !== false) { 341 | return $last_str; 342 | } 343 | return ''; 344 | } 345 | } 346 | 347 | 348 | /* global command line options */ 349 | if (php_sapi_name() == 'cli') { 350 | 351 | 352 | // http://php.net/manual/ru/function.getopt.php example #2 353 | $shortopts = "h"; 354 | $shortopts .= "x"; 355 | $shortopts .= "d"; 356 | $shortopts .= "C"; 357 | $shortopts .= "J"; 358 | $shortopts .= "M"; 359 | $shortopts .= "D"; 360 | $shortopts .= "L"; 361 | $shortopts .= "I"; 362 | $shortopts .= "m:"; // Обязательное значение 363 | $shortopts .= "t:"; // Обязательное значение 364 | $shortopts .= "T:"; // Обязательное значение 365 | $shortopts .= "S:"; // Обязательное значение 366 | 367 | $longopts = array( 368 | "help", 369 | "debug", 370 | "dont-use-colors", 371 | "print-json", 372 | "print-machine", 373 | "dont-recalc", 374 | "dumb-test-print", 375 | "list-tests", 376 | "system-info", 377 | "memory-limit:", // Обязательное значение 378 | "time-limit:", // Обязательное значение 379 | "run-test:", // Обязательное значение 380 | "skip-test:", // Обязательное значение 381 | ); 382 | 383 | $hasLongOpts = true; 384 | if ((int)$phpversion[0] > 5) { 385 | $options = getopt($shortopts, $longopts); 386 | } elseif ((int)$phpversion[0] == 5 && (int)$phpversion[1] >= 3) { 387 | $options = getopt($shortopts, $longopts); 388 | } else { 389 | $options = getopt($shortopts); 390 | $hasLongOpts = false; 391 | } 392 | 393 | if ($options) { 394 | 395 | // First - simple options that do not do any output 396 | foreach ($options as $okey => $oval) { 397 | 398 | switch ($okey) { 399 | case 'd': 400 | case 'dont-recalc': 401 | $recalculateLimits = 0; 402 | break; 403 | 404 | case 'x': 405 | case 'debug': 406 | $debugMode = 1; 407 | break; 408 | 409 | case 'C': 410 | case 'dont-use-colors': 411 | $useColors = 0; 412 | break; 413 | 414 | case 'J': 415 | case 'print-json': 416 | $printJson = 1; 417 | $printMachine = 0; 418 | break; 419 | 420 | case 'M': 421 | case 'print-machine': 422 | $printMachine = 1; 423 | $printJson = 0; 424 | break; 425 | 426 | case 'D': 427 | case 'dumb-test-print': 428 | $printDumbTest = 1; 429 | break; 430 | 431 | case 'L': 432 | case 'list-tests': 433 | $outputTestsList = 1; 434 | break; 435 | 436 | case 'I': 437 | case 'system-info': 438 | $showOnlySystemInfo = 1; 439 | break; 440 | 441 | } // switch key 442 | 443 | } // for options 444 | 445 | 446 | // Drop colors here 447 | if (!$useColors || $printJson || $printMachine) { 448 | $colorReset = ''; 449 | $colorRed = ''; 450 | $colorGreen = ''; 451 | $colorYellow = ''; 452 | $colorGray = ''; 453 | } 454 | 455 | 456 | // Start JSON output here 457 | if ($printJson) print("{ " . PHP_EOL); 458 | 459 | foreach ($options as $okey => $oval) { 460 | 461 | switch ($okey) { 462 | 463 | case 'h': 464 | case 'help': 465 | if ($hasLongOpts) { 466 | print_pre( 467 | PHP_EOL 468 | . 'PHP Benchmark Performance Script, version ' . $scriptVersion . PHP_EOL 469 | . PHP_EOL 470 | . 'Usage: ' . basename(__FILE__) . ' [-h|--help] [-x|--debug] [-C|--dont-use-colors] [-J|--print-json] [-M|--print-machine] [-d|--dont-recalc] [-D|--dumb-test-print] [-L|--list-tests] [-I|--system-info] [-S|--do-not-task-set] [-m|--memory-limit=130] [-t|--time-limit=600] [-T|--run-test=name] [-S|--skip-test=pattern]' . PHP_EOL 471 | . PHP_EOL 472 | . ' -h|--help - print this help and exit' . PHP_EOL 473 | . ' -x|--debug - enable debug mode, raise output level' . PHP_EOL 474 | . ' -C|--dont-use-colors - disable printing html-span or color sequences for capable terminal: xterm, *-color, *-256color. And not use it in JSON/machine mode.' . PHP_EOL 475 | . ' -J|--print-json - enable printing only in JSON format, useful for automated tests. disables print-machine.' . PHP_EOL 476 | . ' -M|--print-machine - enable printing only in machine parsable format, useful for automated tests. disables print-json.' . PHP_EOL 477 | . ' -d|--dont-recalc - do not recalculate test times / operations count even if memory of execution time limits are low' . PHP_EOL 478 | . ' -D|--dumb-test-print - print dumb test time, for debug purpose' . PHP_EOL 479 | . ' -L|--list-tests - output list of available tests and exit' . PHP_EOL 480 | . ' -I|--system-info - output system info but do not run tests and exit' . PHP_EOL 481 | . ' -m|--memory-limit - set memory_limit value in Mb, defaults to 130 (Mb)' . PHP_EOL 482 | . ' -t|--time-limit - set max_execution_time value in seconds, defaults to 600 (sec)' . PHP_EOL 483 | . ' -T|--run-test - run selected tests, test names from --list-tests output, can be defined multiple times' . PHP_EOL 484 | . ' -S|--skip-test - skip selected tests, test names pattern to match name from --list-tests output, can be defined multiple times' . PHP_EOL 485 | . PHP_EOL 486 | . 'Example: php ' . basename(__FILE__) . ' -m=64 -t=30' . PHP_EOL 487 | . PHP_EOL 488 | ); 489 | } else { 490 | print_pre( 491 | PHP_EOL 492 | . 'PHP Benchmark Performance Script, version ' . $scriptVersion . PHP_EOL 493 | . PHP_EOL 494 | . 'Usage: ' . basename(__FILE__) . ' [-h] [-x] [-C] [-J] [-M] [-d] [-D] [-L] [-I] [-S] [-m 130] [-t 600] [-T name]' . PHP_EOL 495 | . PHP_EOL 496 | . ' -h - print this help and exit' . PHP_EOL 497 | . ' -x - enable debug mode, raise output level' . PHP_EOL 498 | . ' -C - disable printing html-span or color sequences for capable terminal: xterm, *-color, *-256color. And not use it in JSON/machine mode.' . PHP_EOL 499 | . ' -J - enable printing only in JSON format, useful for automated tests. disables print-machine.' . PHP_EOL 500 | . ' -M - enable printing only in machine parsable format, useful for automated tests. disables print-json.' . PHP_EOL 501 | . ' -d - do not recalculate test times / operations count even if memory of execution time limits are low' . PHP_EOL 502 | . ' -D - print dumb test time, for debug purpose' . PHP_EOL 503 | . ' -L - output list of available tests and exit' . PHP_EOL 504 | . ' -I - output system info but do not run tests and exit' . PHP_EOL 505 | . ' -m - set memory_limit value in Mb, defaults to 130 (Mb)' . PHP_EOL 506 | . ' -t - set max_execution_time value in seconds, defaults to 600 (sec)' . PHP_EOL 507 | . ' -T - run selected tests, test names from -L output, can be defined multiple times' . PHP_EOL 508 | . ' -S - skip selected tests, test names pattern to match name from -L output, can be defined multiple times' . PHP_EOL 509 | . PHP_EOL 510 | . 'Example: php ' . basename(__FILE__) . ' -m 64 -t 30' . PHP_EOL 511 | . PHP_EOL 512 | ); 513 | } 514 | if ($printJson) { 515 | print("\"messages_count\": {$messagesCnt},\n"); 516 | print("\"end\":true\n}" . PHP_EOL); 517 | } 518 | exit(0); 519 | break; 520 | 521 | case 'm': 522 | case 'memory-limit': 523 | if (is_numeric($oval)) { 524 | $defaultMemoryLimit = (int)$oval; 525 | } else { 526 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Option '$okey' has not numeric value '$oval'! Skip." . PHP_EOL); 527 | } 528 | break; 529 | 530 | case 't': 531 | case 'time-limit': 532 | if (is_numeric($oval)) { 533 | $defaultTimeLimit = (int)$oval; 534 | } else { 535 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Option '$okey' has not numeric value '$oval'! Skip." . PHP_EOL); 536 | } 537 | break; 538 | 539 | case 'T': 540 | case 'run-test': 541 | // Multiple values are joined into array 542 | if (!empty($oval)) { 543 | $selectedTests = (array)$oval; 544 | } else { 545 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Option '$okey' has no value! Skip." . PHP_EOL); 546 | } 547 | break; 548 | 549 | 550 | case 'S': 551 | case 'skip-test': 552 | // Multiple values are joined into array 553 | if (!empty($oval)) { 554 | $skipTests = (array)$oval; 555 | } else { 556 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Option '$okey' has no value! Skip." . PHP_EOL); 557 | } 558 | break; 559 | 560 | 561 | case 'd': 562 | case 'dont-recalc': 563 | case 'x': 564 | case 'debug': 565 | case 'C': 566 | case 'dont-use-colors': 567 | case 'J': 568 | case 'print-json': 569 | case 'M': 570 | case 'print-machine': 571 | case 'D': 572 | case 'dumb-test-print': 573 | case 'L': 574 | case 'list-tests': 575 | case 'I': 576 | case 'system-info': 577 | // Done in previous cycle 578 | break; 579 | 580 | default: 581 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Unknown option '$okey'!" . PHP_EOL); 582 | } 583 | 584 | } 585 | 586 | } // if options 587 | 588 | 589 | } // if sapi == cli 590 | 591 | 592 | // Drop colors here too 593 | if (!$useColors || $printJson || $printMachine) { 594 | $colorReset = ''; 595 | $colorRed = ''; 596 | $colorGreen = ''; 597 | $colorYellow = ''; 598 | $colorGray = ''; 599 | } 600 | 601 | 602 | if (php_sapi_name() != 'cli') { 603 | // Hello, nginx! 604 | header('X-Accel-Buffering: no', true); 605 | if ($printJson) { 606 | header('Content-Type: application/json', true); 607 | } else { 608 | header('Content-Type: text/html; charset=utf-8', true); 609 | } 610 | flush(); 611 | } else { 612 | $flushStr = ''; 613 | } 614 | 615 | $tz = ini_get('date.timezone'); 616 | if (!$tz) ini_set('date.timezone', 'Europe/Moscow'); 617 | 618 | @ini_set('error_log', null); 619 | ini_set('implicit_flush', 1); 620 | ini_set('output_buffering', 0); 621 | ob_implicit_flush(1); 622 | 623 | if ($debugMode){ 624 | ini_set('display_errors', 1); 625 | error_reporting(E_ERROR | E_WARNING | E_PARSE); 626 | } else { 627 | ini_set('display_errors', 0); 628 | // Disable explicit error reporting 629 | error_reporting(E_ERROR | E_WARNING | E_PARSE); 630 | } 631 | 632 | // Check XDebug 633 | $xdebug = (int)ini_get('xdebug.default_enable'); 634 | if ($xdebug) { 635 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} You need to disable Xdebug extension! It greatly slow things down! And mess with PHP internals.".PHP_EOL); 636 | } 637 | 638 | // Check OpCache 639 | if (php_sapi_name() != 'cli') { 640 | $opcache = (int)ini_get('opcache.enable'); 641 | if ($opcache) { 642 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} You may want to disable OpCache extension! It can greatly affect the results! Make it via .htaccess, VHost or FPM config.".PHP_EOL); 643 | } 644 | $apcache = (int)ini_get('apc.enabled'); 645 | } else { 646 | $opcache = (int)ini_get('opcache.enable_cli'); 647 | if ($opcache) { 648 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} You may want to disable Cli OpCache extension! It can greatly affect the results! Run php with param: -dopcache.enable_cli=0".PHP_EOL); 649 | } 650 | $apcache = (int)ini_get('apc.enable_cli'); 651 | } 652 | $xcache = (int)ini_get('xcache.cacher'); 653 | $eaccel = (int)ini_get('eaccelerator.enable'); 654 | 655 | $mbover = (int)ini_get('mbstring.func_overload'); 656 | if ($mbover != 0) { 657 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} You must disable mbstring string functions overloading! It greatly slow things down! And messes with results.".PHP_EOL); 658 | } 659 | 660 | $obd_set = (int)!in_array(ini_get('open_basedir'), array('', null)); 661 | if ($obd_set != 0) { 662 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} You should unset `open_basedir` parameter! It may slow things down!".PHP_EOL); 663 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Parameter `open_basedir` in effect! Script may not able to read system CPU and Memory information. Memory adjustment for tests may not work.\n"); 664 | } 665 | 666 | $dropDead = false; 667 | // No php < 4 668 | if ((int)$phpversion[0] < 4) { 669 | $dropDead = true; 670 | } 671 | // No php <= 4.3 672 | if ((int)$phpversion[0] == 4 && (int)$phpversion[1] < 3) { 673 | $dropDead = true; 674 | } 675 | if ($dropDead) { 676 | print_pre("{$colorRed}<<< ERROR >>>{$colorReset} Need PHP 4.3+! Current version is " . PHP_VERSION .PHP_EOL); 677 | if ($printJson) { 678 | print("\"messages_count\": {$messagesCnt},\n"); 679 | print("\"end\":true\n}".PHP_EOL); 680 | } 681 | exit(1); 682 | } 683 | if (!defined('PHP_MAJOR_VERSION')) { 684 | define('PHP_MAJOR_VERSION', (int)$phpversion[0]); 685 | } 686 | if (!defined('PHP_MINOR_VERSION')) { 687 | define('PHP_MINOR_VERSION', (int)$phpversion[1]); 688 | } 689 | 690 | if ($debugMode) { 691 | ini_set('display_errors', 1); 692 | error_reporting(E_ALL); 693 | } 694 | 695 | $set = set_time_limit($defaultTimeLimit); 696 | if ($set === false) { 697 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Execution time limit not droppped to '{$defaultTimeLimit}' seconds!\nScript will have only '{$originTimeLimit}' seconds to run." . PHP_EOL); 698 | } 699 | $set = ini_set('memory_limit', $defaultMemoryLimit . 'M'); 700 | if ($set === false) { 701 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Memory limit not set to '{$defaultMemoryLimit}'!" . PHP_EOL); 702 | } 703 | 704 | /** ------------------------------- Main Constants ------------------------------- */ 705 | 706 | $line = str_pad("-", 91, "-"); 707 | $padHeader = 89; 708 | $padInfo = 19; 709 | $padLabel = 30; 710 | 711 | $emptyResult = array(0, '-.---', '-.-- ', '-.-- ', 0); 712 | 713 | $cryptSalt = null; 714 | $cryptAlgoName = 'default'; 715 | 716 | // That gives around 130Mb memory use and reasonable test time 717 | $testMemoryFull = 130 * 1024 * 1024; 718 | // That gives around 8Mb memory use to run every tests 719 | $testMemoryMin = 5 * 1024 * 1024; 720 | // Arrays are matrix [$dimention] x [$dimention] 721 | $arrayDimensionLimit = 600; 722 | 723 | // That limit gives around 128Mb too 724 | $stringConcatLoopRepeat = 5; 725 | 726 | $runOnlySelectedTests = !empty($selectedTests); 727 | 728 | $stringTest = " the quick brown fox jumps over the lazy dog and eat lorem ipsum
Valar morghulis
\n\rабыр\nвалар дохаэрис У нас закончились ложки, Нео! "; 729 | $regexPattern = '/[\s,]+/'; 730 | 731 | /** ---------------------------------- Tests limits - to recalculate -------------------------------------------- */ 732 | 733 | // Gathered on this machine 734 | $loopMaxPhpTimesMHz = 3500; 735 | // How much time needed for tests on this machine 736 | $loopMaxPhpTimes = array( 737 | '4.4' => 2099, 738 | '5.2' => 839, 739 | '5.3' => 1235, 740 | '5.4' => 1510, 741 | '5.5' => 802, 742 | '5.6' => 1337, 743 | '7.0' => 672, 744 | '7.1' => 669, 745 | '7.2' => 662, 746 | '7.3' => 586, 747 | '7.4' => 659, 748 | '8.0' => 676, 749 | '8.1' => 450, 750 | '8.2' => 427, 751 | '8.3' => 582, 752 | '8.4' => 529 753 | ); 754 | // Simple and fast test times, used to adjust all test times and limits 755 | $dumbTestMaxPhpTimes = array( 756 | '4.4' => 1.041, 757 | '5.2' => 0.771, 758 | '5.3' => 0.737, 759 | '5.4' => 0.769, 760 | '5.5' => 0.770, 761 | '5.6' => 0.781, 762 | '7.0' => 0.425, 763 | '7.1' => 0.425, 764 | '7.2' => 0.412, 765 | '7.3' => 0.339, 766 | '7.4' => 0.340, 767 | '8.0' => 0.324, 768 | '8.1' => 0.323, 769 | '8.2' => 0.294, 770 | '8.3' => 0.784, 771 | '8.4' => 0.759 772 | ); 773 | // Nice dice roll 774 | // Should not be longer than 600 seconds 775 | $testsLoopLimits = array( 776 | '01_math' => 2000000, 777 | // That limit gives around 90Mb 778 | '02_string_concat' => 5000000, 779 | '03_1_string_number_concat' => 5000000, 780 | '03_2_string_number_format' => 5000000, 781 | '04_string_simple' => 1300000, 782 | '05_string_mb' => 130000, 783 | '06_string_manip' => 1300000, 784 | '07_regex' => 1300000, 785 | '08_1_hashing' => 1300000, 786 | '08_2_crypt' => 10000, 787 | '09_json_encode' => 1300000, 788 | '10_json_decode' => 1300000, 789 | '11_serialize' => 1300000, 790 | '12_unserialize' => 1300000, 791 | '11_igb_serialize' => 1300000, 792 | '12_igb_unserialize' => 1300000, 793 | '11_msgpack_pack' => 1300000, 794 | '12_msgpack_unpack' => 1300000, 795 | '13_array_loop' => 250, 796 | '14_array_loop' => 250, 797 | '15_clean_loops' => 200000000, 798 | '16_loop_ifelse' => 100000000, 799 | '17_loop_ternary' => 100000000, 800 | '18_1_loop_def' => 50000000, 801 | '18_2_loop_undef' => 50000000, 802 | '19_type_func' => 4000000, 803 | '20_type_cast' => 4000000, 804 | '21_loop_except' => 10000000, 805 | '22_loop_nullop' => 60000000, 806 | '23_loop_spaceship' => 60000000, 807 | '26_1_public' => 10000000, 808 | '26_2_getset' => 10000000, 809 | '26_3_magic' => 10000000, 810 | '27_simplexml' => 50000, 811 | '28_domxml' => 50000, 812 | '29_datetime' => 500000, 813 | '30_intl_number_format' => 20000, 814 | '31_intl_message_format' => 200000, 815 | '32_intl_calendar' => 300000, 816 | '33_phpinfo_generate' => 10000, 817 | '34_gd_qrcode' => 1000, 818 | '35_imagick_qrcode' => 1000, 819 | '36_01_zlib_deflate_compress' => 500000, 820 | '36_02_zlib_gzip_compress' => 500000, 821 | '36_bzip2_compress' => 50000, 822 | '36_lz4_compress' => 5000000, 823 | '36_snappy_compress' => 5000000, 824 | '36_zstd_compress' => 5000000, 825 | '36_brotli_compress' => 1000000, 826 | '37_01_php8_str_contains' => 100000, 827 | '37_02_php8_str_contains_emulate' => 100000, 828 | '38_01_php_uuid' => 1000000, 829 | '38_02_mod_uuid' => 1000000, 830 | '39_01_kvstorage_memory' => 500000, 831 | '39_02_kvstorage_xcache' => 500000, 832 | '39_03_kvstorage_apcu' => 500000, 833 | '39_04_kvstorage_shmop' => 500000, 834 | '39_05_kvstorage_memcache' => 500000, 835 | '39_06_kvstorage_redis' => 500000, 836 | '39_07_kvs_sqlite3_generic_file' => 500000, 837 | '39_08_kvs_sqlite3_devshm_file' => 500000, 838 | '39_09_kvs_sqlite3_memory_file' => 500000, 839 | '40_01_gd_save_fill_empty_gif' => 10000, 840 | '40_02_gd_save_fill_empty_png' => 10000, 841 | '40_03_gd_save_fill_empty_jpg' => 10000, 842 | '40_04_gd_save_fill_empty_webp' => 10000, 843 | '40_05_gd_save_fill_empty_avif' => 10000, 844 | '41_01_sodium_string_num_int' => 10000000, 845 | '41_02_sodium_string_num_float' => 10000000, 846 | '42_ctype_isdigit' => 10000000, 847 | '43_iconv_translit' => 10000000, 848 | '44_session_time' => 100000, 849 | ); 850 | // Should not be more than X Mb 851 | // Different PHP could use different amount of memory 852 | // There defined maximum possible 853 | $testsMemoryLimits = array( 854 | '01_math' => 4, 855 | '02_string_concat' => 90, 856 | '03_1_string_number_concat' => 4, 857 | '03_2_string_number_format' => 4, 858 | '04_string_simple' => 4, 859 | '05_string_mb' => 4, 860 | '06_string_manip' => 4, 861 | '07_regex' => 4, 862 | '08_1_hashing' => 4, 863 | '08_2_crypt' => 4, 864 | '09_json_encode' => 4, 865 | '10_json_decode' => 4, 866 | '11_serialize' => 4, 867 | '12_unserialize' => 4, 868 | '11_igb_serialize' => 4, 869 | '12_igb_unserialize' => 4, 870 | // php-5.3 871 | '13_array_loop' => 54, 872 | '14_array_loop' => 62, 873 | // opcache, php-7.4 874 | '15_clean_loops' => 14, 875 | '16_loop_ifelse' => 14, 876 | '17_loop_ternary' => 14, 877 | '18_1_loop_def' => 14, 878 | '18_2_loop_undef' => 14, 879 | '19_type_func' => 14, 880 | '20_type_cast' => 14, 881 | '21_loop_except' => 14, 882 | '22_loop_nullop' => 14, 883 | '23_loop_spaceship' => 14, 884 | '26_1_public' => 14, 885 | '26_2_getset' => 14, 886 | '26_3_magic' => 14, 887 | '27_simplexml' => 14, 888 | '28_domxml' => 14, 889 | '29_datetime' => 14, 890 | '30_intl_number_format' => 14, 891 | '31_intl_message_format' => 14, 892 | '32_intl_calendar' => 14, 893 | '33_phpinfo_generate' => 14, 894 | '34_gd_qrcode' => 14, 895 | '35_imagick_qrcode' => 8, 896 | '36_01_zlib_deflate_compress' => 4, 897 | '36_02_zlib_gzip_compress' => 4, 898 | '36_bzip2_compress' => 4, 899 | '36_lz4_compress' => 4, 900 | '36_snappy_compress' => 4, 901 | '36_zstd_compress' => 4, 902 | '36_brotli_compress' => 4, 903 | '37_01_php8_str_contains' => 4, 904 | '37_02_php8_str_contains_simulate' => 4, 905 | '38_01_php_uuid' => 4, 906 | '38_02_mod_uuid' => 4, 907 | '39_01_kvstorage_memory' => 3, 908 | '39_02_kvstorage_xcache' => 2, 909 | '39_03_kvstorage_apcu' => 47, 910 | '39_04_kvstorage_shmop' => 70, 911 | '39_05_kvstorage_memcache' => 47, 912 | '39_06_kvstorage_redis' => 47, 913 | '39_07_kvs_sqlite3_generic_file' => 4, 914 | '39_08_kvs_sqlite3_devshm_file' => 4, 915 | '39_09_kvs_sqlite3_memory_file' => 4, 916 | '40_01_gd_save_fill_empty_gif' => 4, 917 | '40_02_gd_save_fill_empty_png' => 4, 918 | '40_03_gd_save_fill_empty_jpg' => 4, 919 | '40_04_gd_save_fill_empty_webp' => 4, 920 | '40_05_gd_save_fill_empty_avif' => 4, 921 | '41_01_sodium_string_num_int' => 4, 922 | '41_02_sodium_string_num_float' => 4, 923 | '42_ctype_isdigit' => 4, 924 | '43_iconv_translit' => 4, 925 | '44_session_time' => 4, 926 | ); 927 | 928 | /** ---------------------------------- Common functions -------------------------------------------- */ 929 | 930 | /** 931 | * Get pretty OS release name, if available 932 | */ 933 | function get_current_os() 934 | { 935 | $osFile = '/etc/os-release'; 936 | $result = PHP_OS; 937 | if (@is_readable($osFile)) { 938 | $f = fopen($osFile, 'r'); 939 | while (!feof($f)) { 940 | $line = trim(fgets($f, 1000000)); 941 | if (strpos($line, 'PRETTY_NAME=') === 0) { 942 | $s = explode('=', $line); 943 | $result = array_pop($s); 944 | $result = str_replace('"','', $result); 945 | } 946 | } 947 | } 948 | return $result; 949 | } 950 | 951 | function get_microtime() 952 | { 953 | $time = microtime(true); 954 | if (is_string($time)) { 955 | list($f, $i) = explode(' ', $time); 956 | $time = intval($i) + floatval($f); 957 | } 958 | return $time; 959 | } 960 | 961 | function convert($size) 962 | { 963 | $unit = array('b', 'kb', 'Mb', 'Gb', 'Tb', 'Pb', 'Eb'); 964 | if ($size <= 0) $i = 0; 965 | else $i = floor(log($size, 1024)); 966 | if ($i < 0) $i = 0; 967 | return @round($size / pow(1024, $i), 2) . ' ' . $unit[$i]; 968 | } 969 | 970 | function prefix_si($size) 971 | { 972 | $unit = array(' ', 'k', 'M', 'G', 'T', 'P', 'E', -3 => 'm', -6 => 'u'); 973 | $i = floor(log($size, 1000)); 974 | if ($i < 0) { 975 | if ($i <= -6) { 976 | $i = -6; 977 | } elseif ($i <= -3) { 978 | $i = -3; 979 | } else { 980 | $i = 0; 981 | } 982 | } 983 | return $unit[$i]; 984 | } 985 | 986 | function convert_si($size) 987 | { 988 | $i = floor(log($size, 1000)); 989 | if ($i < 0) { 990 | if ($i <= -6) { 991 | $i = -6; 992 | } elseif ($i <= -3) { 993 | $i = -3; 994 | } else { 995 | $i = 0; 996 | } 997 | } 998 | return @round($size / pow(1000, $i), 2); 999 | } 1000 | 1001 | 1002 | /** 1003 | * Return memory_limit in bytes 1004 | * 1005 | * @return int 1006 | */ 1007 | function getPhpMemoryLimitBytes() 1008 | { 1009 | global $debugMode, $colorGray, $colorReset; 1010 | // http://stackoverflow.com/a/10209530 1011 | $memory_limit = strtolower(ini_get('memory_limit')); 1012 | if ($debugMode) { 1013 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getPhpMemoryLimitBytes(): ini_get memory_limit = '{$memory_limit}'\n"); 1014 | } 1015 | if (preg_match('/^(\d+)(.)$/', $memory_limit, $matches)) { 1016 | if ($debugMode) { 1017 | $ve = var_export($matches, true); 1018 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getPhpMemoryLimitBytes(): parse via preg_math:\n{$ve}\n"); 1019 | } 1020 | if ($matches[2] == 'g') { 1021 | $memory_limit = intval($matches[1]) * 1024 * 1024 * 1024; // nnnG -> nnn GB 1022 | } else if ($matches[2] == 'm') { 1023 | $memory_limit = intval($matches[1]) * 1024 * 1024; // nnnM -> nnn MB 1024 | } else if ($matches[2] == 'k') { 1025 | $memory_limit = intval($matches[1]) * 1024; // nnnK -> nnn KB 1026 | } else { 1027 | $memory_limit = intval($matches[1]); // nnn -> nnn B 1028 | } 1029 | } 1030 | if ($debugMode) { 1031 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getPhpMemoryLimitBytes(): result memory_limit = '{$memory_limit}'\n"); 1032 | } 1033 | return $memory_limit; 1034 | } 1035 | 1036 | /** 1037 | * Return array (dict) with system memory info. 1038 | * All values in bytes. 1039 | * http://stackoverflow.com/a/1455610 1040 | */ 1041 | function getSystemMemInfo() 1042 | { 1043 | global $debugMode, $colorGray, $colorReset; 1044 | 1045 | $meminfo = array(); 1046 | if (! @is_readable("/proc/meminfo")) { 1047 | if ($debugMode) { 1048 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Can't read /proc/meminfo!" . PHP_EOL); 1049 | } 1050 | return $meminfo; 1051 | } 1052 | $data = explode("\n", file_get_contents("/proc/meminfo")); 1053 | foreach ($data as $line) { 1054 | if (empty($line)) { 1055 | continue; 1056 | } 1057 | 1058 | list($key, $val) = explode(":", $line); 1059 | $_val = explode(" ", strtolower(trim($val))); 1060 | $val = intval($_val[0]); 1061 | if (isset($_val[1]) && $_val[1] == 'kb') { 1062 | $val *= 1024; 1063 | } 1064 | $meminfo[$key] = trim($val); 1065 | } 1066 | return $meminfo; 1067 | } 1068 | 1069 | /** 1070 | * Return system memory FREE+CACHED+BUFFERS bytes (may be free) 1071 | * 1072 | * @return int 1073 | */ 1074 | function getSystemMemoryFreeLimitBytes() 1075 | { 1076 | global $debugMode, $colorGray, $colorReset; 1077 | 1078 | $info = getSystemMemInfo(); 1079 | 1080 | if ($debugMode) { 1081 | $ve = var_export($info, true); 1082 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getSystemMemoryFreeLimitBytes(): system memory info:\n{$ve}'\n"); 1083 | } 1084 | 1085 | if (empty($info)) { 1086 | return -1; 1087 | } 1088 | 1089 | if (isset($info['MemAvailable'])) { 1090 | if ($debugMode) { 1091 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getSystemMemoryFreeLimitBytes(): return MemAvailable: {$info['MemAvailable']}\n"); 1092 | } 1093 | return $info['MemAvailable']; 1094 | } 1095 | $available = $info['MemFree'] + $info['Cached'] + $info['Buffers']; 1096 | if ($debugMode) { 1097 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} getSystemMemoryFreeLimitBytes(): return MemFree + Cached + Buffers: {$available}\n"); 1098 | } 1099 | return $available; 1100 | } 1101 | 1102 | /** 1103 | * Read /proc/cpuinfo, fetch some data 1104 | */ 1105 | function getCpuInfo($fireUpCpu = false) 1106 | { 1107 | global $debugMode, $colorGray, $colorReset; 1108 | 1109 | $cpu = array( 1110 | 'model' => '', 1111 | 'vendor' => '', 1112 | 'cores' => 0, 1113 | 'available' => 0, 1114 | 'mhz' => 0.0, 1115 | 'max-mhz' => 0.0, 1116 | 'min-mhz' => 0.0, 1117 | 'mips' => 0.0 1118 | ); 1119 | 1120 | if (! @is_readable('/proc/cpuinfo')) { 1121 | if ($debugMode) { 1122 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Can't read /proc/cpuinfo!" . PHP_EOL); 1123 | } 1124 | $cpu['model'] = 'Unknown'; 1125 | $cpu['vendor'] = 'Unknown'; 1126 | $cpu['cores'] = 1; 1127 | $cpu['available'] = 1; 1128 | return $cpu; 1129 | } 1130 | 1131 | if ($fireUpCpu) { 1132 | // Fire up CPU, Don't waste much time here 1133 | $i = 30000000; 1134 | while ($i--) ; 1135 | } 1136 | if (@is_readable('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq')) { 1137 | $cpu['mhz'] = ((int)file_get_contents('/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq'))/1000.0; 1138 | } 1139 | 1140 | // Code from https://github.com/jrgp/linfo/blob/master/src/Linfo/OS/Linux.php 1141 | // Adopted 1142 | $cpuData = explode("\n", file_get_contents('/proc/cpuinfo')); 1143 | foreach ($cpuData as $line) { 1144 | $line = explode(':', $line, 2); 1145 | 1146 | if (!array_key_exists(1, $line)) { 1147 | continue; 1148 | } 1149 | 1150 | $key = trim($line[0]); 1151 | $value = trim($line[1]); 1152 | 1153 | // What we want are bogomips, MHz, processor, and Model. 1154 | switch ($key) { 1155 | // CPU model 1156 | case 'model name': 1157 | case 'cpu': 1158 | case 'Processor': 1159 | if (empty($cpu['model'])) { 1160 | $cpu['model'] = $value; 1161 | } 1162 | break; 1163 | // Speed in MHz 1164 | case 'cpu MHz': 1165 | if (empty($cpu['mhz']) || $cpu['mhz'] < (float)$value) { 1166 | $cpu['mhz'] = (float)$value; 1167 | } 1168 | break; 1169 | case 'Cpu0ClkTck': // Old sun boxes 1170 | if (empty($cpu['mhz'])) { 1171 | $cpu['mhz'] = (int)hexdec($value) / 1000000.0; 1172 | } 1173 | break; 1174 | case 'bogomips': // twice of MHz usualy on Intel/Amd 1175 | case 'BogoMIPS': // twice of MHz usualy on Intel/Amd 1176 | if (empty($cpu['mhz'])) { 1177 | $cpu['mhz'] = (float)$value / 2.0; 1178 | } 1179 | if (empty($cpu['mips'])) { 1180 | $cpu['mips'] = (float)$value / 2.0; 1181 | } 1182 | break; 1183 | // cores 1184 | case 'cpu cores': 1185 | if (empty($cpu['cores'])) { 1186 | $cpu['cores'] = (int)$value; 1187 | } 1188 | break; 1189 | case 'processor': 1190 | case 'core id': 1191 | if (empty($cpu['available'])) { 1192 | $cpu['available'] = (int)$value+1; 1193 | } else { 1194 | if ($cpu['available'] < (int)$value+1) { 1195 | $cpu['available'] = (int)$value+1; 1196 | } 1197 | } 1198 | break; 1199 | } 1200 | } 1201 | 1202 | // Raspberry Pi or other ARM board etc. 1203 | $cpuData = array(); 1204 | if (@is_executable('/usr/bin/lscpu')) { 1205 | $cpuData = explode("\n", shell_exec('/usr/bin/lscpu 2>&1')); 1206 | } 1207 | foreach ($cpuData as $line) { 1208 | $line = explode(':', $line, 2); 1209 | 1210 | if (!array_key_exists(1, $line)) { 1211 | continue; 1212 | } 1213 | 1214 | $key = trim($line[0]); 1215 | $value = trim($line[1]); 1216 | 1217 | // What we want are bogomips, MHz, processor, and Model. 1218 | switch ($key) { 1219 | // CPU model 1220 | case 'Model name': 1221 | if (empty($cpu['model'])) { 1222 | $cpu['model'] = $value; 1223 | } 1224 | break; 1225 | // cores 1226 | case 'CPU(s)': 1227 | if (empty($cpu['cores'])) { 1228 | $cpu['cores'] = (int)$value; 1229 | // Different output, not like /proc/cpuinfo 1230 | $cpu['available'] = (int)$value; 1231 | } 1232 | break; 1233 | // MHz 1234 | case 'CPU max MHz': 1235 | if (empty($cpu['max-mhz'])) { 1236 | $cpu['max-mhz'] = (int)$value; 1237 | } 1238 | break; 1239 | case 'CPU min MHz': 1240 | if (empty($cpu['min-mhz'])) { 1241 | $cpu['min-mhz'] = (int)$value; 1242 | } 1243 | break; 1244 | // vendor 1245 | case 'Vendor ID': 1246 | if (empty($cpu['vendor'])) { 1247 | $cpu['vendor'] = $value; 1248 | } 1249 | break; 1250 | } 1251 | } 1252 | 1253 | if ($cpu['vendor'] == 'ARM') { 1254 | // Unusable 1255 | $cpu['mips'] = 0; 1256 | } 1257 | 1258 | return $cpu; 1259 | } 1260 | 1261 | function dumb_test_Functions() 1262 | { 1263 | global $stringTest; 1264 | 1265 | $count = 100000; 1266 | $time_start = get_microtime(); 1267 | $stringFunctions = array('strtoupper', 'strtolower', 'strlen', 'str_rot13', 'ord', 'mb_strlen', 'trim', 'md5', 'json_encode'); 1268 | foreach ($stringFunctions as $key => $function) { 1269 | if (!function_exists($function)) { 1270 | unset($stringFunctions[$key]); 1271 | } 1272 | } 1273 | for ($i = 0; $i < $count; $i++) { 1274 | foreach ($stringFunctions as $function) { 1275 | $r = call_user_func_array($function, array($stringTest)); 1276 | } 1277 | } 1278 | return get_microtime() - $time_start; 1279 | } 1280 | 1281 | function mymemory_usage() 1282 | { 1283 | $m = memory_get_usage(true); 1284 | if (!$m) { 1285 | // If Zend Memory Manager disabled 1286 | // Dummy, not accurate 1287 | $dat = getrusage(); 1288 | $m = $dat["ru_maxrss"]; 1289 | } 1290 | return $m; 1291 | } 1292 | 1293 | 1294 | /** ---------------------------------- Code for common variables, tune values -------------------------------------------- */ 1295 | 1296 | // Search most common available algo for SALT 1297 | // http://php.net/manual/ru/function.crypt.php example #3 1298 | $cryptSalt = null; 1299 | if (defined('CRYPT_STD_DES') && CRYPT_STD_DES == 1) { 1300 | $cryptSalt = 'rl'; 1301 | $cryptAlgoName = 'Std. DES'; 1302 | } 1303 | if (defined('CRYPT_EXT_DES') && CRYPT_EXT_DES == 1) { 1304 | $cryptSalt = '_J9..rasm'; 1305 | $cryptAlgoName = 'Ext. DES'; 1306 | } 1307 | if (defined('CRYPT_MD5') && CRYPT_MD5 == 1) { 1308 | $cryptSalt = '$1$rasmusle$'; 1309 | $cryptAlgoName = 'MD5'; 1310 | } 1311 | 1312 | /** 1313 | * These are available since 5.3+ 1314 | * MD5 should be available to all versions. 1315 | */ 1316 | 1317 | /* 1318 | if (defined('CRYPT_BLOWFISH') && CRYPT_BLOWFISH == 1) { 1319 | $cryptSalt = '$2a$07$usesomesillystringforsalt$'; 1320 | $cryptAlgoName = 'BlowFish'; 1321 | } 1322 | if (defined('CRYPT_SHA256') && CRYPT_SHA256 == 1) { 1323 | $cryptSalt = '$5$rounds=5000$usesomesillystringforsalt$'; 1324 | $cryptAlgoName = 'Sha256'; 1325 | } 1326 | if (defined('CRYPT_SHA512') && CRYPT_SHA512 == 1) { 1327 | $cryptSalt = '$6$rounds=5000$usesomesillystringforsalt$'; 1328 | $cryptAlgoName = 'Sha512'; 1329 | } 1330 | */ 1331 | 1332 | if ($cryptAlgoName != 'MD5' && $cryptAlgoName != 'default') { 1333 | if ($printJson || $printMachine) { 1334 | print_pre("<<< WARNING >>> Hashing algorithm MD5 not available for crypt() in this PHP build! It should be available in any PHP build." . PHP_EOL); 1335 | } else { 1336 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nHashing algorithm MD5 not available for crypt() in this PHP build!\n It should be available in any PHP build.\n$line" . PHP_EOL); 1337 | } 1338 | } 1339 | 1340 | $cpuInfo = getCpuInfo(); 1341 | // CPU throttling? 1342 | if ($cpuInfo['mips'] && $cpuInfo['mhz']) { 1343 | if (abs($cpuInfo['mips'] - $cpuInfo['mhz']) > 300) { 1344 | if ($printJson || $printMachine) { 1345 | print_pre("<<< WARNING >>> CPU is in powersaving mode? Set CPU governor to 'performance'! Fire up CPU and recalculate MHz!" . PHP_EOL); 1346 | } else { 1347 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nCPU is in powersaving mode? Set CPU governor to 'performance'!\n Fire up CPU and recalculate MHz!\n$line" . PHP_EOL); 1348 | } 1349 | // TIME WASTED HERE 1350 | $cpuInfo = getCpuInfo(true); 1351 | } 1352 | } else if ($cpuInfo['max-mhz'] && $cpuInfo['mhz']) { 1353 | if (abs($cpuInfo['max-mhz'] - $cpuInfo['mhz']) > 300) { 1354 | if ($printJson || $printMachine) { 1355 | print_pre("<<< WARNING >>> CPU is in powersaving mode? Set CPU governor to 'performance'! Fire up CPU and recalculate MHz!" . PHP_EOL); 1356 | } else { 1357 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nCPU is in powersaving mode? Set CPU governor to 'performance'!\n Fire up CPU and recalculate MHz!\n$line" . PHP_EOL); 1358 | } 1359 | // TIME WASTED HERE 1360 | $cpuInfo = getCpuInfo(true); 1361 | } 1362 | } 1363 | 1364 | /** Recalc loop limits if max_execution_time less than needed */ 1365 | $maxTime = ini_get('max_execution_time'); 1366 | $needTime = $defaultTimeLimit; 1367 | $pv = $phpversion[0] . '.' . $phpversion[1]; 1368 | if (isset($loopMaxPhpTimes[$pv])) { 1369 | $needTime = $loopMaxPhpTimes[$pv]; 1370 | } elseif (isset($loopMaxPhpTimes[$phpversion[0]])) { 1371 | $needTime = $loopMaxPhpTimes[$phpversion[0]]; 1372 | } 1373 | 1374 | if ($debugMode) { 1375 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Need time: " .$needTime . "; Max time: " .$maxTime . PHP_EOL); 1376 | } 1377 | 1378 | $memoryLimitPhp = getPhpMemoryLimitBytes(); 1379 | $memoryLimitSystem = getSystemMemoryFreeLimitBytes(); 1380 | if ($debugMode) { 1381 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Available memory in system: " . convert($memoryLimitSystem) . PHP_EOL); 1382 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Available memory for php : " . convert($memoryLimitPhp) . PHP_EOL); 1383 | } 1384 | 1385 | if ($memoryLimitSystem < 0) { 1386 | // Can't read /proc/meminfo? Drop it. 1387 | $memoryLimitSystem = $memoryLimitPhp; 1388 | if ($debugMode) { 1389 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Can't read available memory in system. Set it equal to PHP's." . PHP_EOL); 1390 | } 1391 | } 1392 | 1393 | $memoryLimit = min($memoryLimitPhp, $memoryLimitSystem); 1394 | $memoryLimitMb = convert($memoryLimit); 1395 | if ($debugMode) { 1396 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Selected memory for php : " . $memoryLimitMb . PHP_EOL); 1397 | } 1398 | 1399 | if (!$memoryLimit || $memoryLimit == '0' || (int)$memoryLimit < $testMemoryMin) { 1400 | print_pre("{$colorRed}<<< ERROR >>>{$colorReset} Available memory is set too low: ".convert($memoryLimitMb).".\nThis is lower than ".convert($testMemoryMin).".\nAbort execution!" . PHP_EOL); 1401 | if ($printJson) { 1402 | print("\"messages_count\": {$messagesCnt},\n"); 1403 | print("\"end\":true\n}" . PHP_EOL); 1404 | } 1405 | exit(1); 1406 | } 1407 | 1408 | // Run tests or not? 1409 | if (!$outputTestsList && !$showOnlySystemInfo) { 1410 | 1411 | // Adjust array tests limits 1412 | if ($memoryLimit < $testMemoryFull) { 1413 | 1414 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nAvailable memory " . $memoryLimitMb 1415 | . " is less than required to run full set of tests: " . convert($testMemoryFull) 1416 | . ".\n Recalculate tests parameters to fit in memory limits." 1417 | . "\n$line" . PHP_EOL); 1418 | if ($debugMode) { 1419 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Original memory limit for php : " . convert($originMemoryLimit) . PHP_EOL); 1420 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Calculated memory limit for php: " . convert($defaultMemoryLimit) . PHP_EOL); 1421 | } 1422 | 1423 | foreach ($testsMemoryLimits as $testName => $limitMb) { 1424 | 1425 | $limitBytes = $limitMb * 1024 * 1024; 1426 | 1427 | // Do we need to check and recalculate limits here? 1428 | // Or we need to fit memory anyway? 1429 | if ($limitBytes > $memoryLimit) { 1430 | 1431 | $factor = 1.0 * ($limitBytes - $memoryLimit) / $limitBytes; 1432 | if ($debugMode) { 1433 | print_pre("{$colorGray}<<< DEBUG >>>{$colorReset} Test: {$testName}, need memory: {$limitMb}, memory factor: " . number_format($factor, 6, '.', '') . PHP_EOL); 1434 | } 1435 | 1436 | // Only if memory not enough, and memory available 1437 | if ($factor > 0 && $factor < 1.0) { 1438 | 1439 | // Special hack for php-7.x 1440 | // New string classes, new memory allocator 1441 | // Consumes more, allocate huge blocks 1442 | if ((int)$phpversion[0] >= 7) $factor *= 1.1; 1443 | 1444 | $diff = (int)($factor * $testsLoopLimits[ $testName ]); 1445 | if (in_array($testName, array('13_array_loop', '14_array_loop'))) { 1446 | $arrayDimensionLimit = (int)($factor * $arrayDimensionLimit); 1447 | $diff = 0; 1448 | } 1449 | 1450 | $testsLoopLimits[$testName] -= $diff; 1451 | } 1452 | 1453 | } 1454 | } 1455 | 1456 | } 1457 | if ($debugMode) print_pre("recalculate limits: " . $recalculateLimits); 1458 | if ($recalculateLimits) { 1459 | 1460 | if (isset($dumbTestMaxPhpTimes[$pv])) { 1461 | $dumbTestTimeMax = $dumbTestMaxPhpTimes[$pv]; 1462 | } elseif (isset($dumbTestMaxPhpTimes[$phpversion[0]])) { 1463 | $dumbTestTimeMax = $dumbTestMaxPhpTimes[$phpversion[0]]; 1464 | } 1465 | 1466 | if ($cpuInfo['mhz'] > $loopMaxPhpTimesMHz) { 1467 | // In reality it's non-linear, but that is best we can suggest 1468 | $needTime *= 1.0 / $cpuInfo['mhz'] * $loopMaxPhpTimesMHz; 1469 | $dumbTestTimeMax *= 1.0 / $cpuInfo['mhz'] * $loopMaxPhpTimesMHz; 1470 | 1471 | if ($printDumbTest) { 1472 | print_pre("CPU is faster than base one, need time recalc: " .$needTime . PHP_EOL); 1473 | } 1474 | } 1475 | 1476 | $factor = 1.0; 1477 | // Don't bother if time is unlimited 1478 | if ($maxTime) { 1479 | // Adjust more only if maxTime too small 1480 | if ($needTime > $maxTime) { 1481 | $factor = 1.0 * $maxTime / $needTime; 1482 | } 1483 | } 1484 | 1485 | if ($factor < 1.0) { 1486 | // Adjust more only if HZ too small 1487 | if ($cpuInfo['mhz'] < $loopMaxPhpTimesMHz) { 1488 | $factor *= 1.0 * $cpuInfo['mhz'] / $loopMaxPhpTimesMHz; 1489 | } 1490 | 1491 | // TIME WASTED HERE 1492 | $dumbTestTime = dumb_test_Functions(); 1493 | // Debug 1494 | if ($printDumbTest) { 1495 | print_pre("Dumb test time: " .$dumbTestTime . PHP_EOL 1496 | . "Dumb test time max: " .$dumbTestTimeMax . PHP_EOL); 1497 | } 1498 | if ($dumbTestTime > $dumbTestTimeMax) { 1499 | $factor *= 1.0 * $dumbTestTimeMax / $dumbTestTime; 1500 | } 1501 | } 1502 | if ($debugMode) { 1503 | // TIME WASTED HERE 1504 | $dumbTestTime = dumb_test_Functions(); 1505 | // Debug 1506 | if ($printDumbTest) { 1507 | print_pre("Dumb test time: " .$dumbTestTime . PHP_EOL 1508 | . "Dumb test time max: " .$dumbTestTimeMax . PHP_EOL); 1509 | } 1510 | } 1511 | 1512 | $cpuModel = $cpuInfo['model']; 1513 | if (strpos($cpuModel, 'Atom') !== false || strpos($cpuInfo['model'], 'ARM') !== false) { 1514 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nYour processor '{$cpuModel}' have too low performance!\n$line" . PHP_EOL); 1515 | $factor = 1.0/3; 1516 | } 1517 | 1518 | if ($factor < 1.0) { 1519 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nMax execution time is less than needed for tests!\nWill try to reduce tests time as much as possible.\nFactor is: '$factor'\n$line" . PHP_EOL); 1520 | foreach ($testsLoopLimits as $tst => $loops) { 1521 | $testsLoopLimits[$tst] = (int)($loops * $factor); 1522 | } 1523 | } 1524 | 1525 | } // recalculate time limits 1526 | 1527 | } // Not only show tests names or system info. or not? 1528 | 1529 | /** ---------------------------------- Common functions for tests -------------------------------------------- */ 1530 | 1531 | /** 1532 | * @return array((int)seconds, (str)seconds, (str)operations/sec), (str)opterations/MHz) 1533 | */ 1534 | function format_result_test($diffSeconds, $opCount, $memory = 0) 1535 | { 1536 | global $cpuInfo, $rawValues4json; 1537 | if ($diffSeconds) { 1538 | $ops = $opCount / $diffSeconds; 1539 | $ops_v = convert_si($ops); 1540 | $ops_u = prefix_si($ops); 1541 | 1542 | $opmhz = 0; 1543 | if (!empty($cpuInfo['mhz'])) { 1544 | $opmhz = $ops / $cpuInfo['mhz']; 1545 | } 1546 | $opmhz_v = convert_si($opmhz); 1547 | $opmhz_u = prefix_si($opmhz); 1548 | 1549 | if ($rawValues4json) { 1550 | return array($diffSeconds, $diffSeconds, 1551 | $ops, $opmhz, $memory 1552 | ); 1553 | } 1554 | return array($diffSeconds, number_format($diffSeconds, 3, '.', ''), 1555 | number_format($ops_v, 2, '.', '') . ' ' . $ops_u, 1556 | $opmhz ? number_format($opmhz_v, 2, '.', '') . ' ' . $opmhz_u : '-.-- ' . $opmhz_u, 1557 | convert($memory) 1558 | ); 1559 | } else { 1560 | if ($rawValues4json) { 1561 | return array(0, 0, 0, 0, 0); 1562 | } 1563 | return array(0, '0.000', 'x.xx ', 'x.xx ', 0); 1564 | } 1565 | } 1566 | 1567 | 1568 | /** ---------------------------------- Tests functions -------------------------------------------- */ 1569 | 1570 | if (is_file('common.inc')) { 1571 | include_once 'common.inc'; 1572 | } else { 1573 | print_pre("$line\n{$colorRed}<<< ERROR >>>{$colorReset}\nMissing file 'common.inc' with common tests!\n$line"); 1574 | if ($printJson) { 1575 | print("\"messages_count\": {$messagesCnt},\n"); 1576 | print("\"end\":true\n}" . PHP_EOL); 1577 | } 1578 | exit(1); 1579 | } 1580 | if ((int)$phpversion[0] >= 5) { 1581 | if (is_file('php5.inc')) { 1582 | include_once 'php5.inc'; 1583 | } else { 1584 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nMissing file 'php5.inc' with try/Exception/catch loop test!\n It matters only for php version 5+.\n$line"); 1585 | } 1586 | } 1587 | 1588 | if ((int)$phpversion[0] >= 7) { 1589 | if (is_file('php7.inc')) { 1590 | include_once 'php7.inc'; 1591 | } else { 1592 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nMissing file 'php7.inc' with PHP 7 new features tests!\n It matters only for php version 7+.\n$line"); 1593 | } 1594 | } 1595 | 1596 | if ((int)$phpversion[0] >= 8) { 1597 | if (is_file('php8.inc')) { 1598 | include_once 'php8.inc'; 1599 | } else { 1600 | print_pre("$line\n{$colorYellow}<<< WARNING >>>{$colorReset}\nMissing file 'php8.inc' with PHP 8 new features tests!\n It matters only for php version 8+.\n$line"); 1601 | } 1602 | } 1603 | 1604 | $functions = get_defined_functions(); 1605 | $availableFunctions =$functions['user']; 1606 | sort($availableFunctions); 1607 | 1608 | // fiter in tests 1609 | function filter_in_name_by_pattern($key) 1610 | { 1611 | global $selectedTests, $debugMode, $availableFunctions; 1612 | $var = $availableFunctions[$key]; 1613 | $ret = 0; 1614 | foreach ($selectedTests as $pattern){ 1615 | // simple test - str in name 1616 | $c=strpos($var,$pattern); 1617 | if ($debugMode) { 1618 | $d=var_export($c,true); 1619 | print("Search '$pattern' inside '$var':$d\n"); 1620 | } 1621 | if ($c!==false) { 1622 | $ret = 1; 1623 | break; 1624 | }; 1625 | } 1626 | //nothing found - skipping 1627 | if ($debugMode) print("Will return $ret\n"); 1628 | if (!$ret) unset($availableFunctions[$key]); 1629 | return $ret; 1630 | } 1631 | // fiter out tests 1632 | function filter_out_name_by_pattern($key) 1633 | { 1634 | global $skipTests, $debugMode, $availableFunctions; 1635 | $var = $availableFunctions[$key]; 1636 | $ret = 1; 1637 | foreach ($skipTests as $pattern){ 1638 | // simple test - str in name 1639 | $c=strpos($var,$pattern); 1640 | if ($debugMode) { 1641 | $d=var_export($c,true); 1642 | print("Search '$pattern' inside '$var':$d\n"); 1643 | } 1644 | if ($c!==false) { 1645 | $ret = 0; 1646 | break; 1647 | }; 1648 | } 1649 | //nothing found - not skipping 1650 | if ($debugMode) print("Will return $ret\n"); 1651 | if (!$ret) unset($availableFunctions[$key]); 1652 | return $ret; 1653 | } 1654 | if ($selectedTests) array_filter($availableFunctions, "filter_in_name_by_pattern",ARRAY_FILTER_USE_KEY); 1655 | if ($skipTests) array_filter($availableFunctions, "filter_out_name_by_pattern",ARRAY_FILTER_USE_KEY); 1656 | /** ------------------------------- Early checks ------------------------------- */ 1657 | 1658 | if ($outputTestsList) { 1659 | if (!$printJson) { 1660 | if (php_sapi_name() != 'cli') { 1661 | print("
");
1662 | 		}
1663 | 		print("\nAvailable tests:\n");
1664 | 		foreach ($availableFunctions as $user) {
1665 | 			if (strpos($user, 'test_') === 0) {
1666 | 				$testName = str_replace('test_', '', $user);
1667 | 				print($testName . PHP_EOL);
1668 | 			}
1669 | 		}
1670 | 		if (php_sapi_name() != 'cli') {
1671 | 			print("
\n"); 1672 | } 1673 | } else { 1674 | print("tests: [".PHP_EOL); 1675 | $a = array(); 1676 | foreach ($availableFunctions as $user) { 1677 | if (strpos($user, 'test_') === 0) { 1678 | $testName = str_replace('test_', '', $user); 1679 | $a[] = $testName; 1680 | } 1681 | } 1682 | print(join(',', $a)); 1683 | print("]".PHP_EOL); 1684 | } 1685 | 1686 | if ($printJson) { 1687 | print("\"messages_count\": {$messagesCnt},\n"); 1688 | print("\"end\":true\n}" . PHP_EOL); 1689 | } 1690 | exit(0); 1691 | } 1692 | 1693 | /** ---------------------------------- Common code -------------------------------------------- */ 1694 | 1695 | $has_mbstring = "{$colorGreen}yes{$colorReset}"; 1696 | if (!function_exists('mb_strlen')) { 1697 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Extension 'mbstring' not loaded or not compiled! Multi-byte string tests will produce empty result!"); 1698 | $has_mbstring = "{$colorRed}no{$colorReset}"; 1699 | } 1700 | $has_json = "{$colorGreen}yes{$colorReset}"; 1701 | if (!function_exists('json_encode')) { 1702 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Extension 'json' not loaded or not compiled! JSON tests will produce empty result!"); 1703 | $has_json = "{$colorRed}no{$colorReset}"; 1704 | if ($printJson) { 1705 | print_pre("{$colorRed}<<< ERROR >>>{$colorReset} Extension 'json' is mandatory for JSON output!"); 1706 | print("\"messag0es_count\": {$messagesCnt},\n"); 1707 | print("\"end\":true\n}" . PHP_EOL); 1708 | exit(-1); 1709 | } 1710 | } 1711 | $has_pcre = "{$colorGreen}yes{$colorReset}"; 1712 | if (!function_exists('preg_match')) { 1713 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Extension 'pcre' not loaded or not compiled! Regex tests will procude empty result!"); 1714 | $has_pcre = "{$colorRed}no{$colorReset}"; 1715 | } 1716 | $has_opcache = "{$colorGreen}no{$colorReset}"; 1717 | if (extension_loaded('Zend OPcache')) { 1718 | $has_opcache = "{$colorYellow}yes{$colorReset}"; 1719 | } 1720 | $has_xcache = "{$colorYellow}no{$colorReset}"; 1721 | if (extension_loaded('XCache')) { 1722 | $has_xcache = "{$colorYellow}yes{$colorReset}"; 1723 | } 1724 | $has_apc = "{$colorGreen}no{$colorReset}"; 1725 | if (extension_loaded('apc')) { 1726 | $has_apc = "{$colorYellow}yes{$colorReset}"; 1727 | } 1728 | $has_apcu = "{$colorYellow}no{$colorReset}"; 1729 | if (extension_loaded('apcu')) { 1730 | $has_apcu = "{$colorGreen}yes{$colorReset}"; 1731 | } 1732 | $has_shmop = "{$colorYellow}no{$colorReset}"; 1733 | if (extension_loaded('shmop')) { 1734 | $has_shmop = "{$colorGreen}yes{$colorReset}"; 1735 | } 1736 | $has_sodium = "{$colorYellow}no{$colorReset}"; 1737 | if (extension_loaded('sodium')) { 1738 | $has_sodium = "{$colorGreen}yes{$colorReset}"; 1739 | } 1740 | $has_memcache = "{$colorYellow}no{$colorReset}"; 1741 | if (extension_loaded('memcache')) { 1742 | $has_memcache = "{$colorGreen}yes{$colorReset}"; 1743 | include_once('memcache.inc'); 1744 | $v=get_memcached_version(); 1745 | if ($v) define('MEMCACHE_VERSION',$v); 1746 | else define('MEMCACHE_VERSION','-.-.-'); 1747 | } 1748 | $has_redis = "{$colorYellow}no{$colorReset}"; 1749 | if (extension_loaded('memcache')) { 1750 | $has_redis = "{$colorGreen}yes{$colorReset}"; 1751 | include_once('redis.inc'); 1752 | $v=get_redis_version(); 1753 | if ($v) define('REDIS_VERSION',$v); 1754 | else define('REDIS_VERSION','-.-.-'); 1755 | } 1756 | $has_sqlite3 = "{$colorYellow}no{$colorReset}"; 1757 | if (extension_loaded('sqlite3')) { 1758 | $has_sqlite3 = "{$colorGreen}yes{$colorReset}"; 1759 | include_once('sqlite3.inc'); 1760 | $v=get_sqlite3_version(); 1761 | if ($v) define('SQLITE3_VERSION',$v); 1762 | else define('SQLITE3_VERSION','-.-.-'); 1763 | } 1764 | $has_eacc = "{$colorGreen}no{$colorReset}"; 1765 | if (extension_loaded('eAccelerator')) { 1766 | $has_eacc = "{$colorYellow}yes{$colorReset}"; 1767 | } 1768 | $has_gd = "{$colorYellow}no{$colorReset}"; 1769 | $has_gdgif = "{$colorYellow}no{$colorReset}"; 1770 | $has_gdpng = "{$colorYellow}no{$colorReset}"; 1771 | $has_gdjpg = "{$colorYellow}no{$colorReset}"; 1772 | $has_gdwebp = "{$colorYellow}no{$colorReset}"; 1773 | $has_gdavif = "{$colorYellow}no{$colorReset}"; 1774 | if (function_exists('imagegif')) { 1775 | $has_gdgif = "{$colorGreen}yes{$colorReset}"; 1776 | } 1777 | if (function_exists('imagepng')) { 1778 | $has_gdpng = "{$colorGreen}yes{$colorReset}"; 1779 | } 1780 | if (function_exists('imagejpeg')) { 1781 | $has_gdjpg = "{$colorGreen}yes{$colorReset}"; 1782 | } 1783 | if (function_exists('imagewebp')) { 1784 | $has_gdwebp = "{$colorGreen}yes{$colorReset}"; 1785 | } 1786 | if (function_exists('imageavif')) { 1787 | $has_gdavif = "{$colorGreen}yes{$colorReset}"; 1788 | } 1789 | if (extension_loaded('gd')) { 1790 | $has_gd = "{$colorGreen}yes{$colorReset}"; 1791 | $info = gd_info(); 1792 | if(!defined("GD_VERSION")) define("GD_VERSION",$info["GD Version"]); 1793 | } else { 1794 | define("GD_VERSION","-.-.-"); 1795 | } 1796 | $has_imagick = "{$colorYellow}no{$colorReset}"; 1797 | if (extension_loaded('imagick')) { 1798 | $has_imagick = "{$colorGreen}yes{$colorReset}"; 1799 | $imv = Imagick::getVersion(); 1800 | define("IMG_VERSION", $imv["versionString"]); 1801 | } else { 1802 | define("IMG_VERSION", "-.-.-"); 1803 | } 1804 | $has_xdebug = "{$colorGreen}no{$colorReset}"; 1805 | if (extension_loaded('xdebug')) { 1806 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Extension 'xdebug' loaded! It will affect results and slow things greatly! Even if not enabled!\n"); 1807 | print_pre("{$colorYellow}<<< WARNING >>>{$colorReset} Set xdebug.mode in php.ini / VHost or FPM config / php_admin_value or via cmd '-dxdebug.mode=off' option of PHP executable.\n"); 1808 | $has_xdebug = "{$colorRed}yes{$colorReset}"; 1809 | ini_set("xdebug.mode", "off"); 1810 | ini_set("xdebug.default_enable", 0); 1811 | ini_set("xdebug.remote_autostart", 0); 1812 | ini_set("xdebug.remote_enable", 0); 1813 | ini_set("xdebug.profiler_enable", 0); 1814 | } 1815 | $xdbg_mode = ini_get("xdebug.mode"); 1816 | 1817 | $has_dom = "{$colorYellow}no{$colorReset}"; 1818 | if (extension_loaded('dom')) { 1819 | $has_dom = "{$colorGreen}yes{$colorReset}"; 1820 | } 1821 | $has_simplexml = "{$colorYellow}no{$colorReset}"; 1822 | if (extension_loaded('simplexml')) { 1823 | $has_simplexml = "{$colorGreen}yes{$colorReset}"; 1824 | } 1825 | $has_intl = "{$colorYellow}no{$colorReset}"; 1826 | if (extension_loaded('intl')) { 1827 | $has_intl = "{$colorGreen}yes{$colorReset}"; 1828 | } 1829 | $has_ctype = "{$colorYellow}no{$colorReset}"; 1830 | if (extension_loaded('ctype')) { 1831 | $has_ctype = "{$colorGreen}yes{$colorReset}"; 1832 | } 1833 | $has_iconv = "{$colorYellow}no{$colorReset}"; 1834 | if (extension_loaded('iconv')) { 1835 | $has_iconv = "{$colorGreen}yes{$colorReset}"; 1836 | } 1837 | $has_session = "{$colorYellow}no{$colorReset}"; 1838 | if (extension_loaded('session')) { 1839 | $has_session = "{$colorGreen}yes{$colorReset}"; 1840 | } 1841 | $has_zlib = "{$colorYellow}no{$colorReset}"; 1842 | $has_gzip = "{$colorYellow}no{$colorReset}"; 1843 | if (extension_loaded('zlib')) { 1844 | $has_zlib = "{$colorGreen}yes{$colorReset}"; 1845 | if(function_exists('gzencode')) { 1846 | $has_gzip = "{$colorGreen}yes{$colorReset}"; 1847 | } 1848 | } 1849 | $has_bz2 = "{$colorYellow}no{$colorReset}"; 1850 | if (extension_loaded('bz2')) { 1851 | $has_bz2 = "{$colorGreen}yes{$colorReset}"; 1852 | } 1853 | $has_lz4 = "{$colorYellow}no{$colorReset}"; 1854 | if (extension_loaded('lz4')) { 1855 | $has_lz4 = "{$colorGreen}yes{$colorReset}"; 1856 | } 1857 | $has_snappy = "{$colorYellow}no{$colorReset}"; 1858 | if (extension_loaded('snappy')) { 1859 | $has_snappy = "{$colorGreen}yes{$colorReset}"; 1860 | } 1861 | $has_zstd = "{$colorYellow}no{$colorReset}"; 1862 | if (extension_loaded('zstd')) { 1863 | $has_zstd = "{$colorGreen}yes{$colorReset}"; 1864 | } 1865 | $has_brotli = "{$colorYellow}no{$colorReset}"; 1866 | if (extension_loaded('brotli')) { 1867 | $has_brotli = "{$colorGreen}yes{$colorReset}"; 1868 | } 1869 | 1870 | $has_uuid = "{$colorYellow}no{$colorReset}"; 1871 | if (extension_loaded('uuid')) { 1872 | $has_uuid = "{$colorGreen}yes{$colorReset}"; 1873 | } 1874 | 1875 | $has_jsond = "{$colorYellow}no{$colorReset}"; 1876 | $has_jsond_as_json = "{$colorYellow}no{$colorReset}"; 1877 | if ($jsond = extension_loaded('jsond')) { 1878 | $has_jsond = "{$colorGreen}yes{$colorReset}"; 1879 | } 1880 | if ($jsond && !function_exists('jsond_encode')) { 1881 | $has_jsond_as_json = "{$colorGreen}yes{$colorReset}"; 1882 | } 1883 | 1884 | if (!defined('PCRE_VERSION')) define('PCRE_VERSION', '-.--'); 1885 | if (!defined('ZLIB_VERSION')) define('ZLIB_VERSION', '-.-.-'); 1886 | if (!defined('MEMCACHE_VERSION')) define('MEMCACHE_VERSION', '-.-.-'); 1887 | if (!defined('REDIS_VERSION')) define('REDIS_VERSION', '-.-.-'); 1888 | if (!defined('SQLITE3_VERSION')) define('SQLITE3_VERSION', '-.-.-'); 1889 | if (!defined('LIBXML_DOTTED_VERSION')) define('LIBXML_DOTTED_VERSION', '-.-.-'); 1890 | if (!defined('SODIUM_LIBRARY_VERSION')) define('SODIUM_LIBRARY_VERSION', '-.-.-'); 1891 | if (!defined('INTL_ICU_VERSION')) define('INTL_ICU_VERSION', '-.-'); 1892 | if (!defined('LIBZSTD_VERSION_STRING')) define('LIBZSTD_VERSION_STRING', '-.-.-'); 1893 | 1894 | function print_results_common() 1895 | { 1896 | $total = 0; 1897 | 1898 | global $availableFunctions; 1899 | global $line, $padHeader, $cpuInfo, $padInfo, $scriptVersion, $maxTime, $originTimeLimit, $originMemoryLimit, $cryptAlgoName, $memoryLimitMb; 1900 | global $flushStr, $has_apc, $has_pcre, $has_intl, $has_json, $has_simplexml, $has_dom, $has_mbstring, $has_opcache, $has_xcache; 1901 | global $has_gd, $has_gdgif, $has_gdpng, $has_gdjpg, $has_gdwebp, $has_gdavif; 1902 | global $has_imagick, $has_igb, $has_msg, $has_jsond, $has_jsond_as_json, $has_ctype, $has_iconv, $has_session; 1903 | global $has_zlib, $has_uuid, $has_gzip, $has_bz2, $has_lz4, $has_snappy, $has_zstd, $has_brotli; 1904 | global $has_apcu, $has_shmop, $has_memcache, $has_redis, $has_sodium, $has_sqlite3, $opcache, $has_eacc, $has_xdebug, $xcache, $apcache, $eaccel, $xdebug, $xdbg_mode, $obd_set, $mbover; 1905 | global $showOnlySystemInfo, $padLabel, $functions, $runOnlySelectedTests, $selectedTests, $totalOps; 1906 | global $colorGreen, $colorReset, $colorRed; 1907 | 1908 | if (php_sapi_name() != 'cli') echo "
";
1909 | 	echo "\n$line\n|"
1910 | 		. str_pad("PHP BENCHMARK SCRIPT", $padHeader, " ", STR_PAD_BOTH)
1911 | 		. "|\n$line\n"
1912 | 		. str_pad("Start", $padInfo) . " : " . date("Y-m-d H:i:s") . "\n"
1913 | 		. str_pad("Server name", $padInfo) . " : " . gethostname() . "\n"
1914 | 		. str_pad("Server system", $padInfo) . " : " . php_uname('s') . '/' . php_uname('r') . ' ' . php_uname('m') . "\n"
1915 | 		. str_pad("Platform", $padInfo) . " : " . PHP_OS . "\n"
1916 | 		. str_pad("System", $padInfo) . " : " . get_current_os() . "\n"
1917 | 		. str_pad("CPU", $padInfo) . " :\n"
1918 | 		. str_pad("model", $padInfo, ' ', STR_PAD_LEFT) . " : " . $cpuInfo['model'] . "\n"
1919 | 		. str_pad("cores", $padInfo, ' ', STR_PAD_LEFT) . " : " . $cpuInfo['cores'] . "\n"
1920 | 		. str_pad("available", $padInfo, ' ', STR_PAD_LEFT) . " : " . $cpuInfo['available'] . "\n"
1921 | 		. str_pad("MHz", $padInfo, ' ', STR_PAD_LEFT) . " : " . $cpuInfo['mhz'] . ' MHz' . "\n"
1922 | 		. str_pad("Benchmark version", $padInfo) . " : " . $scriptVersion . "\n"
1923 | 		. str_pad("PHP version", $padInfo) . " : " . PHP_VERSION . "\n"
1924 | 		. str_pad("PHP time limit", $padInfo) . " : " . $originTimeLimit . " sec\n"
1925 | 		. str_pad("Setup time limit", $padInfo) . " : " . $maxTime . " sec\n"
1926 | 		. str_pad("PHP memory limit", $padInfo) . " : " . $originMemoryLimit . "\n"
1927 | 		. str_pad("Setup memory limit", $padInfo) . " : " . $memoryLimitMb . "\n"
1928 | 		. str_pad("Crypt hash algo", $padInfo) . " : " . $cryptAlgoName . "\n"
1929 | 		. str_pad("Loaded modules", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1930 | 		. str_pad("-useful->", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1931 | 		. str_pad("json", $padInfo, ' ', STR_PAD_LEFT) . " : $has_json\n"
1932 | 		. str_pad("mbstring", $padInfo, ' ', STR_PAD_LEFT) . " : $has_mbstring\n"
1933 | 		. str_pad("pcre", $padInfo, ' ', STR_PAD_LEFT) . " : $has_pcre" . ($has_pcre == "{$colorGreen}yes{$colorReset}" ? '; version: ' . PCRE_VERSION : '') . "\n"
1934 | 		. str_pad("simplexml", $padInfo, ' ', STR_PAD_LEFT) . " : $has_simplexml; libxml version: ".LIBXML_DOTTED_VERSION."\n"
1935 | 		. str_pad("dom", $padInfo, ' ', STR_PAD_LEFT) . " : $has_dom\n"
1936 | 		. str_pad("ctype", $padInfo, ' ', STR_PAD_LEFT) . " : $has_ctype\n"
1937 | 		. str_pad("iconv", $padInfo, ' ', STR_PAD_LEFT) . " : $has_iconv\n"
1938 | 		. str_pad("session", $padInfo, ' ', STR_PAD_LEFT) . " : $has_session\n"
1939 | 		. str_pad("intl", $padInfo, ' ', STR_PAD_LEFT) . " : $has_intl" . ($has_intl == "{$colorGreen}yes{$colorReset}" ? '; icu version: ' . INTL_ICU_VERSION : '')."\n"
1940 | 		. str_pad("-optional->", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1941 | 		. str_pad("gd", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gd: version: ". GD_VERSION."\n"
1942 | 		. str_pad("\t- GIF", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gdgif"."\n"
1943 | 		. str_pad("\t- PNG", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gdpng"."\n"
1944 | 		. str_pad("\t- JPG", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gdjpg"."\n"
1945 | 		. str_pad("\t- WEBP", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gdwebp"."\n"
1946 | 		. str_pad("\t- AVIF", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gdavif"."\n"
1947 | 		. str_pad("imagick", $padInfo, ' ', STR_PAD_LEFT) . " : $has_imagick: version: ".IMG_VERSION."\n"
1948 | 		. str_pad("apcu", $padInfo, ' ', STR_PAD_LEFT) . " : $has_apcu;\n"
1949 | 		. str_pad("shmop", $padInfo, ' ', STR_PAD_LEFT) . " : $has_shmop\n"
1950 | 		. str_pad("memcache", $padInfo, ' ', STR_PAD_LEFT) . " : $has_memcache, version: ".MEMCACHE_VERSION.";\n"
1951 | 		. str_pad("redis", $padInfo, ' ', STR_PAD_LEFT) . " : $has_redis, version: ".REDIS_VERSION.";\n"
1952 | 		. str_pad("sqlite3", $padInfo, ' ', STR_PAD_LEFT) . " : $has_sqlite3, version: ".SQLITE3_VERSION.";\n"
1953 | 		. str_pad("sodium", $padInfo, ' ', STR_PAD_LEFT) . " : $has_sodium, version: ".SODIUM_LIBRARY_VERSION.";\n"
1954 | 		. str_pad("-alternative->", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1955 | 		. str_pad("igbinary", $padInfo, ' ', STR_PAD_LEFT) . " : $has_igb\n"
1956 | 		. str_pad("msgpack", $padInfo, ' ', STR_PAD_LEFT) . " : $has_msg\n"
1957 | 		. str_pad("jsond", $padInfo, ' ', STR_PAD_LEFT) . " : $has_jsond\n"
1958 | 		. str_pad("jsond as json >>", $padInfo, ' ', STR_PAD_LEFT) . " : $has_jsond_as_json\n"
1959 | 		. str_pad("-compression->", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1960 | 		. str_pad("zlib", $padInfo, ' ', STR_PAD_LEFT) . " : $has_zlib, version: ".ZLIB_VERSION."\n"
1961 | 		. str_pad("gzip", $padInfo, ' ', STR_PAD_LEFT) . " : $has_gzip\n"
1962 | 		. str_pad("bz2", $padInfo, ' ', STR_PAD_LEFT) . " : $has_bz2\n"
1963 | 		. str_pad("lz4", $padInfo, ' ', STR_PAD_LEFT) . " : $has_lz4\n"
1964 | 		. str_pad("snappy", $padInfo, ' ', STR_PAD_LEFT) . " : $has_snappy\n"
1965 | 		. str_pad("zstd", $padInfo, ' ', STR_PAD_LEFT) . " : $has_zstd, version: ".LIBZSTD_VERSION_STRING."\n"
1966 | 		. str_pad("brotli", $padInfo, ' ', STR_PAD_LEFT) . " : $has_brotli\n"
1967 | 		. str_pad("uuid", $padInfo, ' ', STR_PAD_LEFT) . " : $has_uuid\n"
1968 | 		. str_pad("-affecting->", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1969 | 		. str_pad("opcache", $padInfo, ' ', STR_PAD_LEFT) . " : $has_opcache; enabled: {$opcache}\n"
1970 | 		. str_pad("xcache", $padInfo, ' ', STR_PAD_LEFT) . " : $has_xcache; enabled: {$xcache}\n"
1971 | 		. str_pad("apc", $padInfo, ' ', STR_PAD_LEFT) . " : $has_apc; enabled: {$apcache}\n"
1972 | 		. str_pad("eaccelerator", $padInfo, ' ', STR_PAD_LEFT) . " : $has_eacc; enabled: {$eaccel}\n"
1973 | 		. str_pad("xdebug", $padInfo, ' ', STR_PAD_LEFT) . " : $has_xdebug, enabled: {$xdebug}, mode: '{$xdbg_mode}'\n"
1974 | 		. str_pad("PHP parameters", $padInfo, ' ', STR_PAD_LEFT) . "\n"
1975 | 		. str_pad("open_basedir", $padInfo, ' ', STR_PAD_LEFT) . " : is empty? ".(!$obd_set ? "{$colorGreen}yes{$colorReset}" : "{$colorRed}no{$colorReset}")."\n"
1976 | 		. str_pad("mb.func_overload", $padInfo, ' ', STR_PAD_LEFT) . " : " . ($mbover ? "{$colorRed}{$mbover}{$colorReset}\n" : "{$colorGreen}{$mbover}{$colorReset}\n")
1977 | 		. "$line\n" . $flushStr;
1978 | 	flush();
1979 | 
1980 | 	if (!$showOnlySystemInfo) {
1981 | 
1982 | 		echo str_pad('TEST NAME', $padLabel) . " :"
1983 | 			. str_pad('SECONDS', 9 + 4, ' ', STR_PAD_LEFT) . " |" . str_pad('OP/SEC', 9 + 4, ' ', STR_PAD_LEFT) . " |" . str_pad('OP/SEC/MHz', 9 + 7, ' ', STR_PAD_LEFT) . " |" . str_pad('MEMORY', 10, ' ', STR_PAD_LEFT) . "\n"
1984 | 			. "$line\n" . $flushStr;
1985 | 		flush();
1986 | 
1987 | 		foreach ($availableFunctions as $user) {
1988 | 			if (strpos($user, 'test_') === 0) {
1989 | 				$testName = str_replace('test_', '', $user);
1990 | 				/*if ($runOnlySelectedTests) {
1991 | 					if (!in_array($testName, $selectedTests)) {
1992 | 						continue;
1993 | 					}
1994 | 				}*/
1995 | 				echo str_pad($testName, $padLabel) . " :";
1996 | 				list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = $user();
1997 | 				$total += $resultSec;
1998 | 				echo str_pad($resultSecFmt, 9, ' ', STR_PAD_LEFT) . " sec |" . str_pad($resultOps, 9, ' ', STR_PAD_LEFT) . "Op/s |" . str_pad($resultOpMhz, 9, ' ', STR_PAD_LEFT) . "Ops/MHz |" . str_pad($memory, 10, ' ', STR_PAD_LEFT) . "\n";
1999 | 				echo $flushStr;
2000 | 				flush();
2001 | 			}
2002 | 		}
2003 | 
2004 | 		list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = format_result_test($total, $totalOps, 0);
2005 | 
2006 | 		echo "$line\n"
2007 | 			. str_pad("Total:", $padLabel) . " :";
2008 | 		echo str_pad($resultSecFmt, 9, ' ', STR_PAD_LEFT) . " sec |" . str_pad($resultOps, 9, ' ', STR_PAD_LEFT) . "Op/s |" . str_pad($resultOpMhz, 9, ' ', STR_PAD_LEFT) . "Ops/MHz |" . "\n";
2009 | 		echo str_pad("Current PHP memory usage:", $padLabel) . " :" . str_pad(convert(mymemory_usage()), 12, ' ', STR_PAD_LEFT) . "\n"
2010 | 			// php-4 don't have peak_usage function
2011 | 			. (function_exists('memory_get_peak_usage')
2012 | 				? str_pad("Peak PHP memory usage:", $padLabel) . " :" . str_pad(convert(memory_get_peak_usage()), 12, ' ', STR_PAD_LEFT) . "\n"
2013 | 				: ''
2014 | 			);
2015 | 
2016 | 		echo "$line\n";
2017 | 		echo str_pad("End", $padLabel) . " : " . date("Y-m-d H:i:s") . "\n";
2018 | 
2019 | 	} // show only system info?
2020 | 	else {
2021 | 		echo str_pad("End", $padInfo) . " : " . date("Y-m-d H:i:s") . "\n";
2022 | 	}
2023 | 
2024 | 	if (php_sapi_name() != 'cli')
2025 | 		echo "
\n"; 2026 | flush(); 2027 | } 2028 | 2029 | function print_results_machine() 2030 | { 2031 | $total = 0; 2032 | 2033 | global $availableFunctions; 2034 | global $scriptVersion, $showOnlySystemInfo, $rawValues4json; 2035 | global $functions, $runOnlySelectedTests, $selectedTests, $totalOps; 2036 | 2037 | echo "" 2038 | . "PHP_BENCHMARK_SCRIPT: $scriptVersion\n" 2039 | . "START: " . date("Y-m-d H:i:s") . "\n" 2040 | . "SERVER_name: " . gethostname() . "\n" 2041 | . "SERVER_sys: " . php_uname('s') . '/' . php_uname('r') . ' ' . php_uname('m') . "\n" 2042 | . "SYSTEM: " . get_current_os() . "\n" 2043 | . "PHP_VERSION: " . PHP_VERSION . "\n" 2044 | ; 2045 | flush(); 2046 | 2047 | if (!$showOnlySystemInfo) { 2048 | 2049 | echo "TEST_NAME: SECONDS, OP/SEC, OP/SEC/MHz, MEMORY\n"; 2050 | flush(); 2051 | 2052 | $rawValues4json = true; 2053 | 2054 | foreach ($availableFunctions as $user) { 2055 | if (strpos($user, 'test_') === 0) { 2056 | $testName = str_replace('test_', '', $user); 2057 | if ($runOnlySelectedTests) { 2058 | if (!in_array($testName, $selectedTests)) { 2059 | continue; 2060 | } 2061 | } 2062 | echo $testName . ": "; 2063 | list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = $user(); 2064 | $total += $resultSec; 2065 | echo $resultSecFmt . ", ". $resultOps . ", " . $resultOpMhz . ", " . $memory . "\n"; 2066 | flush(); 2067 | } 2068 | } 2069 | 2070 | list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = format_result_test($total, $totalOps, 0); 2071 | 2072 | echo "TOTAL: " . $resultSecFmt . ", " . $resultOps . ", " . $resultOpMhz . "\n"; 2073 | flush(); 2074 | 2075 | } 2076 | 2077 | echo "END: " . date("Y-m-d H:i:s") . "\n"; 2078 | } 2079 | 2080 | function print_results_json() 2081 | { 2082 | $total = 0; 2083 | 2084 | global $availableFunctions; 2085 | global $scriptVersion, $showOnlySystemInfo, $rawValues4json, $messagesCnt; 2086 | global $functions, $runOnlySelectedTests, $selectedTests, $totalOps; 2087 | 2088 | echo "" 2089 | . "\"php_benchmark_script\": \"$scriptVersion\",\n" 2090 | . "\"start\": \"" . date("Y-m-d H:i:s") . "\",\n" 2091 | . "\"server_name\": \"" . gethostname() . "\",\n" 2092 | . "\"server_sys\": \"" . php_uname('s') . '/' . php_uname('r') . ' ' . php_uname('m') . "\",\n" 2093 | . "\"system\": \"" . get_current_os() . "\",\n" 2094 | . "\"php_version\": \"" . PHP_VERSION . "\",\n" 2095 | ; 2096 | flush(); 2097 | 2098 | if (!$showOnlySystemInfo) { 2099 | 2100 | echo "\"results\": {\n"; 2101 | echo " \"columns\": [ \"test_name\", \"seconds\", \"op\/sec\", \"op\/sec\/MHz\", \"memory\" ],\n"; 2102 | flush(); 2103 | 2104 | $rawValues4json = true; 2105 | 2106 | echo " \"rows\": [\n"; 2107 | foreach ($availableFunctions as $user) { 2108 | if (strpos($user, 'test_') === 0) { 2109 | $testName = str_replace('test_', '', $user); 2110 | if ($runOnlySelectedTests) { 2111 | if (!in_array($testName, $selectedTests)) { 2112 | continue; 2113 | } 2114 | } 2115 | echo " [ \"".$testName . "\", "; 2116 | list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = $user(); 2117 | $total += $resultSec; 2118 | echo $resultSecFmt . ", ". $resultOps . ", " . $resultOpMhz . ", " . $memory . " ],\n"; 2119 | flush(); 2120 | } 2121 | } 2122 | echo " null\n ]\n"; 2123 | echo "},\n"; 2124 | flush(); 2125 | 2126 | list($resultSec, $resultSecFmt, $resultOps, $resultOpMhz, $memory) = format_result_test($total, $totalOps, 0); 2127 | 2128 | echo "\"total\": { \"seconds\": "; 2129 | echo $resultSecFmt . ", \"op\/sec\":" . $resultOps . ", \"op\/sec\/MHz\":" . $resultOpMhz . " },\n"; 2130 | } 2131 | print("\"messages_count\": {$messagesCnt},\n"); 2132 | print("\"end\":\"".date("Y-m-d H:i:s")."\"\n}" . PHP_EOL); 2133 | flush(); 2134 | } 2135 | 2136 | if ($printJson) { 2137 | print_results_json(); 2138 | } else if ($printMachine) { 2139 | print_results_machine(); 2140 | } else { 2141 | print_results_common(); 2142 | } 2143 | -------------------------------------------------------------------------------- /browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rusoft/php-simple-benchmark-script/6cc136cc0fe47fc7375719e850f812f36b8b3522/browser.png -------------------------------------------------------------------------------- /common.inc: -------------------------------------------------------------------------------- 1 | $function) { 15 | if (!function_exists($function)) { 16 | unset($mathFunctions[$key]); 17 | } 18 | } 19 | 20 | $count = $testsLoopLimits['01_math']; 21 | $time_start = get_microtime(); 22 | for ($i = 0; $i < $count; $i++) { 23 | foreach ($mathFunctions as $function) { 24 | $r = call_user_func_array($function, array($i)); 25 | } 26 | } 27 | $totalOps += $count; 28 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 29 | } 30 | 31 | function test_02_String_Concat() 32 | { 33 | global $testsLoopLimits, $stringConcatLoopRepeat, $totalOps; 34 | 35 | $count = $testsLoopLimits['02_string_concat']; 36 | $time_start = get_microtime(); 37 | for ($r = 0; $r < $stringConcatLoopRepeat; ++$r) { 38 | $s = ''; 39 | for ($i = 0; $i < $count; ++$i) { 40 | $s .= ' - Valar dohaeris'; 41 | // Work-around for opCache 8.0+ code elimination, maybe 42 | $s .= ($i % 111) ? PHP_EOL : '!'; 43 | } 44 | } 45 | $totalOps += $count * $stringConcatLoopRepeat; 46 | $memory = mymemory_usage(); 47 | unset($s); 48 | return format_result_test(get_microtime() - $time_start, $count * $stringConcatLoopRepeat, $memory); 49 | } 50 | 51 | function test_03_1_String_Number_Concat() 52 | { 53 | global $testsLoopLimits, $totalOps; 54 | 55 | $count = $testsLoopLimits['03_1_string_number_concat']; 56 | $time_start = get_microtime(); 57 | $s = ''; 58 | for ($i = 0; $i < $count; ++$i) { 59 | $f = $i * 1.0; 60 | $s = 'This is number ' . $i . ' string concat. Число: ' . $f . PHP_EOL; 61 | // Work-around for opCache 8.0+ code elimination, maybe 62 | $s .= (($i % 333 == 0) ? '!' : ''); 63 | } 64 | $totalOps += $count; 65 | $memory = mymemory_usage(); 66 | unset($s); 67 | return format_result_test(get_microtime() - $time_start, $count, $memory); 68 | } 69 | 70 | function test_03_2_String_Number_Format() 71 | { 72 | global $testsLoopLimits, $totalOps; 73 | 74 | $count = $testsLoopLimits['03_2_string_number_format']; 75 | $time_start = get_microtime(); 76 | $s = ''; 77 | for ($i = 0; $i < $count; ++$i) { 78 | $f = $i * 1.0; 79 | $s = "This is number {$i} string format. Число: {$f}\n"; 80 | // Work-around for opCache 8.0+ code elimination, maybe 81 | $s .= (($i % 333 == 0) ? '!' : ''); 82 | } 83 | $totalOps += $count; 84 | $memory = mymemory_usage(); 85 | unset($s); 86 | return format_result_test(get_microtime() - $time_start, $count, $memory); 87 | } 88 | 89 | function test_04_String_Simple_Functions() 90 | { 91 | global $stringTest, $testsLoopLimits, $totalOps; 92 | 93 | $stringFunctions = array('strtoupper', 'strtolower', 'strrev', 'strlen', 'str_rot13', 'ord', 'trim'); 94 | foreach ($stringFunctions as $key => $function) { 95 | if (!function_exists($function)) { 96 | unset($stringFunctions[$key]); 97 | } 98 | } 99 | 100 | $count = $testsLoopLimits['04_string_simple']; 101 | $time_start = get_microtime(); 102 | for ($i = 0; $i < $count; $i++) { 103 | foreach ($stringFunctions as $function) { 104 | $r = call_user_func_array($function, array($stringTest)); 105 | } 106 | } 107 | $totalOps += $count; 108 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 109 | } 110 | 111 | function test_05_String_Multibyte() 112 | { 113 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 114 | 115 | if (!function_exists('mb_strlen')) { 116 | return $emptyResult; 117 | } 118 | 119 | $stringFunctions = array('mb_strtoupper', 'mb_strtolower', 'mb_strlen', 'mb_strwidth'); 120 | foreach ($stringFunctions as $key => $function) { 121 | if (!function_exists($function)) { 122 | unset($stringFunctions[$key]); 123 | } 124 | } 125 | 126 | $count = $testsLoopLimits['05_string_mb']; 127 | $time_start = get_microtime(); 128 | for ($i = 0; $i < $count; $i++) { 129 | foreach ($stringFunctions as $function) { 130 | $r = call_user_func_array($function, array($stringTest)); 131 | } 132 | } 133 | $totalOps += $count; 134 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 135 | } 136 | 137 | function test_06_String_Manipulation() 138 | { 139 | global $stringTest, $testsLoopLimits, $totalOps; 140 | 141 | $stringFunctions = array('addslashes', 'chunk_split', 'metaphone', 'strip_tags', 'soundex', 'wordwrap'); 142 | foreach ($stringFunctions as $key => $function) { 143 | if (!function_exists($function)) { 144 | unset($stringFunctions[$key]); 145 | } 146 | } 147 | 148 | $count = $testsLoopLimits['06_string_manip']; 149 | $time_start = get_microtime(); 150 | for ($i = 0; $i < $count; $i++) { 151 | foreach ($stringFunctions as $function) { 152 | $r = call_user_func_array($function, array($stringTest)); 153 | } 154 | } 155 | $totalOps += $count; 156 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 157 | } 158 | 159 | function test_07_Regex() 160 | { 161 | global $stringTest, $regexPattern, $testsLoopLimits, $totalOps; 162 | 163 | $count = $testsLoopLimits['07_regex']; 164 | $time_start = get_microtime(); 165 | $stringFunctions = array('preg_match', 'preg_split'); 166 | foreach ($stringFunctions as $key => $function) { 167 | if (!function_exists($function)) { 168 | unset($stringFunctions[$key]); 169 | } 170 | } 171 | for ($i = 0; $i < $count; $i++) { 172 | foreach ($stringFunctions as $function) { 173 | $r = call_user_func_array($function, array($regexPattern, $stringTest)); 174 | } 175 | } 176 | $totalOps += $count; 177 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 178 | } 179 | 180 | function test_08_1_Hashing() 181 | { 182 | global $stringTest, $testsLoopLimits, $totalOps; 183 | 184 | $stringFunctions = array('crc32', 'md5', 'sha1'); 185 | foreach ($stringFunctions as $key => $function) { 186 | if (!function_exists($function)) { 187 | unset($stringFunctions[$key]); 188 | } 189 | } 190 | 191 | $count = $testsLoopLimits['08_1_hashing']; 192 | $time_start = get_microtime(); 193 | for ($i = 0; $i < $count; $i++) { 194 | foreach ($stringFunctions as $function) { 195 | $r = call_user_func_array($function, array($stringTest)); 196 | } 197 | } 198 | $totalOps += $count; 199 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 200 | } 201 | 202 | function test_08_2_Crypt() 203 | { 204 | global $stringTest, $cryptSalt, $testsLoopLimits, $totalOps; 205 | 206 | $stringFunctions = array('crypt'); 207 | foreach ($stringFunctions as $key => $function) { 208 | if (!function_exists($function)) { 209 | unset($stringFunctions[$key]); 210 | } 211 | } 212 | 213 | $count = $testsLoopLimits['08_2_crypt']; 214 | $time_start = get_microtime(); 215 | for ($i = 0; $i < $count; $i++) { 216 | foreach ($stringFunctions as $function) { 217 | $r = call_user_func_array($function, array($stringTest, $cryptSalt)); 218 | } 219 | } 220 | $totalOps += $count; 221 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 222 | } 223 | 224 | function test_09_Json_Encode() 225 | { 226 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 227 | 228 | if (!function_exists('json_encode')) { 229 | return $emptyResult; 230 | } 231 | 232 | $data = array( 233 | $stringTest, 234 | 123456, 235 | 123.456, 236 | array(123456), 237 | null, 238 | false, 239 | ); 240 | $obj = new stdClass(); 241 | $obj->fieldStr = 'value'; 242 | $obj->fieldInt = 123456; 243 | $obj->fieldFloat = 123.456; 244 | $obj->fieldArray = array(123456); 245 | $obj->fieldNull = null; 246 | $obj->fieldBool = false; 247 | $data[] = $obj; 248 | 249 | $count = $testsLoopLimits['09_json_encode']; 250 | $time_start = get_microtime(); 251 | for ($i = 0; $i < $count; $i++) { 252 | foreach ($data as $value) { 253 | $r = json_encode($value); 254 | } 255 | } 256 | $totalOps += $count; 257 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 258 | } 259 | 260 | function test_10_Json_Decode() 261 | { 262 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 263 | 264 | if (!function_exists('json_decode')) { 265 | return $emptyResult; 266 | } 267 | 268 | $data = array( 269 | $stringTest, 270 | 123456, 271 | 123.456, 272 | array(123456), 273 | null, 274 | false, 275 | ); 276 | $obj = new stdClass(); 277 | $obj->fieldStr = 'value'; 278 | $obj->fieldInt = 123456; 279 | $obj->fieldFloat = 123.456; 280 | $obj->fieldArray = array(123456); 281 | $obj->fieldNull = null; 282 | $obj->fieldBool = false; 283 | $data[] = $obj; 284 | 285 | foreach ($data as $key => $value) { 286 | $data[$key] = json_encode($value); 287 | } 288 | 289 | $count = $testsLoopLimits['10_json_decode']; 290 | $time_start = get_microtime(); 291 | for ($i = 0; $i < $count; $i++) { 292 | foreach ($data as $value) { 293 | $r = json_decode($value); 294 | } 295 | } 296 | $totalOps += $count; 297 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 298 | } 299 | 300 | function test_11_Serialize() 301 | { 302 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 303 | 304 | if (!function_exists('serialize')) { 305 | return $emptyResult; 306 | } 307 | 308 | $data = array( 309 | $stringTest, 310 | 123456, 311 | 123.456, 312 | array(123456), 313 | null, 314 | false, 315 | ); 316 | $obj = new stdClass(); 317 | $obj->fieldStr = 'value'; 318 | $obj->fieldInt = 123456; 319 | $obj->fieldFloat = 123.456; 320 | $obj->fieldArray = array(123456); 321 | $obj->fieldNull = null; 322 | $obj->fieldBool = false; 323 | $data[] = $obj; 324 | 325 | $count = $testsLoopLimits['11_serialize']; 326 | $time_start = get_microtime(); 327 | for ($i = 0; $i < $count; $i++) { 328 | foreach ($data as $value) { 329 | $r = serialize($value); 330 | } 331 | } 332 | $totalOps += $count; 333 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 334 | } 335 | 336 | function test_12_Unserialize() 337 | { 338 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 339 | 340 | if (!function_exists('unserialize')) { 341 | return $emptyResult; 342 | } 343 | 344 | $data = array( 345 | $stringTest, 346 | 123456, 347 | 123.456, 348 | array(123456), 349 | null, 350 | false, 351 | ); 352 | $obj = new stdClass(); 353 | $obj->fieldStr = 'value'; 354 | $obj->fieldInt = 123456; 355 | $obj->fieldFloat = 123.456; 356 | $obj->fieldArray = array(123456); 357 | $obj->fieldNull = null; 358 | $obj->fieldBool = false; 359 | $data[] = $obj; 360 | 361 | foreach ($data as $key => $value) { 362 | $data[$key] = serialize($value); 363 | } 364 | 365 | $count = $testsLoopLimits['12_unserialize']; 366 | $time_start = get_microtime(); 367 | for ($i = 0; $i < $count; $i++) { 368 | foreach ($data as $value) { 369 | $r = unserialize($value); 370 | } 371 | } 372 | $totalOps += $count; 373 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 374 | } 375 | 376 | function test_13_Array_Fill() 377 | { 378 | global $testsLoopLimits, $arrayDimensionLimit, $totalOps; 379 | 380 | $arrayTestLoopLimit = $testsLoopLimits['13_array_loop']; 381 | $time_start = get_microtime(); 382 | $memory = 0; 383 | for ($n = 0; $n < $arrayTestLoopLimit; ++$n) { 384 | $x = array(); 385 | for ($i = 0; $i < $arrayDimensionLimit; ++$i) { 386 | for ($j = 0; $j < $arrayDimensionLimit; ++$j) { 387 | $x[$i][$j] = $i * $j; 388 | } 389 | } 390 | if (!$memory) $memory = mymemory_usage(); 391 | unset($x); 392 | } 393 | $totalOps += pow($arrayDimensionLimit, 2) * $arrayTestLoopLimit; 394 | return format_result_test(get_microtime() - $time_start, pow($arrayDimensionLimit, 2) * $arrayTestLoopLimit, $memory); 395 | } 396 | 397 | function test_14_Array_Range() 398 | { 399 | global $testsLoopLimits, $arrayDimensionLimit, $totalOps; 400 | 401 | $arrayTestLoopLimit = $testsLoopLimits['14_array_loop']; 402 | $time_start = get_microtime(); 403 | $memory = 0; 404 | for ($n = 0; $n < $arrayTestLoopLimit; ++$n) { 405 | $x = array()+range(0, $arrayDimensionLimit); 406 | for ($i = 0; $i < $arrayDimensionLimit; $i++) { 407 | $x[$i] = array()+range(0, $arrayDimensionLimit); 408 | } 409 | if (!$memory) $memory = mymemory_usage(); 410 | unset($x); 411 | } 412 | $totalOps += $arrayDimensionLimit * $arrayTestLoopLimit; 413 | return format_result_test(get_microtime() - $time_start, $arrayDimensionLimit * $arrayTestLoopLimit, $memory); 414 | } 415 | 416 | function test_14_Array_Unset() 417 | { 418 | global $testsLoopLimits, $arrayDimensionLimit, $totalOps; 419 | 420 | $xx = range(0, $arrayDimensionLimit); 421 | for ($i = 0; $i < $arrayDimensionLimit; $i++) { 422 | $xx[$i] = array()+range(0, $arrayDimensionLimit); 423 | } 424 | 425 | $arrayTestLoopLimit = $testsLoopLimits['14_array_loop']; 426 | $time_start = get_microtime(); 427 | $memory = 0; 428 | for ($n = 0; $n < $arrayTestLoopLimit; ++$n) { 429 | $x = array()+$xx; 430 | if (!$memory) $memory = mymemory_usage(); 431 | for ($i = $arrayDimensionLimit-1; $i >= 0; $i--) { 432 | for ($j = 0; $j < $arrayDimensionLimit; $j++) { 433 | unset($x[$i][$j]); 434 | } 435 | unset($x[$i]); 436 | } 437 | unset($x); 438 | } 439 | unset($xx); 440 | $totalOps += pow($arrayDimensionLimit, 2) * $arrayTestLoopLimit; 441 | return format_result_test(get_microtime() - $time_start, pow($arrayDimensionLimit, 2) * $arrayTestLoopLimit, $memory); 442 | } 443 | 444 | function test_15_Clean_Loops() 445 | { 446 | global $testsLoopLimits, $totalOps; 447 | 448 | $count = $testsLoopLimits['15_clean_loops']; 449 | $time_start = get_microtime(); 450 | 451 | // @warning Since 8.0 may be eliminated as dead-code if opcache loaded and enabled 452 | for ($i = 0; $i < $count; ++$i) ; 453 | 454 | $i = 0; 455 | // @warning Since 8.0 may be eliminated as dead-code if opcache loaded and enabled 456 | while ($i++ < $count) ; 457 | 458 | $totalOps += $count * 2; 459 | return format_result_test(get_microtime() - $time_start, $count * 2, mymemory_usage()); 460 | } 461 | 462 | function test_16_Loop_IfElse() 463 | { 464 | global $testsLoopLimits, $totalOps; 465 | 466 | $count = $testsLoopLimits['16_loop_ifelse']; 467 | $time_start = get_microtime(); 468 | $a = 0; 469 | for ($i = 0; $i < $count; $i++) { 470 | $d = $i % 5; 471 | if ($d == 1) { 472 | $a++; 473 | } elseif ($d == 2) { 474 | $a--; 475 | } else if ($d == 3) { 476 | $a++; 477 | } else { 478 | $a--; 479 | } 480 | } 481 | $totalOps += $count; 482 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 483 | } 484 | 485 | function test_17_Loop_Ternary() 486 | { 487 | global $testsLoopLimits, $totalOps; 488 | 489 | $count = $testsLoopLimits['17_loop_ternary']; 490 | $time_start = get_microtime(); 491 | $a = 0; 492 | for ($i = 0; $i < $count; $i++) { 493 | $r = ($i % 2 == 1) 494 | ? (($i % 3 == 1) 495 | ? (($i % 5 == 1) 496 | ? 3 497 | : 2) 498 | : 1) 499 | : 0; 500 | $a += $r; 501 | } 502 | $totalOps += $count; 503 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 504 | } 505 | 506 | function test_18_1_Loop_Defined_Access() 507 | { 508 | global $testsLoopLimits, $totalOps; 509 | 510 | $a = array(0 => 1, 1 => 0); 511 | $r = 0; 512 | 513 | $count = $testsLoopLimits['18_1_loop_def']; 514 | $time_start = get_microtime(); 515 | for ($i = 0; $i < $count; $i++) { 516 | $r += $a[$i % 2]; 517 | } 518 | $totalOps += $count; 519 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 520 | } 521 | 522 | function test_18_2_Loop_Undefined_Access() 523 | { 524 | global $testsLoopLimits, $totalOps; 525 | 526 | $a = array(1 => 1, 3 => 1); 527 | $r = 0; 528 | 529 | $count = $testsLoopLimits['18_2_loop_undef']; 530 | $time_start = get_microtime(); 531 | for ($i = 0; $i < $count; $i++) { 532 | $r += @$a[$i % 5] ? 0 : 1; 533 | } 534 | $totalOps += $count; 535 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 536 | } 537 | 538 | function test_19_Type_Functions() 539 | { 540 | global $testsLoopLimits, $totalOps; 541 | 542 | $ia = array('123456', '0.000001', '0x123', '0644', 456, 123.456); 543 | $fa = array('123456.7890', '123.456e7', '3E-12', '0.0000001', 456, 123.456); 544 | 545 | $count = $testsLoopLimits['19_type_func']; 546 | $time_start = get_microtime(); 547 | for ($i = 0; $i < $count; $i++) { 548 | foreach ($ia as $n) { 549 | $r = intval($n); 550 | } 551 | foreach ($fa as $n) { 552 | $r = floatval($n); 553 | } 554 | } 555 | $totalOps += $count; 556 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 557 | } 558 | 559 | function test_20_Type_Casting() 560 | { 561 | global $testsLoopLimits, $totalOps; 562 | 563 | $ia = array('123456', '0.000001', '0x123', '0644', 456, 123.456); 564 | $fa = array('123456.7890', '123.456e7', '3E-12', '0.0000001', 456, 123.456); 565 | 566 | $count = $testsLoopLimits['20_type_cast']; 567 | $time_start = get_microtime(); 568 | for ($i = 0; $i < $count; $i++) { 569 | foreach ($ia as $n) { 570 | $r = (int)$n; 571 | } 572 | foreach ($fa as $n) { 573 | $r = (float)$n; 574 | } 575 | } 576 | $totalOps += $count; 577 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 578 | } 579 | 580 | function test_33_PhpInfo_Generate() 581 | { 582 | global $testsLoopLimits, $totalOps; 583 | 584 | $count = $testsLoopLimits['33_phpinfo_generate']; 585 | $time_start = get_microtime(); 586 | for ($i = 0; $i < $count; $i++) { 587 | ob_start(); 588 | phpinfo(); 589 | ob_get_clean(); 590 | } 591 | $totalOps += $count; 592 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 593 | } 594 | -------------------------------------------------------------------------------- /compression-brotli.inc: -------------------------------------------------------------------------------- 1 | fieldStr = 'value'; 27 | $obj->fieldInt = 123456; 28 | $obj->fieldFloat = 123.456; 29 | $obj->fieldArray = array(123456); 30 | $obj->fieldNull = null; 31 | $obj->fieldBool = false; 32 | $data[] = $obj; 33 | 34 | $count = $testsLoopLimits['11_igb_serialize']; 35 | $time_start = get_microtime(); 36 | for ($i = 0; $i < $count; $i++) { 37 | foreach ($data as $value) { 38 | $r = igbinary_serialize($value); 39 | } 40 | } 41 | $totalOps += $count; 42 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 43 | } 44 | 45 | function test_12_IGB_Unserialize() 46 | { 47 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 48 | 49 | if (!function_exists('igbinary_unserialize')) { 50 | return $emptyResult; 51 | } 52 | 53 | $data = array( 54 | $stringTest, 55 | 123456, 56 | 123.456, 57 | array(123456), 58 | null, 59 | false, 60 | ); 61 | $obj = new stdClass(); 62 | $obj->fieldStr = 'value'; 63 | $obj->fieldInt = 123456; 64 | $obj->fieldFloat = 123.456; 65 | $obj->fieldArray = array(123456); 66 | $obj->fieldNull = null; 67 | $obj->fieldBool = false; 68 | $data[] = $obj; 69 | 70 | foreach ($data as $key => $value) { 71 | $data[$key] = igbinary_serialize($value); 72 | } 73 | 74 | $count = $testsLoopLimits['12_igb_unserialize']; 75 | $time_start = get_microtime(); 76 | for ($i = 0; $i < $count; $i++) { 77 | foreach ($data as $value) { 78 | $r = igbinary_unserialize($value); 79 | } 80 | } 81 | $totalOps += $count; 82 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 83 | } 84 | -------------------------------------------------------------------------------- /intl.inc: -------------------------------------------------------------------------------- 1 | format($num); 36 | 37 | $fmtC->formatCurrency($num, 'EUR'); 38 | $fmtC->formatCurrency($num, 'RUR'); 39 | 40 | $fmtD->format($num); 41 | $fmtD->setTextAttribute(NumberFormatter::DEFAULT_RULESET, "%in-numerals"); 42 | $fmtD->format($num); 43 | $fmtD->setTextAttribute(NumberFormatter::DEFAULT_RULESET, "%with-words"); 44 | $fmtD->format($num); 45 | 46 | $fmtS->format($num); 47 | } 48 | $totalOps += $count; 49 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 50 | } 51 | 52 | /** 53 | * @since: 5.5.0 54 | */ 55 | function test_32_Intl_Calendar() 56 | { 57 | global $testsLoopLimits, $totalOps, $emptyResult; 58 | 59 | if (!class_exists('IntlCalendar', false)) { 60 | return $emptyResult; 61 | } 62 | if (!class_exists('IntlTimeZone', false)) { 63 | return $emptyResult; 64 | } 65 | 66 | $count = $testsLoopLimits['32_intl_calendar']; 67 | $time_start = get_microtime(); 68 | 69 | $cal = IntlCalendar::createInstance(IntlTimeZone::getGMT()); 70 | 71 | $a = 0; 72 | for ($i = 0; $i < $count; $i++) { 73 | $num = $i / 100.; 74 | $cal->clear(); 75 | $cal->setTime($num); 76 | 77 | if ($cal->inDaylightTime()) $a++; 78 | if ($cal->isWeekend()) $a--; 79 | if ($cal->getMinimalDaysInFirstWeek()) $a++; 80 | 81 | $cal->add(IntlCalendar::FIELD_MONTH, 1); 82 | $cal->add(IntlCalendar::FIELD_DAY_OF_MONTH, 1); 83 | if ($cal->inDaylightTime()) $a--; 84 | if ($cal->isWeekend()) $a++; 85 | if ($cal->getMinimalDaysInFirstWeek()) $a--; 86 | } 87 | $totalOps += $count; 88 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 89 | } -------------------------------------------------------------------------------- /kv-apcu.inc: -------------------------------------------------------------------------------- 1 | available){ 25 | return $emptyResult; 26 | } 27 | 28 | $count = $testsLoopLimits['39_03_kvstorage_apcu']; 29 | $time_start = get_microtime(); 30 | 31 | if ($debugMode) { 32 | var_dump($count); 33 | var_dump($kvstorage); 34 | } 35 | 36 | for ($i = 0; $i < $count; $i++) { 37 | $num = $i / 100.; 38 | $kvstorage->set($i, $num); 39 | $v=$kvstorage->get($i); 40 | if ($v===$num) $kvstorage->del($i); 41 | } 42 | $totalOps += $count; 43 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 44 | } 45 | -------------------------------------------------------------------------------- /kv-memcache.inc: -------------------------------------------------------------------------------- 1 | available){ 24 | return $emptyResult; 25 | } 26 | 27 | $count = $testsLoopLimits['39_05_kvstorage_memcache']; 28 | $time_start = get_microtime(); 29 | 30 | for ($i = 0; $i < $count; $i++) { 31 | $num = $i / 100.; 32 | $kvstorage->set($i, $num); 33 | $v=$kvstorage->get($i); 34 | if ($v===$num) $kvstorage->del($i); 35 | } 36 | $totalOps += $count; 37 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 38 | } 39 | -------------------------------------------------------------------------------- /kv-memory.inc: -------------------------------------------------------------------------------- 1 | set($i, $num); 29 | $v=$kvstorage->get($i); 30 | if ($v===$num) $kvstorage->del($i); 31 | } 32 | $totalOps += $count; 33 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 34 | } 35 | -------------------------------------------------------------------------------- /kv-redis.inc: -------------------------------------------------------------------------------- 1 | available){ 24 | return $emptyResult; 25 | } 26 | 27 | $count = $testsLoopLimits['39_06_kvstorage_redis']; 28 | $time_start = get_microtime(); 29 | 30 | for ($i = 0; $i < $count; $i++) { 31 | $num = $i / 100.; 32 | $kvstorage->set($i, $num); 33 | $v=$kvstorage->get($i); 34 | if ($v===$num) $kvstorage->del($i); 35 | } 36 | $totalOps += $count; 37 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 38 | } 39 | -------------------------------------------------------------------------------- /kv-shmop.inc: -------------------------------------------------------------------------------- 1 | available){ 24 | return $emptyResult; 25 | } 26 | 27 | $count = $testsLoopLimits['39_04_kvstorage_shmop']; 28 | $time_start = get_microtime(); 29 | 30 | for ($i = 0; $i < $count; $i++) { 31 | $num = $i / 100.; 32 | $kvstorage->set($i, $num); 33 | $v=$kvstorage->get($i); 34 | if ($v===$num) $kvstorage->del($i); 35 | } 36 | $totalOps += $count; 37 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 38 | } 39 | -------------------------------------------------------------------------------- /kv-sqlite3-devshm-file.inc: -------------------------------------------------------------------------------- 1 | open($sqlite3_dbpath); 33 | if (!$kvstorage->available){ 34 | print("storage noavail"); 35 | return $emptyResult; 36 | } 37 | 38 | $count = $testsLoopLimits['39_08_kvs_sqlite3_devshm_file']; 39 | $time_start = get_microtime(); 40 | 41 | for ($i = 0; $i < $count; $i++) { 42 | $num = $i / 100.; 43 | $kvstorage->set($i, $num); 44 | $v=$kvstorage->get($i); 45 | if ($v===$num) $kvstorage->del($i); 46 | } 47 | $kvstorage->close(); 48 | $totalOps += $count; 49 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 50 | } 51 | -------------------------------------------------------------------------------- /kv-sqlite3-generic-file.inc: -------------------------------------------------------------------------------- 1 | open($sqlite3_dbpath); 33 | if (!$kvstorage->available){ 34 | print("storage noavail"); 35 | return $emptyResult; 36 | } 37 | 38 | $count = $testsLoopLimits['39_07_kvs_sqlite3_generic_file']; 39 | $time_start = get_microtime(); 40 | 41 | for ($i = 0; $i < $count; $i++) { 42 | $num = $i / 100.; 43 | $kvstorage->set($i, $num); 44 | $v=$kvstorage->get($i); 45 | if ($v===$num) $kvstorage->del($i); 46 | } 47 | $kvstorage->close(); 48 | $totalOps += $count; 49 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 50 | } 51 | -------------------------------------------------------------------------------- /kv-sqlite3-memory-file.inc: -------------------------------------------------------------------------------- 1 | open($sqlite3_dbpath); 33 | if (!$kvstorage->available){ 34 | print("storage noavail"); 35 | return $emptyResult; 36 | } 37 | 38 | $count = $testsLoopLimits['39_09_kvs_sqlite3_memory_file']; 39 | $time_start = get_microtime(); 40 | 41 | for ($i = 0; $i < $count; $i++) { 42 | $num = $i / 100.; 43 | $kvstorage->set($i, $num); 44 | $v=$kvstorage->get($i); 45 | if ($v===$num) $kvstorage->del($i); 46 | } 47 | $kvstorage->close(); 48 | $totalOps += $count; 49 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 50 | } 51 | -------------------------------------------------------------------------------- /kv-xcache.inc: -------------------------------------------------------------------------------- 1 | available){ 24 | return $emptyResult; 25 | } 26 | 27 | $count = $testsLoopLimits['39_02_kvstorage_xcache']; 28 | $time_start = get_microtime(); 29 | 30 | for ($i = 0; $i < $count; $i++) { 31 | $num = $i / 100.; 32 | $kvstorage->set($i, $num); 33 | $v=$kvstorage->get($i); 34 | if ($v===$num) $kvstorage->del($i); 35 | } 36 | $totalOps += $count; 37 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 38 | } 39 | -------------------------------------------------------------------------------- /kvstorage-apcu.inc: -------------------------------------------------------------------------------- 1 | available=true; 11 | if (!function_exists('apcu_store')) 12 | $this->available=false; 13 | if (!function_exists('apcu_fetch')) 14 | $this->available=false; 15 | if (!function_exists('apcu_delete')) 16 | $this->available=false; 17 | } 18 | 19 | public function set($key, $value, $timeout=60){ 20 | return apcu_store($key, $value, $timeout); 21 | } 22 | 23 | public function get($key, $default=null){ 24 | return apcu_exists($key) 25 | ? apcu_fetch($key) 26 | : $default; 27 | } 28 | 29 | public function del($key){ 30 | return apcu_delete($key); 31 | } 32 | } 33 | $kvstorage=new KVStorageApcu(); 34 | -------------------------------------------------------------------------------- /kvstorage-mem.inc: -------------------------------------------------------------------------------- 1 | storage = array(); 12 | } 13 | 14 | public function set($key, $value){ 15 | $this->storage[$key]=$value; 16 | return true; 17 | } 18 | 19 | public function get($key, $default=null){ 20 | if (!isset($this->storage[$key])){ 21 | return $default; 22 | } else { 23 | return $this->storage[$key]; 24 | } 25 | } 26 | 27 | public function del($key){ 28 | if (!isset($this->storage[$key])){ 29 | return false; 30 | } else { 31 | unset($this->storage[$key]); 32 | return true; 33 | } 34 | } 35 | } 36 | $kvstorage=new KVStorageInMemory(); 37 | -------------------------------------------------------------------------------- /kvstorage-memcache.inc: -------------------------------------------------------------------------------- 1 | available=true; 12 | if (!class_exists('Memcache')) 13 | $this->available=false; 14 | if (!function_exists('get_memcache_object')) include('memcache.inc'); 15 | $this->object=get_memcache_object(); 16 | } 17 | 18 | public function set($key, $value, $timeout=60){ 19 | return $this->object->set($key, $value,0, $timeout); 20 | } 21 | 22 | public function get($key, $default=null){ 23 | return $this->object->get($key); 24 | } 25 | 26 | public function del($key){ 27 | return $this->object->delete($key); 28 | } 29 | } 30 | $kvstorage=new KVStorageMemcache(); 31 | -------------------------------------------------------------------------------- /kvstorage-redis.inc: -------------------------------------------------------------------------------- 1 | available=true; 12 | if (!class_exists('Redis')) 13 | $this->available=false; 14 | if (!function_exists('get_redis_object')) include('redis.inc'); 15 | $this->object=get_redis_object(); 16 | } 17 | 18 | public function set($key, $value, $timeout=60){ 19 | return $this->object->set($key, $value, $timeout); 20 | } 21 | 22 | public function get($key, $default=null){ 23 | return $this->object->get($key); 24 | } 25 | 26 | public function del($key){ 27 | return $this->object->expire($key,0); 28 | } 29 | } 30 | $kvstorage=new KVStorageRedis(); 31 | -------------------------------------------------------------------------------- /kvstorage-shmop.inc: -------------------------------------------------------------------------------- 1 | available=true; 11 | if (!function_exists('shmop_open')) 12 | $this->available=false; 13 | if (!function_exists('shmop_write')) 14 | $this->available=false; 15 | if (!function_exists('shmop_read')) 16 | $this->available=false; 17 | if (!function_exists('shmop_size')) 18 | $this->available=false; 19 | if (!function_exists('shmop_close')) 20 | $this->available=false; 21 | } 22 | 23 | public function set($key, $value, $timeout=60){ 24 | $id=shmop_open(1, "a", 0, 0); 25 | if ($id===false) return false; 26 | $ret=shmop_write($id, $value, 0); 27 | shmop_close($id); 28 | return $ret; 29 | } 30 | 31 | public function get($key, $default=null){ 32 | $id=shmop_open(1, "a", 0, 0); 33 | if ($id===false) return false; 34 | $size=shmop_size($id); 35 | $ret=shmop_read($id,0,$size); 36 | shmop_close($id); 37 | return $ret; 38 | } 39 | 40 | public function del($key){ 41 | $id=shmop_open(1, "a", 0, 0); 42 | if ($id===false) return false; 43 | $ret=shmop_delete($id); 44 | shmop_close($id); 45 | return $ret; 46 | } 47 | } 48 | $kvstorage=new KVStorageShmop(); 49 | -------------------------------------------------------------------------------- /kvstorage-sqlite3.inc: -------------------------------------------------------------------------------- 1 | available=true; 14 | if (!class_exists('SQLite3')) 15 | $this->available=false; 16 | else 17 | $this->db=new SQLite3(':memory:'); 18 | $this->create(); 19 | } 20 | 21 | public function open($full_path){ 22 | if (!$this->available) return false; 23 | if ($this->db===null){ 24 | $this->db=new SQLite3($full_path); 25 | return true; 26 | } 27 | } 28 | 29 | public function close(){ 30 | if (!$this->available) return false; 31 | $this->db->close(); 32 | $this->db=null; 33 | return true; 34 | } 35 | 36 | public function version(){ 37 | if (!$this->available) return '-.-.-'; 38 | $v=$this->db->version(); 39 | if($v) return $v['versionString']; 40 | } 41 | 42 | public function set($key, $value, $timeout=60){ 43 | if (!$this->available) return 0; 44 | if ($this->get($key)) 45 | $this->db->exec("UPDATE {$this->tableName} SET val='$value' WHERE key=$key;"); 46 | else 47 | $this->db->exec("INSERT INTO {$this->tableName} (key, val) VALUES ($key, '$value');"); 48 | return $this->db->changes(); 49 | } 50 | 51 | public function get($key, $default=null){ 52 | if (!$this->available) return false; 53 | $row = $this->db->querySingle("SELECT * FROM {$this->tableName} WHERE key=$key",1); 54 | if ($row) { 55 | return $row['val']; 56 | } 57 | return false; 58 | } 59 | 60 | public function del($key){ 61 | if (!$this->available) return 0; 62 | $this->db->exec("DELETE {$this->tableName} WHERE key=$key;"); 63 | return $this->db->changes(); 64 | } 65 | 66 | public function create(){ 67 | return $this->db->exec("CREATE TABLE `{$this->tableName}`(key INTEGER, val TEXT); CREATE INDEX skey ON {$this->tableName}(key)"); 68 | } 69 | } 70 | //$kvstorage=new KVStorageSqlite3(); 71 | -------------------------------------------------------------------------------- /kvstorage-xcache.inc: -------------------------------------------------------------------------------- 1 | available=true; 11 | if (!function_exists('xcache_set')) 12 | $this->available=false; 13 | if (!function_exists('xcache_get')) 14 | $this->available=false; 15 | if (!function_exists('xcache_unset')) 16 | $this->available=false; 17 | } 18 | 19 | public function set($key, $value, $timeout=60){ 20 | return xcache_set($key, $value, $timeout); 21 | } 22 | 23 | public function get($key, $default=null){ 24 | return xcache_isset($key) 25 | ? xcache_get($key) 26 | : $default; 27 | } 28 | 29 | public function del($key){ 30 | return xcache_unset($key); 31 | } 32 | } 33 | $kvstorage=new KVStorageXcache(); 34 | -------------------------------------------------------------------------------- /memcache-conn.ini: -------------------------------------------------------------------------------- 1 | [memcached] 2 | host = localhost 3 | port = 11211 -------------------------------------------------------------------------------- /memcache.inc: -------------------------------------------------------------------------------- 1 | 'localhost', 12 | 'port'=>11211 13 | ); 14 | if (is_file('memcached-conn.ini')){ 15 | $cfg=parse_ini_file('memcached-conn.ini'); 16 | } 17 | static $m=null; 18 | if ($m===null) 19 | $m = new Memcache; 20 | if ($m->connect($cfg['host'], $cfg['port'])) 21 | return $m; 22 | return false; 23 | } 24 | 25 | function get_memcached_version() 26 | { 27 | $m = get_memcache_object(); 28 | if ($m) 29 | return $m->getVersion(); 30 | return false; 31 | } 32 | -------------------------------------------------------------------------------- /mod-ctype-isdigit.inc: -------------------------------------------------------------------------------- 1 | fieldStr = 'value'; 27 | $obj->fieldInt = 123456; 28 | $obj->fieldFloat = 123.456; 29 | $obj->fieldArray = array(123456); 30 | $obj->fieldNull = null; 31 | $obj->fieldBool = false; 32 | $data[] = $obj; 33 | 34 | $count = $testsLoopLimits['11_msgpack_pack']; 35 | $time_start = get_microtime(); 36 | for ($i = 0; $i < $count; $i++) { 37 | foreach ($data as $value) { 38 | $r = msgpack_pack($value); 39 | } 40 | } 41 | $totalOps += $count; 42 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 43 | } 44 | 45 | function test_12_msgpack_unpack() 46 | { 47 | global $stringTest, $emptyResult, $testsLoopLimits, $totalOps; 48 | 49 | if (!function_exists('msgpack_unpack')) { 50 | return $emptyResult; 51 | } 52 | 53 | $data = array( 54 | $stringTest, 55 | 123456, 56 | 123.456, 57 | array(123456), 58 | null, 59 | false, 60 | ); 61 | $obj = new stdClass(); 62 | $obj->fieldStr = 'value'; 63 | $obj->fieldInt = 123456; 64 | $obj->fieldFloat = 123.456; 65 | $obj->fieldArray = array(123456); 66 | $obj->fieldNull = null; 67 | $obj->fieldBool = false; 68 | $data[] = $obj; 69 | 70 | foreach ($data as $key => $value) { 71 | $data[$key] = msgpack_pack($value); 72 | } 73 | 74 | $count = $testsLoopLimits['12_msgpack_unpack']; 75 | $time_start = get_microtime(); 76 | for ($i = 0; $i < $count; $i++) { 77 | foreach ($data as $value) { 78 | $r = msgpack_unpack($value); 79 | } 80 | } 81 | $totalOps += $count; 82 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 83 | } 84 | -------------------------------------------------------------------------------- /php-options.php: -------------------------------------------------------------------------------- 1 | number; 22 | } 23 | 24 | public function setNumber($new) 25 | { 26 | $this->number = $new; 27 | return $this; 28 | } 29 | } 30 | 31 | class MagicMethods 32 | { 33 | private $number = 0; 34 | 35 | public function __get($name) 36 | { 37 | if ($name === 'number') { 38 | return $this->number; 39 | } 40 | return null; 41 | } 42 | 43 | public function __set($name, $new) 44 | { 45 | if ($name === 'number') { 46 | $this->number = $new; 47 | } 48 | } 49 | } 50 | 51 | /* ------------------------ Tests ------------------------ */ 52 | 53 | function test_21_0_Loop_Exception_None() 54 | { 55 | global $testsLoopLimits, $totalOps; 56 | 57 | $count = $testsLoopLimits['21_loop_except']; 58 | $time_start = get_microtime(); 59 | $a = 0; 60 | for ($i = 0; $i < $count; $i++) { 61 | $a += $i; 62 | if ($i % 10000 == 1) $a = 0; 63 | } 64 | $totalOps += $count; 65 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 66 | } 67 | 68 | function test_21_1_Loop_Exception_Try() 69 | { 70 | global $testsLoopLimits, $totalOps; 71 | 72 | $count = $testsLoopLimits['21_loop_except']; 73 | $time_start = get_microtime(); 74 | $a = 0; 75 | for ($i = 0; $i < $count; $i++) { 76 | try { 77 | $a += $i; 78 | if ($i % 10000 == 1) $a = 0; 79 | } catch (Exception $e) { 80 | } 81 | } 82 | $totalOps += $count; 83 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 84 | } 85 | 86 | function test_21_2_Loop_Exception_Catch() 87 | { 88 | global $testsLoopLimits, $totalOps; 89 | 90 | $count = $testsLoopLimits['21_loop_except']; 91 | $time_start = get_microtime(); 92 | $a = 0; 93 | for ($i = 0; $i < $count; $i++) { 94 | try { 95 | $a += $i; 96 | if ($i % 10000 == 1) $a = 0; 97 | throw new Exception($i); 98 | } catch (Exception $e) { 99 | } 100 | } 101 | $totalOps += $count; 102 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 103 | } 104 | 105 | function test_26_1_Class_Public_Properties() 106 | { 107 | global $testsLoopLimits, $totalOps; 108 | 109 | $c = new PublicProperties(); 110 | $r = 0; 111 | 112 | $count = $testsLoopLimits['26_1_public']; 113 | $time_start = get_microtime(); 114 | for ($i = 0; $i < $count; $i++) { 115 | $r = $c->number; 116 | $c->number = $r + $i; 117 | } 118 | $totalOps += $count; 119 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 120 | } 121 | 122 | function test_26_2_Class_Getter_Setter() 123 | { 124 | global $testsLoopLimits, $totalOps; 125 | 126 | $c = new GetterSetter(); 127 | $r = 0; 128 | 129 | $count = $testsLoopLimits['26_2_getset']; 130 | $time_start = get_microtime(); 131 | for ($i = 0; $i < $count; $i++) { 132 | $r = $c->getNumber(); 133 | $c->setNumber($r + $i); 134 | } 135 | $totalOps += $count; 136 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 137 | } 138 | 139 | function test_26_3_Class_Magic_Methods() 140 | { 141 | global $testsLoopLimits, $totalOps; 142 | 143 | $c = new MagicMethods(); 144 | $r = 0; 145 | 146 | $count = $testsLoopLimits['26_3_magic']; 147 | $time_start = get_microtime(); 148 | for ($i = 0; $i < $count; $i++) { 149 | $r = $c->number; 150 | $c->number = $r + $i; 151 | } 152 | $totalOps += $count; 153 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 154 | } 155 | 156 | // ------------------------- xml ------------------------- 157 | 158 | function test_27_SimpleXml() 159 | { 160 | global $testsLoopLimits, $totalOps, $emptyResult; 161 | 162 | $count = $testsLoopLimits['27_simplexml']; 163 | $time_start = get_microtime(); 164 | 165 | if (!class_exists('SimpleXMLElement', false)) { 166 | return $emptyResult; 167 | } 168 | 169 | $file = 'test.xml'; 170 | if (!@is_readable($file)) { 171 | return $emptyResult; 172 | } 173 | 174 | $xmlStr = file_get_contents($file); 175 | 176 | $a = 0; 177 | for ($i = 0; $i < $count; $i++) { 178 | $rss = new SimpleXMLElement($xmlStr); 179 | if ($rss->channel->title == 'PECL: Latest releases') $a++; 180 | if ($rss->item[1]->title == 'rdkafka 5.0.1') $a++; 181 | } 182 | $totalOps += $count; 183 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 184 | } 185 | 186 | function test_28_DomXml() 187 | { 188 | global $testsLoopLimits, $totalOps, $emptyResult; 189 | 190 | $count = $testsLoopLimits['28_domxml']; 191 | $time_start = get_microtime(); 192 | 193 | if (!class_exists('DOMDocument', false)) { 194 | return $emptyResult; 195 | } 196 | 197 | $file = 'test.xml'; 198 | if (!@is_readable($file)) { 199 | return $emptyResult; 200 | } 201 | 202 | $xmlStr = file_get_contents($file); 203 | 204 | $a = 0; 205 | for ($i = 0; $i < $count; $i++) { 206 | $rss = new DOMDocument('1.0', 'utf-8'); 207 | $rss->loadXML($xmlStr); 208 | 209 | $channels = $rss->getElementsByTagName('channel'); 210 | /** @var \DOMNodeList $channels */ 211 | $channel = $channels->item(0); 212 | /** @var \DOMElement $channel */ 213 | $chTitle = $channel->getElementsByTagName('title'); 214 | /** @var \DOMNodeList $chTitle */ 215 | $chTitle = $chTitle->item(0); 216 | if ($chTitle->nodeValue == 'PECL: Latest releases') $a++; 217 | 218 | $items = $rss->getElementsByTagName('item'); 219 | /** @var \DOMNodeList $items */ 220 | $item = $items->item(1); 221 | /** @var \DOMElement $item */ 222 | $iTitle = $item->getElementsByTagName('title'); 223 | /** @var \DOMNodeList $iTitle */ 224 | $iTitle = $iTitle->item(0); 225 | if ($iTitle->nodeValue == 'rdkafka 5.0.1') $a++; 226 | } 227 | $totalOps += $count; 228 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 229 | } 230 | 231 | // ------------------- DateTime classes --------------------- 232 | 233 | function test_29_DateTime() 234 | { 235 | global $testsLoopLimits, $totalOps, $emptyResult; 236 | 237 | if (!class_exists('DateTime', false)) { 238 | return $emptyResult; 239 | } 240 | if (!class_exists('DateInterval', false)) { 241 | return $emptyResult; 242 | } 243 | 244 | $count = $testsLoopLimits['29_datetime']; 245 | $time_start = get_microtime(); 246 | 247 | $now = new DateTime(); 248 | $day = new DateInterval("P1D"); 249 | $year = new DateInterval("P1Y"); 250 | 251 | $a = 0; 252 | for ($i = 0; $i < $count; $i++) { 253 | $unix = DateTime::createFromFormat("U", $i); 254 | $unix->sub($year); 255 | $unix->add($day); 256 | $diff = $now->diff($unix); 257 | $a += $diff->y % 2; 258 | } 259 | $totalOps += $count; 260 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 261 | } 262 | 263 | 264 | 265 | /** 266 | * @since 5.3.0 267 | */ 268 | function test_31_Intl_Message_Format() 269 | { 270 | global $testsLoopLimits, $totalOps, $emptyResult; 271 | 272 | if (!class_exists('MessageFormatter', false)) { 273 | return $emptyResult; 274 | } 275 | if (!function_exists('msgfmt_create')) { 276 | return $emptyResult; 277 | } 278 | 279 | $count = $testsLoopLimits['31_intl_message_format']; 280 | $time_start = get_microtime(); 281 | 282 | $fmt = new MessageFormatter("en_US", "{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree"); 283 | $fmt2 = new MessageFormatter('en', 'Found {0, plural, =0 {no result} =1 {one result} other {# results}}'); 284 | 285 | for ($i = 0; $i < $count; $i++) { 286 | $num = $i / 123.; 287 | $fmt->format(array($i, 123, $num)); 288 | $fmt2->format(array($i)); 289 | } 290 | $totalOps += $count; 291 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 292 | } 293 | 294 | -------------------------------------------------------------------------------- /php7.inc: -------------------------------------------------------------------------------- 1 | 0, 2 => 2, 4 => 4); 11 | 12 | $count = $testsLoopLimits['22_loop_nullop']; 13 | $time_start = get_microtime(); 14 | for ($i = 0; $i < $count; $i++) { 15 | $r = $a[$i % 5] ?? 0; 16 | } 17 | $totalOps += $count; 18 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 19 | } 20 | 21 | function test_23_Loop_Spaceship_Op() 22 | { 23 | global $testsLoopLimits, $totalOps; 24 | 25 | $count = $testsLoopLimits['23_loop_spaceship']; 26 | $time_start = get_microtime(); 27 | for ($i = 0; $i < $count; $i++) { 28 | $r = $i % 5 <=> 2; 29 | } 30 | $totalOps += $count; 31 | return format_result_test(get_microtime() - $time_start, $count, mymemory_usage()); 32 | } 33 | -------------------------------------------------------------------------------- /php8.inc: -------------------------------------------------------------------------------- 1 | 'localhost', 12 | 'port'=>6379, 13 | 'database'=>2, 14 | ); 15 | if (is_file('redis-conn.ini')){ 16 | $cfg=parse_ini_file('redis-conn.ini'); 17 | } 18 | static $r=null; 19 | if ($r===null) 20 | $r = new Redis; 21 | if ($r->connect($cfg['host'], $cfg['port'])){ 22 | $r->swapdb(0, (int)$cfg['database']); 23 | return $r; 24 | } 25 | return false; 26 | } 27 | 28 | function get_redis_version() 29 | { 30 | $r = get_redis_object(); 31 | if ($r){ 32 | $info = $r->info('server'); 33 | // print_r($info); 34 | return $info['redis_version']; 35 | } 36 | return false; 37 | } 38 | -------------------------------------------------------------------------------- /sqlite3.inc: -------------------------------------------------------------------------------- 1 | close(); $s=null;} 15 | if ($s===null) 16 | $s = new SQLite3($sqlite3_dbpath); 17 | return $s; 18 | return false; 19 | } 20 | 21 | function get_sqlite3_version() 22 | { 23 | $s = get_sqlite3_object(); 24 | if ($s){ 25 | $info = $s->version(); 26 | // print_r($info); 27 | return $info['versionString']; 28 | } 29 | return false; 30 | } 31 | -------------------------------------------------------------------------------- /test.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | https://pecl.php.net 9 | php-webmaster@lists.php.net 10 | php-webmaster@lists.php.net 11 | en-us 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | PECL: Latest releases 30 | The latest releases in PECL. 31 | 32 | 33 | 34 | rdkafka 6.0.0RC1 35 | https://pecl.php.net/package-changelog.php?package=rdkafka&amp;release=6.0.0RC1 36 | 37 | ## Enhancements 38 | - PHP 8.1 support (@ruudk, @remicollet, @nick-zh, @arnaud-lb) 39 | 40 | ## Breaking changes 41 | - Added tentative return types in PHP 8.1 builds 42 | 2021-11-19T14:05:06-05:00 43 | 44 | 45 | rdkafka 5.0.1 46 | https://pecl.php.net/package-changelog.php?package=rdkafka&amp;release=5.0.1 47 | 48 | ## Enhancements 49 | - Add pausePartitions(), resumePartitions() on RdKfaka, RdKafka\KafkaConsumer (#438, @arnaud-lb) 50 | - Clarify error when KafkaConsumer is closed (@zoonru) 51 | 52 | ## Bugfixes 53 | - Fix windows build (#440, @nick-zh) 54 | - Fix crash in RdKafka\Metadata\Topic::getTopic() (#465, @arnaud-lb) 55 | 2021-11-19T13:57:07-05:00 56 | 57 | 58 | gRPC 1.42.0 59 | https://pecl.php.net/package-changelog.php?package=gRPC&amp;release=1.42.0 60 | 61 | - gRPC Core 1.42.0 update 62 | 2021-11-19T08:11:05-05:00 63 | 64 | 65 | swoole 4.8.2 66 | https://pecl.php.net/package-changelog.php?package=swoole&amp;release=4.8.2 67 | 68 | - Fixed memory leak of proc_open hook 69 | - Fixed compatibility of curl native hook with PHP-8.0 and PHP-8.1 70 | - Fixed connection cannot be closed normally in the Manager process 71 | - Fixed Manager process cannot use sendMessage 72 | - Fixed Coroutine\Http\Server received abnormally large POST data parsing 73 | - Fixed cannot exit directly when a fatal error occurs in PHP8 environment 74 | - Adjust coroutine max_concurrency option, only allowed to be used in Co::set() 75 | - Adjust Coroutine::join() to ignore non-exists coroutine 76 | 2021-11-18T01:07:51-05:00 77 | 78 | 79 | imagick 3.6.0 80 | https://pecl.php.net/package-changelog.php?package=imagick&amp;release=3.6.0 81 | 82 | - No change from 3.6.0RC2 83 | 2021-11-17T14:52:30-05:00 84 | 85 | 86 | phalcon 5.0.0alpha7 87 | https://pecl.php.net/package-changelog.php?package=phalcon&amp;release=5.0.0alpha7 88 | 89 | Full changelog can be found at: https://github.com/phalcon/cphalcon/blob/master/CHANGELOG-5.0.md 90 | 91 | ## Changed 92 | - Changes to the `Phalcon\Acl`: 93 | - Renamed `Phalcon\Acl\ComponentAware` to `Phalcon\Acl\ComponentAwareInterface` 94 | - Renamed `Phalcon\Acl\RoleAware` to `Phalcon\Acl\RoleAwareInterface` [#15691](https://github.com/phalcon/cphalcon/issues/15691) 95 | - Changed `require` to `require_once` in `Phalcon\Loader` to avoid conflicts with other loaders [#15489](https://github.com/phalcon/cphalcon/issues/15489) 96 | - Changed `require` to `require_once` in `Phalcon\Cli\Console` and `Phalcon\Mvc\Application` for a bit of extra performance [#15489](https://github.com/phalcon/cphalcon/issues/15489) 97 | - `Phalcon\Collection` has been moved under the `Support` namespace: 98 | - Renamed `Phalcon\Collection` to `Phalcon\Support\Collection` 99 | - Renamed `Phalcon\Collection\Exception` to `Phalcon\Support\Collection\Exception` 100 | - Renamed `Phalcon\Collection\ReadOnly` to `Phalcon\Support\Collection\ReadOnly` 101 | - Renamed `Phalcon\Collection` to `Phalcon\Support\Collection` [#15700](https://github.com/phalcon/cphalcon/issues/15700) 102 | - Changes to `Phalcon\Session\Bag`: 103 | - Changed `Phalcon\Session\Bag::construct` to accept a container instead of internally calling the default 104 | - Changed `Phalcon\Session\Bag::construct` to throw an exception if the container is not specified 105 | - Changed `Phalcon\Session\Bag::init` to store the data in the session [#15494](https://github.com/phalcon/cphalcon/issues/15494) 106 | - Changed `Phalcon\Events\Event::construct()` to allow `source` to be nullable [#15133](https://github.com/phalcon/cphalcon/issues/15133) 107 | - Changes to `Phalcon\Crypt` 108 | - Moved `Phalcon\Crypt\Exception` to `Phalcon\Crypt\Exception\Exception` 109 | - Moved `Phalcon\Crypt\Mismatch` to `Phalcon\Crypt\Exception\Mismatch` 110 | - Changed the ccm/gcm modes to store the `authTag` with the encryption string and process it with the decryption string [#15717](https://github.com/phalcon/cphalcon/issues/15717) 111 | - Created new namespace `Phalcon\Encryption` 112 | - Moved `Phalcon\Crypt` to `Phalcon\Encryption\Crypt` 113 | - Moved `Phalcon\Security` to `Phalcon\Encryption\Security` 114 | - Moved the whole `Security` namespace under `Encryption` 115 | - `Security\JWT\Exceptions\UnsupportedAlgorithmException` to `Encryption\Security\JWT\Exceptions\UnsupportedAlgorithmException` 116 | - `Security\JWT\Exceptions\ValidatorException` to `Encryption\Security\JWT\Exceptions\ValidatorException` 117 | - `Security\JWT\Signer\AbstractSigner` to `Encryption\Security\JWT\Signer\AbstractSigner` 118 | - `Security\JWT\Signer\Hmac` to `Encryption\Security\JWT\Signer\Hmac` 119 | - `Security\JWT\Signer\None` to `Encryption\Security\JWT\Signer\None` 120 | - `Security\JWT\Signer\SignerInterface` to `Encryption\Security\JWT\Signer\SignerInterface` 121 | - `Security\JWT\Token\AbstractItem` to `Encryption\Security\JWT\Token\AbstractItem` 122 | - `Security\JWT\Token\Enum` to `Encryption\Security\JWT\Token\Enum` 123 | - `Security\JWT\Token\Item` to `Encryption\Security\JWT\Token\Item` 124 | - `Security\JWT\Token\Parser` to `Encryption\Security\JWT\Token\Parser` 125 | - `Security\JWT\Token\Signature` to `Encryption\Security\JWT\Token\Signature` 126 | - `Security\JWT\Token\Token` to `Encryption\Security\JWT\Token\Token` 127 | - `Security\JWT\Builder` to `Encryption\Security\JWT\Builder` 128 | - `Security\JWT\Validator` to `Encryption\Security\JWT\Validator` 129 | - `Security\JWT\Validator` to `Encryption\Security\JWT\Validator` 130 | - `Security\Exception` to `Encryption\Security\Exception` 131 | - `Security\Random` to `Encryption\Security\Random` [#15729](https://github.com/phalcon/cphalcon/issues/15729) 132 | - Renamed 133 | - `Phalcon\Crypt\Crypt::getHashAlgo()` to `Phalcon\Crypt\Crypt::getHashAlgorithm()` 134 | - `Phalcon\Crypt\Crypt::getAvailableHashAlgos()` to `Phalcon\Crypt\Crypt::getAvailableHashAlgorithms()` 135 | - `Phalcon\Crypt\Crypt::setHashAlgo()` to `Phalcon\Crypt\Crypt::setHashAlgorithm()` [#15717](https://github.com/phalcon/cphalcon/issues/15717) 136 | - Renamed `Phalcon\Factory\AdapterFactory::getAdapters()` to `Phalcon\Factory\AdapterFactory::getServices()` [#15717](https://github.com/phalcon/cphalcon/issues/15717) 137 | - Changed `Phalcon\Crypt\Crypt::__construct()` to have `useSigning` set to `true` by default [#15717](https://github.com/phalcon/cphalcon/issues/15717) 138 | - Changes to `Phalcon\Config` 139 | - Moved `Phalcon\Config` to `Phalcon\Config\Config` 140 | - Changed `Phalcon\Config\Config::path` by making the `delimiter` parameter a `string` 141 | - Changed `Phalcon\Config\Adapter\Ini::__construct` to not accept `null` as the mode. The default is now `INI_SCANNER_NORMAL` (2) 142 | - Refactored the code for more efficiency and speed [#15720](https://github.com/phalcon/cphalcon/issues/15720) 143 | - Changed `Phalcon\Db\Adapter\AdapterInterface::getInternalHandler()` and `Phalcon\Db\Adapter\Pdo\AbstractPdo::getInternalHandler()` to return `var` instead of `\PDO` for custom adapters with different engines [#15119](https://github.com/phalcon/cphalcon/issues/15119) 144 | - Moved `Phalcon\Filter` to `Phalcon\Filter\Filter`; added more tests [#15726](https://github.com/phalcon/cphalcon/issues/15726) 145 | - Changed `Phalcon\Mvc\Model::getPreparedQuery()` to return `QueryInterface` instead of `Query` [#15562](https://github.com/phalcon/cphalcon/issues/15562) 146 | - Moved `Phalcon\Cache` to `Phalcon\Cache\Cache` [#15728](https://github.com/phalcon/cphalcon/issues/15728) 147 | - Changed `Phalcon\Factory\AdapterFactory` to define the factory exception in `getExceptionClass()` instead of a property. [#15728](https://github.com/phalcon/cphalcon/issues/15728) 148 | - Renamed `Phalcon\Db\Adapter\AbstractAdapter::getSqlVariables()` to `Phalcon\Db\Adapter\AbstractAdapter::getSQLVariables()` to align with the rest of the `getSQL*` methods [#15637](https://github.com/phalcon/cphalcon/issues/15637) 149 | - Moved `Phalcon\Logger` to `Phalcon\Logger\Logger` [#15727](https://github.com/phalcon/cphalcon/issues/15727) 150 | - Changes to `Phalcon\Escaper` 151 | - Moved `Phalcon\Escaper` to `Phalcon\Html\Escaper` 152 | - Moved `Phalcon\Escaper\EscaperInterface` to `Phalcon\Html\Escaper\EscaperInterface` 153 | - Moved `Phalcon\Escaper\Exception` to `Phalcon\Html\Escaper\Exception` 154 | - Deprecated methods (to be removed at a future version) 155 | - `escapeCss()` becomes `css()` 156 | - `escapeJs()`, becomes `js()` 157 | - `escapeHtml()` becomes `html()` 158 | - `escapeHtmlAttr()` becomes `attributes()` 159 | - `escapeUrl()` becomes `url()` 160 | - `setHtmlQuoteType()` becomes `setFlags()` [#15757](https://github.com/phalcon/cphalcon/issues/15757) 161 | - Changed `Phalcon\Encryption\Security::hash()` to also use `password_hash()` and accept `ARGON2*` algorithms [#15731](https://github.com/phalcon/cphalcon/issues/15731) 162 | - Removed uncamelize of `realClassName` in `Phalcon\Mvc\Router\Route::getRoutePaths()` if definition is string to make processing same as if array definition [#15067](https://github.com/phalcon/cphalcon/issues/15067) 163 | - Changed `Phalcon\Validation::getValue()` behavior to get value from `data` if not found in `entity`. [#14203](https://github.com/phalcon/cphalcon/issues/14203) 164 | - Changed `Phalcon\Forms\Form::isValid()` signature: added `whitelist` argument. [#14203](https://github.com/phalcon/cphalcon/issues/14203) 165 | - Changed `Phalcon\Support\Collection\ReadOnly` to `Phalcon\Support\Collection\ReadOnlyCollection` to avoid conflicts with the read-only feature in PHP 8.1 [#15767](https://github.com/phalcon/cphalcon/issues/15767) 166 | - Removed `Phalcon\Text` - replaced by `Phalcon\Support\Helper\Str\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 167 | - Removed `Phalcon\Helper\Arr` - replaced by `Phalcon\Support\Helper\Arr\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 168 | - Removed `Phalcon\Helper\File` - replaced by `Phalcon\Support\Helper\File\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 169 | - Removed `Phalcon\Helper\Json` - replaced by `Phalcon\Support\Helper\Json\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 170 | - Removed `Phalcon\Helper\Number` - replaced by `Phalcon\Support\Helper\Number\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 171 | - Removed `Phalcon\Helper\Str` - replaced by `Phalcon\Support\Helper\Str\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 172 | - Removed references to `Phalcon\Text`, `Phacon\Helper\*` from the code replacing it with `Phalcon\Support\Helper\*` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 173 | - Synchronized tests with `phalcon/phalcon` thus increasing coverage [#15776](https://github.com/phalcon/cphalcon/issues/15776) 174 | - Changed `Phalcon\Assets\Manager` to require a `Phalcon\Html\TagFactory` in its constructor [#15776](https://github.com/phalcon/cphalcon/issues/15776) 175 | 176 | ## Added 177 | - Added more tests in the suite for additional code coverage [#15691](https://github.com/phalcon/cphalcon/issues/15691) 178 | - Added `Phalcon\Events\AbstractEventsAware` class to handle the Events Manager when necessary [#15691](https://github.com/phalcon/cphalcon/issues/15691) 179 | - Added `Phalcon\Acl\Adapter\AdapterInterface::getInheritedRoles()` and `Phalcon\Acl\Adapter\Memory::getInheritedRoles()` that returns the inherited roles based on a passed role name (or all if no parameter supplied) [#15154](https://github.com/phalcon/cphalcon/issues/15154) 180 | - Changes to `Phalcon\Crypt` 181 | - Added `Phalcon\Crypt\Padding\PadInteface` and padding adapters 182 | - `Phalcon\Crypt\Padding\Ansi` 183 | - `Phalcon\Crypt\Padding\Iso10126` 184 | - `Phalcon\Crypt\Padding\IsoIek` 185 | - `Phalcon\Crypt\Padding\Noop` 186 | - `Phalcon\Crypt\Padding\PadInterface` 187 | - `Phalcon\Crypt\Padding\Pkcs7` 188 | - `Phalcon\Crypt\Padding\Space` 189 | - `Phalcon\Crypt\Padding\Zero` 190 | - Added `Phalcon\Crypt\PadFactory` to easily create padding adapters 191 | - Added more tests increasing coverage [#15717](https://github.com/phalcon/cphalcon/issues/15717) 192 | - Added `Phalcon\Cache\Adapter\*::setForever()` and `Phalcon\Storage\Adapter\*::setForever()` to allow storing a key forever [#15485](https://github.com/phalcon/cphalcon/issues/15485) 193 | - Added `Phalcon\Encryption\Security::getHashInformation()` to return information for a hash [#15731](https://github.com/phalcon/cphalcon/issues/15731) 194 | - Added constants `Phalcon\Encryption\Security::CRYPT_ARGON2I` and `Phalcon\Encryption\Security::CRYPT_ARGON2ID` [#15731](https://github.com/phalcon/cphalcon/issues/15731) 195 | - Added `allowEmpty` checks to common validators [#15515](https://github.com/phalcon/cphalcon/issues/15515) 196 | - Added `Phalcon\Forms\Form::getFilteredValue()` to get filtered value without providing entity [#15438](https://github.com/phalcon/cphalcon/issues/15438) 197 | - Added `Phalcon\Forms\Form::setWhitelist()` and `Phalcon\Forms\Form::getWhitelist()` [#14203](https://github.com/phalcon/cphalcon/issues/14203) 198 | - Added `dirtyState` serialization in `Phalcon\Mvc\Model` [#15571](https://github.com/phalcon/cphalcon/issues/15571) 199 | - Added short versions of helpers for `Phalcon\Html\TagFactory` (call service as a method) [#15776](https://github.com/phalcon/cphalcon/issues/15776) 200 | - Added short versions of helpers for `Phalcon\Support\HelperFactory` (call service as a method) [#15776](https://github.com/phalcon/cphalcon/issues/15776) 201 | - Added `Phalcon\Html\Helper\Doctype` helper for `doctype` generation [#15776](https://github.com/phalcon/cphalcon/issues/15776) 202 | - Added `style` or `link` tag option for `Phalcon\Html\Helper\Style` [#15776](https://github.com/phalcon/cphalcon/issues/15776) 203 | 204 | ## Fixed 205 | - Fixed `Query::getExpression()` return type [#15553](https://github.com/phalcon/cphalcon/issues/15553) 206 | - Fixed `Phalcon\Mvc\Model::getRelated()` to correctly return relationships (cached or not) when the foreign key has changed [#15649](https://github.com/phalcon/cphalcon/issues/15649) 207 | - Fixed `Phalcon\Db\Adapter\Pdo\*`, `Phalcon\Mvc\Model` and `Phalcon\Mvc\Model\MetaData\Strategy\Annotations` to treat `BIGINT` numbers as string [#15632](https://github.com/phalcon/cphalcon/issues/15632) 208 | - Fixed `Phalcon\Crypt\Crypt::decrypt()` to correctly calculate the hash when using signed mode [#15717](https://github.com/phalcon/cphalcon/issues/15717) 209 | - Fixed `Phalcon\Mvc\Model\Manager::isVisibleModelProperty()` to correctly check if setting property is visible [#15276](https://github.com/phalcon/cphalcon/issues/15276) 210 | - Fixed `Phalcon\Config\Config::merge` to retain numeric indexes in deep merges [#14705](https://github.com/phalcon/cphalcon/issues/14705) 211 | - Fixed globals (Zephir change) to correctly display string values for global settings in `phpinfo()` [#15269](https://github.com/phalcon/cphalcon/issues/15269) 212 | - Fixed `Phalcon\Storage\Adapter\Redis::getAdapter()` and `Phalcon\Cache\Adapter\Redis::getAdapter()` to accept the connection timeout in the constructor `options` [#15744](https://github.com/phalcon/cphalcon/issues/15744) 213 | - Fixed `Phalcon\Db\Adapter\AbstractAdapter::getSQLVariables()` to return an empty array when initialized [#15637](https://github.com/phalcon/cphalcon/issues/15637) 214 | - Fixed `Phalcon\Cache\Adapter\*` and `Phalcon\Storage\Adapter\*` to delete a key when `set()` is called with a zero or negative TTL [#15485](https://github.com/phalcon/cphalcon/issues/15485) 215 | - Fixed `Phalcon\Db\Adapter\Pdo\Mysql` to not use `PDO::ATTR_EMULATE_PREPARES` and `PDO::ATTR_STRINGIFY_FETCHES` by default. This allows numbers to be returned with resultsets instead of strings for numeric fields [#15361](https://github.com/phalcon/cphalcon/issues/15361) 216 | - Fixed `Phalcon\Validation\Validator\File` to use `messageFileEmpty` [#14928](https://github.com/phalcon/cphalcon/issues/14928) 217 | - Fixed `Phalcon\Db\RawValue` usage bugs in `Phalcon\Mvc\Model::doLowUpdate()` [#15413](https://github.com/phalcon/cphalcon/issues/15413) 218 | - Fixed `type` attribute for stylesheet links [#15776](https://github.com/phalcon/cphalcon/issues/15776) 219 | - Fixed `Phalcon\Debug` to not throw an exception if a URL service is not present [#15381](https://github.com/phalcon/cphalcon/issues/15381) 220 | 221 | ## Removed 222 | - Removed `Phalcon\Kernel` - obsolete [#15776](https://github.com/phalcon/cphalcon/issues/15776) 223 | 2021-11-17T08:21:24-05:00 224 | 225 | 226 | redis 5.3.5RC1 227 | https://pecl.php.net/package-changelog.php?package=redis&amp;release=5.3.5RC1 228 | 229 | phpredis 5.3.5RC1 230 | 231 | This release adds support for exponential backoff w/jitter, experimental 232 | support for detecting a dirty connection, as well as many other fixes 233 | and improvements. 234 | 235 | You can find a detailed list of changes in Changelog.md and package.xml 236 | or by inspecting the git commit logs. 237 | 238 | --- Sponsors --- 239 | 240 | Audiomack - https://audiomack.com 241 | Open LMS - https://openlms.net 242 | BlueHost - https://bluehost.com 243 | Object Cache Pro for WordPress - https://objectcache.pro 244 | Avtandil Kikabidze - https://github.com/akalongman 245 | Zaher Ghaibeh - https://github.com/zaherg 246 | BatchLabs - https://batch.com 247 | Luis Zarate - https://github.com/jlzaratec 248 | 249 | --- 250 | 251 | * Fixed segfault in redis_setoption_handler [692e4e84] (Pavlo Yatsukhnenko) 252 | * Fix masters array in the event of a cluster failover [bce692962] (Bar Shaul) 253 | * Fix 32 bit type error [672dec87f] (Remi Collet) 254 | * Fix radix character in certain locales [89a871e24] (Pavlo Yatsukhnenko) 255 | * ZSTD Validation fix [6a77ef5cd] (Michael Grunder) 256 | * Remove superfluous typecast [b2871471f] (Remi Collet) 257 | 258 | * Updated documentation [f84168657, d017788e7, 20ac84710, 0adf05260, 259 | aee29bf73, 09a095e72, 12ffbf33a, ff331af98, a6bdb8731, 305c15840, 260 | 1aa10e93a, d78b0c79d, c6d37c27c, a6303f5b9, d144bd2c7, a6fb815ef, 9ef862bc6] 261 | (neodisco, Clement Tessier, T. Todua, dengliming, Maxime Cornet, 262 | Emanuele Filannino Michael Grunder) 263 | 264 | * Travis CI Fixes 265 | [a43f4586e, 4fde8178f, 7bd5415ac, fdb8c4bb7, d4f407470] 266 | (Pavlo Yatsukhnenko) 267 | 268 | * Minor fixes/cleanup 269 | [2e190adc1, 99975b592, 9d0879fa5, 22b06457b] 270 | (Pavlo Yatsukhnenko) 271 | 272 | * Fix RedisArray constructor bug 273 | [85dc883ba](https://github.com/phpredis/phpredis/commit/85dc883ba) 274 | ([Pavlo Yatsukhnenko](https://github.com/yatsukhnenko)) 275 | 276 | * Moved to GitHub Actions 277 | [4d2afa786, 502d09fd5] (Pavlo Yatsukhnenko) 278 | 279 | * Use more appropriate array iteration macro 280 | [6008900c2] (Pavlo Yatsukhnenko) 281 | 282 | * Clean up session tests 283 | [ab25ae7f3] (Michael Grunder) 284 | 285 | * RedisArray refactors [1250f0001, 017b2ea7f, 37ed3f079] 286 | (Pavlo Yatsukhnenko) 287 | 288 | * Use zend_parse_parameters_none helper 289 | [a26b14dbe] (Remi Collet) 290 | 291 | * Support for various exponential backoff strategies 292 | [#1986, #1993, 732eb8dcb, 05129c3a3, 5bba6a7fc], 293 | (Nathaniel Braun) 294 | 295 | * Added experimental support for detecting a dirty connection 296 | [d68579562] (Michael Grunder) 297 | 298 | * Created distinct compression utility methods (pack/unpack) 299 | [#1939, da2790aec] (Michael Grunder) 300 | 301 | * SMISMEMBER Command 302 | [#1894, ae2382472, ed283e1ab] (Pavlo Yatsukhnenko) 303 | 2021-11-16T22:19:51-05:00 304 | 305 | 306 | ev 1.1.6RC1 307 | https://pecl.php.net/package-changelog.php?package=ev&amp;release=1.1.6RC1 308 | 309 | Suppressed warnings for UnwindExit and GracefulExit in PHP 8. Thanks to Aaron Piotrowski. 310 | 2021-11-13T13:48:23-05:00 311 | 312 | 313 | imagick 3.6.0RC2 314 | https://pecl.php.net/package-changelog.php?package=imagick&amp;release=3.6.0RC2 315 | 316 | - Fixes: 317 | * Remove deprecated message from Imagick::roundCorners() 318 | - Added: 319 | * Imagick::addNoiseImageWithAttenuate() 320 | 2021-11-11T15:06:12-05:00 321 | 322 | 323 | imagick 3.6.0RC1 324 | https://pecl.php.net/package-changelog.php?package=imagick&amp;release=3.6.0RC1 325 | 326 | - Imagick::getImageInterlaceScheme is undeprecated. It's the appropriate function to call to get the image interlace setting. 327 | - Image formats are now normalised to lower case. 328 | - Imagick::getImageIndex and Imagick::setImageIndex are undeprecated and work on ImageMagick 7. They call MagickGetIteratorIndex and MagickSetIteratorIndex internally. 329 | - Imagick::averageImages is undeprecated. For IM 7 it now calls EvaluateImages(wand->images,MeanEvaluateOperator). 330 | - Imagick::flattenImages is undeprecated. For IM 7 it now calls MagickMergeImageLayers(intern->magick_wand, FlattenLayer); internally. 331 | - Imagick::getImageSize is undeprecated. For IM 7 it now calls MagickGetImageLength internally. 332 | - Imagick::roundCornersImage is undeprecated and available on IM7. 333 | - Fixes: 334 | * Imagick::borderImage() changed internally to use OverCompositeOp rather than AtopCompositeOp for ImageMagick > 7. If you need the old behaviour, please use Imagick::borderImageWithComposite() instead, which allows you to set the composite method. 335 | * Imagick::frameImage() changed internally to use OverCompositeOp rather than AtopCompositeOp for ImageMagick > 7. If you need the old behaviour, please use Imagick::frameImageWithComposite() instead, which allows you to set the composite method. 336 | * Imagick::profileImage() fixed to allow null as second paramter again. If you can't upgrade to this version yet, pass in "", which has the same effect. 337 | * Imagick::ALPHACHANNEL_COPY and Imagick::ALPHACHANNEL_OPAQUE should be available on IM7. 338 | * Imagick::setImageMatteColor() should be available on IM7. 339 | - Added: 340 | * Imagick::borderImageWithComposite() same as Imagick::borderImage() but allows user to set composite operator used. 341 | * Imagick::frameImageWithComposite() same as Imagick::frameImage() but allows user to set composite operator used. 342 | * function Imagick::cannyEdgeImage 343 | * function Imagick::setSeed 344 | * function Imagick::waveletDenoiseImage 345 | * function Imagick::meanShiftImage 346 | * function Imagick::kmeansImage 347 | * function Imagick::rangeThresholdImage 348 | * function Imagick::autoThresholdImage 349 | * function Imagick::bilateralBlurImage 350 | * function Imagick::claheImage 351 | * function Imagick::channelFxImage 352 | * function Imagick::colorThresholdImage 353 | * function Imagick::complexImages 354 | * function Imagick::interpolativeResizeImage 355 | * function Imagick::levelImageColors 356 | * function Imagick::levelizeImage 357 | * function Imagick::orderedDitherImage 358 | * function Imagick::whiteBalanceImage 359 | 2021-11-10T12:23:13-05:00 360 | 361 | 362 | 363 | --------------------------------------------------------------------------------