- 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&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&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&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&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&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&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&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&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&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&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 |
--------------------------------------------------------------------------------