业务代码$selectDate = [];
$first = explode("-", "");
$last = explode("-", "2019-04-16");
$minY = $first[0];
$minM = $first[1];
$maxY = $last[0];
$maxM = $last[1];
$n = 0;
for ($y = $minY; $y <= $maxY; $y++) {
for ($m = 1; $m <= 12; $m++) {
if ($y == $minY && $m < $minM) {
continue;
}
if ($y == $maxY && $m > $maxM) {
break 2;
}
$n++;
array_unshift($selectDate, sprintf("%04d-%02d", $y, $m));
}
}
echo $n."\n";
才24232次循环。
在PHP 5.4.32耗时39.930s(页面直接超时了);
在PHP 5.6.40耗时6.550s;
在PHP 7.2.14耗时3.319s;
strace 对比
服务器配置都是Intel(R) Xeon(R) CPU E5-2680 v3 @ 2.50GHz 4核8G执行strace -c php xx.php# php 5.4.32
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
34.96 0.001530 22 71 brk
31.92 0.001397 12 114 munmap
18.90 0.000827 24 34 25 ioctl
11.13 0.000487 2 242 mmap
2.29 0.000100 1 119 7 open
0.80 0.000035 0 115 close
0.00 0.000000 0 94 read
0.00 0.000000 0 1 write
0.00 0.000000 0 27 3 stat
0.00 0.000000 0 143 fstat
0.00 0.000000 0 14 8 lstat
0.00 0.000000 0 29 3 lseek
0.00 0.000000 0 81 mprotect
0.00 0.000000 0 5 rt_sigaction
0.00 0.000000 0 6 rt_sigprocmask
0.00 0.000000 0 5 1 access
0.00 0.000000 0 1 clone
0.00 0.000000 0 1 execve
0.00 0.000000 0 3 fcntl
0.00 0.000000 0 2 getdents
0.00 0.000000 0 3 getcwd
0.00 0.000000 0 4 gettimeofday
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 4 futex
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.004376 1122 47 total# php 5.6.40
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
49.38 0.000360 2 158 munmap
21.26 0.000155 1 284 mmap
17.83 0.000130 1 123 7 open
11.52 0.000084 1 119 close
0.00 0.000000 0 81 read
0.00 0.000000 0 1 write
0.00 0.000000 0 30 2 stat
0.00 0.000000 0 150 fstat
0.00 0.000000 0 14 8 lstat
0.00 0.000000 0 32 3 lseek
0.00 0.000000 0 83 mprotect
0.00 0.000000 0 24 brk
0.00 0.000000 0 4 rt_sigaction
0.00 0.000000 0 2 rt_sigprocmask
0.00 0.000000 0 28 28 ioctl
0.00 0.000000 0 3 access
0.00 0.000000 0 1 execve
0.00 0.000000 0 2 fcntl
0.00 0.000000 0 4 getdents
0.00 0.000000 0 3 getcwd
0.00 0.000000 0 4 gettimeofday
0.00 0.000000 0 1 getrlimit
0.00 0.000000 0 1 arch_prctl
0.00 0.000000 0 4 futex
0.00 0.000000 0 1 sched_setaffinity
0.00 0.000000 0 2 sched_getaffinity
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.000729 1161 48 total# php 7.2.14
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
97.88 0.927258 5 193880 clock_gettime
0.85 0.008041 34 240 mmap
0.28 0.002688 19 138 mprotect
0.22 0.002090 20 107 9 open
0.17 0.001603 21 77 read
0.16 0.001519 13 114 fstat
0.15 0.001417 16 91 munmap
0.13 0.001271 12 102 close
0.05 0.000431 431 1 readlink
0.03 0.000279 3 81 rt_sigaction
0.02 0.000162 6 26 madvise
0.02 0.000156 7 24 3 stat
0.01 0.000066 3 22 3 lstat
0.01 0.000051 26 2 futex
0.01 0.000049 8 6 3 access
0.00 0.000041 2 22 3 lseek
0.00 0.000041 10 4 getcwd
0.00 0.000033 2 15 15 mkdir
0.00 0.000024 24 1 execve
0.00 0.000022 11 2 write
0.00 0.000022 1 35 brk
0.00 0.000021 1 24 fcntl
0.00 0.000020 20 1 arch_prctl
0.00 0.000000 0 2 rt_sigprocmask
0.00 0.000000 0 17 17 ioctl
0.00 0.000000 0 2 getdents
0.00 0.000000 0 1 unlink
0.00 0.000000 0 1 fchmod
0.00 0.000000 0 5 gettimeofday
0.00 0.000000 0 2 getrlimit
0.00 0.000000 0 2 2 statfs
0.00 0.000000 0 1 gettid
0.00 0.000000 0 1 set_tid_address
0.00 0.000000 0 1 openat
0.00 0.000000 0 1 set_robust_list
------ ----------- ----------- --------- --------- ----------------
100.00 0.947305 195051 55 total
源码对比/* PHP 5.4..32 */
PHP_FUNCTION(array_unshift)
{
zval ***args, /* Function arguments array */
*stack; /* Input stack */
HashTable *new_hash; /* New hashtable for the stack */
HashTable old_hash;
int argc; /* Number of function arguments */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
return;
}
/* Use splice to insert the elements at the beginning. Destroy old
* hashtable and replace it with new one */
new_hash = php_splice(Z_ARRVAL_P(stack), 0, 0, &args[0], argc, NULL);
old_hash = *Z_ARRVAL_P(stack);
if (Z_ARRVAL_P(stack) == &EG(symbol_table)) {
zend_reset_all_cv(&EG(symbol_table) TSRMLS_CC);
}
*Z_ARRVAL_P(stack) = *new_hash;
FREE_HASHTABLE(new_hash);
zend_hash_destroy(&old_hash);
/* Clean up and return the number of elements in the stack */
efree(args);
RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
}/* PHP 5.6.40 */
PHP_FUNCTION(array_unshift)
{
zval ***args, /* Function arguments array */
*stack; /* Input stack */
int argc; /* Number of function arguments */
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a+", &stack, &args, &argc) == FAILURE) {
return;
}
/* Use splice to insert the elements at the beginning. */
php_splice(Z_ARRVAL_P(stack), 0, 0, args, argc, NULL TSRMLS_CC);
/* Clean up and return the number of elements in the stack */
efree(args);
RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
}/* PHP 7.2.14 */
PHP_FUNCTION(array_unshift)
{
zval *args, /* Function arguments array */
*stack; /* Input stack */
HashTable new_hash; /* New hashtable for the stack */
int argc; /* Number of function arguments */
int i;
zend_string *key;
zval *value;
ZEND_PARSE_PARAMETERS_START(2, -1)
Z_PARAM_ARRAY_EX(stack, 0, 1)
Z_PARAM_VARIADIC('+', args, argc)
ZEND_PARSE_PARAMETERS_END();
zend_hash_init(&new_hash, zend_hash_num_elements(Z_ARRVAL_P(stack)) + argc, NULL, ZVAL_PTR_DTOR, 0);
for (i = 0; i < argc; i++) {
if (Z_REFCOUNTED(args[i])) {
Z_ADDREF(args[i]);
}
zend_hash_next_index_insert_new(&new_hash, &args[i]);
}
if (EXPECTED(Z_ARRVAL_P(stack)->u.v.nIteratorsCount == 0)) {
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
if (key) {
zend_hash_add_new(&new_hash, key, value);
} else {
zend_hash_next_index_insert_new(&new_hash, value);
}
} ZEND_HASH_FOREACH_END();
} else {
uint32_t old_idx;
uint32_t new_idx = i;
uint32_t iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), 0);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(stack), key, value) {
if (key) {
zend_hash_add_new(&new_hash, key, value);
} else {
zend_hash_next_index_insert_new(&new_hash, value);
}
old_idx = (Bucket*)value - Z_ARRVAL_P(stack)->arData;
if (old_idx == iter_pos) {
zend_hash_iterators_update(Z_ARRVAL_P(stack), old_idx, new_idx);
iter_pos = zend_hash_iterators_lower_pos(Z_ARRVAL_P(stack), iter_pos + 1);
}
new_idx++;
} ZEND_HASH_FOREACH_END();
}
/* replace HashTable data */
Z_ARRVAL_P(stack)->u.v.nIteratorsCount = 0;
Z_ARRVAL_P(stack)->pDestructor = NULL;
zend_hash_destroy(Z_ARRVAL_P(stack));
Z_ARRVAL_P(stack)->u.v.flags = new_hash.u.v.flags;
Z_ARRVAL_P(stack)->nTableSize = new_hash.nTableSize;
Z_ARRVAL_P(stack)->nTableMask = new_hash.nTableMask;
Z_ARRVAL_P(stack)->nNumUsed = new_hash.nNumUsed;
Z_ARRVAL_P(stack)->nNumOfElements = new_hash.nNumOfElements;
Z_ARRVAL_P(stack)->nNextFreeElement = new_hash.nNextFreeElement;
Z_ARRVAL_P(stack)->arData = new_hash.arData;
Z_ARRVAL_P(stack)->pDestructor = new_hash.pDestructor;
zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
/* Clean up and return the number of elements in the stack */
RETVAL_LONG(zend_hash_num_elements(Z_ARRVAL_P(stack)));
}