Closed
Description
Description
I noticed that a PHP script was consuming a very high amount of CPU. I used strace to investigate and found that it was repeatedly executing fcntl. I used GDB to trace the process and found that it was continuously looping through a specific code path, as detailed in the following quote.
One scenario is that our script is hosted under a PHP process, where the host process forks a child process to execute the specific code.
- opcache.jit* settings
opcache.jit => tracing => tracing
opcache.jit_bisect_limit => 0 => 0
opcache.jit_blacklist_root_trace => 16 => 16
opcache.jit_blacklist_side_trace => 8 => 8
opcache.jit_buffer_size => 16M => 16M
opcache.jit_debug => 0 => 0
opcache.jit_hot_func => 127 => 127
opcache.jit_hot_loop => 64 => 64
opcache.jit_hot_return => 8 => 8
opcache.jit_hot_side_exit => 8 => 8
opcache.jit_max_exit_counters => 8192 => 8192
opcache.jit_max_loop_unrolls => 8 => 8
opcache.jit_max_polymorphic_calls => 2 => 2
opcache.jit_max_recursive_calls => 2 => 2
opcache.jit_max_recursive_returns => 2 => 2
opcache.jit_max_root_traces => 1024 => 1024
opcache.jit_max_side_traces => 128 => 128
opcache.jit_max_trace_length => 1024 => 1024
opcache.jit_prof_threshold => 0.005 => 0.005
- GDB
zbacktrace
shows code in PHP land blocking onself::$traceAt = now();
- The following script just trying to show the core parts of the code which triggered the issue
namespace {
function now()
{
return date('Y-m-d H:i:s');
}
}
namespace core\Context {
class A {
private static $traceAt;
public static function resetTraceCtx()
{
self::$traceAt = now();
}
}
}
namespace third {
$max = 10000;
$i = 0;
while ($i++ < $max) {
\core\Context\A::resetTraceCtx();
// poll info from queue
usleep(100000);
}
}
- GDB backtrace
#0 zend_jit_trace_exit (exit_num=0, regs=0x7ffe8841e390) at ext/opcache/jit/zend_jit_trace.c:8171
#1 0x000000001300042a in ?? ()
#2 0x000000000673ab60 in ?? ()
#3 0x0000000002d3327f in ?? ()
#4 0x00000000000207a9 in ?? ()
#5 0x0000000000680f1d in timelib_time_tz_abbr_update (tm=0x7f3d4a8157e0, tz_abbr=0x7ffe8841e510 "\200U\201J=\177") at /path/to/php-8.3.7/ext/date/lib/timelib.c:128
#6 0x0000000000000000 in ?? ()
- loop in ASM
0x000000001300042a ? add $0x100,%rsp
0x0000000013000431 ? test %eax,%eax
0x0000000013000433 ? jne 0x13000443
0x0000000013000435 ? mov 0x1a28f28,%r14
0x000000001300043d ? mov (%r14),%r15
0x0000000013000440 ? jmpq *(%r15) ->
0x0000000013000443 ? jl 0x13000330
0x0000000013000449 ? mov 0x1a28f28,%r14
0x0000000013000451 ? mov (%r14),%r15
0x0000000013000454 ? cmpb $0x0,0x1a28f56
0x000000001300045c ? jne 0x13000000
0x0000000013000462 ? mov 0x18(%r14),%rax
0x0000000013000466 ? mov 0xc0(%rax),%rax
0x000000001300046d ? mov 0xa0(%rax),%rax
0x0000000013000474 ? jmpq *(%r15,%rax,1)
0x00000000130af820 ? movl $0x3ff,0x1a28f38
0x00000000130af82b ? mov 0x40(%r14),%rdx
0x00000000130af82f ? mov 0x8(%rdx),%rax
0x00000000130af833 ? cmp $0x54306e0,%rax
0x00000000130af83a ? jne 0x130af8c0 ->
0x00000000130af840 ? mov 0x1a28f08,%r15
0x00000000130af848 ? mov 0x1a28f10,%rdx
0x00000000130af850 ? sub %r15,%rdx
0x00000000130af853 ? cmp $0x60,%rdx
0x00000000130af857 ? jb 0x13000904
0x00000000130af85d ? addq $0x60,0x1a28f08
0x00000000130af866 ? movl $0x0,0x28(%r15)
0x00000000130af86e ? mov %rax,0x18(%r15)
0x00000000130af8c0 ? mov $0x4fb4318,%rdi
0x00000000130af8c7 ? lea 0x8(%rdx),%rsi
0x00000000130af8cb ? movabs $0x7f3d4aa7e610,%rax // static zend_function* ZEND_FASTCALL zend_jit_find_ns_func_helper(zval *func_name, void **cache_slot)
0x00000000130af8d5 ? callq *%rax
// return back
0x00000000130af8d7 ? cmp $0x54306e0,%rax
0x00000000130af8de ? je 0x130af840
0x00000000130af8e4 ? jmpq 0x13000900 ->
0x00000000130af8e9 ? add %al,(%rax)
0x00000000130af8eb ? add %al,(%rax)
0x00000000130af8ed ? add %al,(%rax)
0x00000000130af8ef ? add %cl,-0x39(%rcx)
0x00000000130af8f2 ? (bad)
0x00000000130af8f3 ? (bad)
0x00000000130af8f4 ? or $0x41,%al
0x0000000013000900 ? pushq $0x0
0x0000000013000902 ? jmp 0x1300097e ->
0x000000001300097e ? addq $0x0,(%rsp)
0x0000000013000983 ? jmpq 0x13000340 ->
0x0000000013000988 ? add %al,(%rax)
0x000000001300098a ? add %al,(%rax)
0x000000001300098c ? add %al,(%rax)
0x0000000013000340 ? sub $0xf8,%rsp
0x0000000013000347 ? mov %r15,0x78(%rsp)
0x000000001300034c ? mov %r11,0x58(%rsp)
0x0000000013000351 ? mov %r10,0x50(%rsp)
0x0000000013000356 ? mov %r9,0x48(%rsp)
0x000000001300035b ? mov %r8,0x40(%rsp)
0x0000000013000360 ? mov %rdi,0x38(%rsp)
0x0000000013000365 ? mov %rsi,0x30(%rsp)
0x000000001300036a ? mov %rdx,0x10(%rsp)
0x000000001300036f ? mov %rcx,0x8(%rsp)
0x0000000013000374 ? mov %rax,(%rsp)
0x0000000013000378 ? mov 0xf8(%rsp),%rdi
0x0000000013000380 ? mov %rsp,%rsi
0x0000000013000383 ? movsd %xmm15,0xf8(%rsp)
0x000000001300038d ? movsd %xmm14,0xf0(%rsp)
0x0000000013000397 ? movsd %xmm13,0xe8(%rsp)
0x00000000130003a1 ? movsd %xmm12,0xe0(%rsp)
0x00000000130003ab ? movsd %xmm11,0xd8(%rsp)
0x00000000130003ab ? movsd %xmm11,0xd8(%rsp)
0x00000000130003b5 ? movsd %xmm10,0xd0(%rsp)
0x00000000130003bf ? movsd %xmm9,0xc8(%rsp)
0x00000000130003c9 ? movsd %xmm8,0xc0(%rsp)
0x00000000130003d3 ? movsd %xmm7,0xb8(%rsp)
0x00000000130003dc ? movsd %xmm6,0xb0(%rsp)
0x00000000130003e5 ? movsd %xmm5,0xa8(%rsp)
0x00000000130003ee ? movsd %xmm4,0xa0(%rsp)
0x00000000130003f7 ? movsd %xmm3,0x98(%rsp)
0x0000000013000400 ? movsd %xmm2,0x90(%rsp)
0x0000000013000409 ? movsd %xmm1,0x88(%rsp)
0x0000000013000412 ? movsd %xmm0,0x80(%rsp)
0x000000001300041b ? mov %r15,(%r14)
0x000000001300041e ? movabs $0x7f3d4ab05090,%rax // int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf *regs)
0x0000000013000428 ? callq *%rax
0x000000001300042a ? add $0x100,%rsp // loop again
0x0000000013000431 ? test %eax,%eax
PHP Version
PHP 8.3.7
Operating System
Rocky Linux 8