On Mon, Feb 4, 2019 at 11:48 PM Benjamin Eberlei <kont...@beberlei.de>
wrote:

>
>
> On Mon, Feb 4, 2019 at 10:29 PM Benjamin Eberlei <kont...@beberlei.de>
> wrote:
>
>>
>>
>> On Thu, Jan 31, 2019 at 10:44 AM Dmitry Stogov <dmi...@zend.com> wrote:
>>
>>> Hi Internals,
>>>
>>>
>>> I'm glad to finally propose including JIT into PHP.
>>>
>>>
>>> https://wiki.php.net/rfc/jit
>>>
>>>
>>> In the current state it may be included both into PHP-8, where we are
>>> going to continue active improvement, and into PHP-7.4, as an experimental
>>> feature.
>>>
>>
>> Can you give some information on if there are pre-conditions that must
>> hold for a function to be jitted, or quit conditions that force the JIT to
>> be reverted for a function? In addition, it would be helpful for testing if
>> there was a way to find out if a function was jitted, maybe through
>> ReflectionMethod/Function or opcache_get_status() ?
>>
>
> And as a follow up, the JIT seems to affect zend_execute_ex and
> zend_execute_internal based profiling (tested with tideways_xhprof) in a
> way that all Jitted functions are not called through those two hooks
> anymore, and don't appear in profiling data anymore. Is that a correct
> description? The number of parent=>child call entries drops from 88 to 12
> in my sample code when jit is activated.
>
> Is that a desired side-effect?
>

Opening this tree of the discussion again with my research findings on JIT
+ production tracing.

I want to discuss a few ways forward:

1. Joe prototyped a solution how to instrument userland code that is JIT
compatible right now without php-src changes. It swaps zend_op_array with
an additional zend_internal_function wrapper acting as a decorator for each
entry in CG(function_table) that is instrumented. Code for this approach
can be found here: https://github.com/beberlei/php-overload-poc/ - but it
requires some more work, specifically Joe said it must be turned into a
zend_extension to get fully working.

This approach would help with extensions that currently instrument very
specific functions (mysqli_query, curl_exec, ....) such as tideways,
dd_trace, NewRelics (and other APM vendors).

Downside is it requires to overwrite debug_backtrace to filter out the
double frames and potentially has problems with the ReflectionFunction /
ReflectionMethod API having subtly different behaviors for internal and
userland functions. And this would probably lead to problems when multiple
extensiosn use the same approach.

It would not work with full function profilers such as Blackfire, php-spx,
that don't know the functions they instrument, instrument all the
functions. I don't include xdebug in that list, because it is mostly used
in non production evnironments that don't use the JIT, but the other
profilers are explicitly for production usage.

It would also not work with extensions that allow developers to instrument
class+methods / functions at runtime, such as dd_trace [1] and tideways

2. Another approach could be to generalize this approach
stackdriver-debugger [2] has by modifying the AST to include the profiling
code. But having additional internal fucntion calls "profiler_start" +
"profiler_stop" there would have a lot more overhead than execute_ex
wrappers currently do. Alternatively the engine could introduce new opcodes
for enter/leave tracing that directly translate to a C call to newly
created hooks and could also get JIT support.

This could be generalized to the point where php-src provides the code for
the ast injection so that extensions could just re-use it. I think this
would be the cleanest approach.

3. Separating execute_ex from the desire to do tracing would be possible if
we introduce a new hook "zend_trace_function(int enterOrExit, const char
*class_name, const char *function_name, zval *args, zval *returnValue);" .
I am not sure if the JIT could actually call this hook, probably not
because args and returnValue might not be in zval representation. I haven't
looked this deeply into the JIT yet.

As a benefit this new hook would prevent tracing/profiling extensions from
forcing the VM to generate the more inefficient opcodes for function calls
by overwriting zend_execute_ex

4. A last solution for the specific function instrumentation (not feasible
for generic profilers though) would be an API to register functions that
extensions consider "@nojit" which extensions could do on MINIT:

opcache_jit_mark_nojit_func("my_function");
opcache_jit_mark_nojit_method("MyClass", "method");

This would allow extensions to always see these calls in zend_execute_ex
callbacks.

@Dmitry: What do you think about a path forward here for a solution that
enables production tracing?

[1]
https://github.com/DataDog/dd-trace-php/blob/master/src/DDTrace/Integrations/PDO/PDOIntegration.php#L44
[2]
https://github.com/GoogleCloudPlatform/stackdriver-debugger-php-extension/blob/master/stackdriver_debugger_ast.c


>>>
>>> Thanks. Dmitry.
>>>
>>

Reply via email to