NoiseByNorthwest / php-spx

A simple & straight-to-the-point PHP profiling extension with its built-in web UI
GNU General Public License v3.0
2.02k stars 78 forks source link

Feature request: arguments capturing #206

Open ilnytskyi opened 1 year ago

ilnytskyi commented 1 year ago

It would be nice to have possibility to capture arguments and its values. Related checkbox in panel can be introduced. Like for current profile (Profile internal functions) For the beginning only simple types like Strings - (truncated after char limit defined in panel), Numbers - as it is

More complex types can be simplified Arrays - (only length for the beginning if possible) Objects - Just info about instance type (maybe add spl object id/hash if possible)

Maybe final result would look like this Selection_187

If I see correctly, arguments capturing would significantly increase dump size and added some overhead https://github.com/NoiseByNorthwest/php-spx/blob/master/src/spx_php.c#L249 (As we need to link called function with arguments)

Maybe some optimizations like skipping arguments in constructors would help Selection_188

NoiseByNorthwest commented 1 year ago

This feature would be especially useful for some debugging / reverse engineering use cases which are not the main target of SPX.

I'm however open to add it as long as :

Regarding the complexity, the hard part will be producing the stringified argument list summary. We must as possible reuse an existing logic within the PHP code base.

Do you know if this logic is already exposed via a native PHP construct or function ?

ilnytskyi commented 1 year ago

There is php function get_defined_vars(); if called at the beginning of the method will return arguments and names. Then some custom serializer needed to produce nice output. (smth like json_encode but skipping/replacing complex types)

Selection_190

source C implementation: https://github.com/php/php-src/blob/master/Zend/zend_builtin_functions.c#L1334

NoiseByNorthwest commented 1 year ago

@ilnytskyi I need something which roughly returns (or includes whithin a returned string) the string you want as summarized argument list.

NoiseByNorthwest commented 1 year ago

debug_print_backtrace() does what you have described. Implemented here https://github.com/php/php-src/blob/php-8.1.13/Zend/zend_builtin_functions.c#L1619

That is still a lot of work.

ilnytskyi commented 1 year ago

I checked xdebug tracer and it looks like it does almost exactly what I reported: In machine traced format it outputs simplified arguments. Running xdebug tracer with config like this.

xdebug.trace_format=1
xdebug.collect_assignments = 1 //this can even capture internal variables

XDEBUG_MODE=trace XDEBUG_TRIGGER=PHPSTORM php php_sandbox.php

will produce string like this

'name'  1   ['level1' => ['level2' => [...]], 'key2' => 55] NULL    class stdClass {  }

More description here https://xdebug.org/docs/all_settings#trace_format

Full trace of my file

Version: 3.1.5
File format: 4
TRACE START [2022-11-24 07:36:53.878895]
1   0   0   0.000311    603464  {main}  1       /home/www/magento/pub/php_sandbox.php   0   0
2   1   0   0.000366    603464  ini_set 0       /home/www/magento/pub/php_sandbox.php   4   2   'display_errors'    1
2   1   1   0.000427    603912
2   2   0   0.000454    603840  ini_set 0       /home/www/magento/pub/php_sandbox.php   5   2   'display_startup_errors'    1
2   2   1   0.000495    603912
2   3   0   0.000522    603840  ini_set 0       /home/www/magento/pub/php_sandbox.php   6   2   'memory_limit'  -1
2   3   1   0.000559    603944
2   4   0   0.000578    603872  error_reporting 0       /home/www/magento/pub/php_sandbox.php   8   1   32767
2   4   1   0.000614    603944
2   5   0   0.000634    603944  testArgs    1       /home/www/magento/pub/php_sandbox.php   25  5   'name'  1   ['level1' => ['level2' => [...]], 'key2' => 55] NULL    class stdClass {  }
3   6   0   0.000692    604000  get_defined_vars    0       /home/www/magento/pub/php_sandbox.php   17  0
3   6   1   0.000726    604752
2       A                       /home/www/magento/pub/php_sandbox.php   17  $defined = ['name' => 'name', 'level' => 1, 'someVals' => ['level1' => [...], 'key2' => 55], 'user' => NULL, 'object' => class stdClass {  }]
3   7   0   0.000802    604752  json_encode 0       /home/www/magento/pub/php_sandbox.php   18  3   ['name' => 'name', 'level' => 1, 'someVals' => ['level1' => [...], 'key2' => 55], 'user' => NULL, 'object' => class stdClass {  }]  16  1
3   7   1   0.000860    604848
2       A                       /home/www/magento/pub/php_sandbox.php   18  $out = FALSE
2       A                       /home/www/magento/pub/php_sandbox.php   20  $a = 1
2   5   1   0.000944    604376
1   0   1   0.000972    604280
            0.001071    373792
TRACE END   [2022-11-24 07:36:53.879731]

I believe this is the way that string is produced (but for textual format = 0 where arguments names are also included)

-> testArgs($name = 'name', $level = 1, $someVals = ['level1' => ['level2' => [...]], 'key2' => 55], $user = NULL, $object = class stdClass {  })

https://github.com/xdebug/xdebug/blob/master/src/tracing/trace_textual.c#L108

Now I am not sure if we need to implement this for SPX as this feature would only be needed for debugging / reverse engineering. Maybe it would be better to focus on visualizing this xdebug trace in SPX-like timeline view.

NoiseByNorthwest commented 1 year ago

I've the same doubt, optimizing SPX for non-profiling use cases could be at best a Pandora's box.