WyriHaximus / reactphp-child-process-messenger

MIT License
31 stars 14 forks source link

High memory usage and churn due to usage of Doctrine\Inflector #112

Closed lucasnetau closed 1 year ago

lucasnetau commented 1 year ago

Doctrine\Inflector is used in WyriHaximus\React\ChildProcess\Messenger\Messages\Factory::fromLine to convert rpc_error and rpc_success to the camelCase rpcError / rpcSuccess.

https://github.com/WyriHaximus/reactphp-child-process-messenger/blob/530abc7de0e68aca1ca1d7b892e1f4c5e2c2a326/src/Messages/Factory.php#L21

Running the benchmark/memory.php with PHP8 shows that using Doctrine increases peak memory usage from 4.1MB to 44-109MB. Additionally since the Inflector is initialised on every messenger line, then released, we have both a high memory churn but also high CPU cost related to that initialisation. This can be seen on an XDebug trace.

The commit history doesn't explain why Inflector is used instead of just doing a straight string equality comparison with $method === 'rpcSuccess' || $method === 'rpc_success' etc.

I can provide a PR. This would also remove the Doctrine\Inflector dependancy

lucasnetau commented 1 year ago

The high memory usage appears to be a side effect of the high churn of Inflector instances, PHP doesn't have time to release the memory before the next instance and therefore memory grows until it reaches an equilibrium.

Further testing shows that the option of using a static cache of the Inflector results in a significant memory saving and no churn. The benchmark/memory.php also is 60-81% faster to complete 100000 messaging cycles, so there is a performance improvement here.

benchmark/memory.php current (I=100000) Done: 22168 msec (17168 msec without sleep)

Current memory usage: 2.025 MB Peak memory usage: 43.091 MB Current real memory usage: 44 MB Peak real memory usage: 46 MB

benchmark/memory.php static cache Inflector (I=100000) Done: 8233 msec (3233 msec without sleep)

Current memory usage: 1.172 MB Peak memory usage: 4.23 MB Current real memory usage: 6MB Peak real memory usage: 6MB

benchmark/memory.php hardcode if camelCase (I=100000) Done: 8027 msec (3027 msec without sleep)

Current memory usage: 0.967 MB Peak memory usage: 4.23 MB Current real memory usage: 6MB Peak real memory usage: 6MB