Plugin for kevinchappell/formBuilder to render media (image/video/audit) on forms
This is an in-browser client only implementation of the American 75-number version of Bingo.
Adds a private static property to the Messages Factory to only create a single reusable instance of Doctrine\Inflector. In the benchmark\memory.php test this reduces peak memory by 40MB for 100000 RPC calls and improves benchmark performance by 60-80% in testing. A bonus is improved readability of XDebug traces without all the Doctrine calls in each call.
Closes #112
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.
Current memory usage: 2.025 MB Peak memory usage: 43.091 MB Current real memory usage: 44 MB Peak real memory usage: 46 MB
Current memory usage: 1.172 MB Peak memory usage: 4.23 MB Current real memory usage: 6MB Peak real memory usage: 6MB
Current memory usage: 0.967 MB Peak memory usage: 4.23 MB Current real memory usage: 6MB Peak real memory usage: 6MB
Split Garbage Collection operations into a separate function that provides consistent logging when run
@WyriHaximus Yes, In my use case the services are writing out a state file every 1 second. So each second there is a Filesystem putContents to a temp file followed by a rename. This is using Reach Filesystem Child Process, EIO is unusable per the previous tickets opened.
react-child-process-messenger makes good use of TcpServer to do the RPC work, so when doing file operations you rapidly leak memory.
Hi @clue @WyriHaximus @SimonFrings , I wanted to bring to your attention an internal PHP memory leak (https://github.com/php/php-src/issues/10885) I found which has been affecting me with TcpServer (Specifically through react-child-process-messenger + react/filesystem).
Essentially for each instance of TcpServer, PHP was allocating 720+ bytes that was never released until shutdown, seems to have always existed since PHP4 days https://3v4l.org/XBaaP
The good news is the PHP team quickly provided a patch which has been merged into PHP8.1, 8.2, Master so the next releases will have a fix. It may be useful to add some documentation to TcpServer of this issue for memory constrained environments where there is a high churn of TcpServer instances.
@damianwadley It crashes the application with PHP Fatal error: Allowed memory size.
You can see in the example in the original report that if you stick a ini_set('memory_limit','40M');
at the top, the script will crash after 40214 iterations on PHP8.0.28 (faster on 8.2 as it uses more memory per context).
I have a long running PHP application that is creating stream_socket_server over time, the memory allocated by stream_context_create() is never released even after closing and destroying the stream_socket_server. A minimal reproduction is below (backlog is set to allocate more memory on each loop however even an empty array to stream_context_create shows this issue). Eventually the application will crash, this is more evident in memory constrained environments like container deployments.
I found an old PHP bugs report referencing this with stream_socket_client (https://bugs.php.net/bug.php?id=61371) inhibition for deleting the context was too broad
and a really old one that says that stream_context_create() memory is never released https://bugs.php.net/bug.php?id=40257 but this is not documented.
Output from memprof shows the allocated memory from stream_context_create()
<?php
$m0 = memory_get_usage(true);
for ($i=0;$i<50000;++$i){
$context = stream_context_create(['socket'=>['backlog'=>511]]);
$server = @\stream_socket_server(
'tcp://127.0.0.1:0',
$errno,
$errstr,
\STREAM_SERVER_BIND | \STREAM_SERVER_LISTEN,
$context,
);
fclose($server);
unset($server);
unset($context);
unset($errno);
unset($errstr);
}
$m1 = memory_get_usage(true);
echo ($m1-$m0)/1048576,' MB allocated',PHP_EOL;
$cycles = \gc_collect_cycles() + gc_collect_cycles();
echo 'Ran ', $cycles, ' GC Cycles', PHP_EOL;
Resulted in this output:
46.00390625 MB allocated
Ran 0 GC Cycles
But I expected this output instead:
0 MB allocated
Ran 0 GC Cycles
PHP 8.0.28 - PHP 8.2.4
No response
While tracking down memory growth on a long running process using ReactPHP Filesystem I came across the following circular reference that needs to be cleaned up by the GC. Results where seen in benchmark/memory.php
In a small test of 2500 invocations of RPC this reduced GC cycles from 137 to 0
While tracking down memory growth on a long running process using ReactPHP Filesystem I came across the following circular reference that needs to be cleaned up by the GC.
Circular reference between $server and the connection event listener causes garbage collection cycles when resolving.
I've additionally added removing listeners on all instances of closing the server, tests coverage is only for the success route.
Unset timer to remove reference. Improve display of garbage collection cycles in output memory benchmark
Remove listeners on terminate to remove cyclic references causing garbage collection cycles
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 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.
I first tried static caching of the Inflector, this stops the churn but that 105MB is always used, so not useful.
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
Improve memory usage by removing listener reference on stream close and not triggering garbage collection cycles. This was found while debugging a large number of garbage collection cycles coming out of reactphp-child-process-pool.
Is there a planned 1.8.1 or 1.9.0 to release the PHP8.1 compatibility fix merged in https://github.com/WyriHaximus/reactphp-child-process-pool/pull/74?
Add CONTROL_MSG_HEARTBEAT to inject a heartbeat event into the engine every X seconds as configured. Rules can use this for updating things, checking for missing data (including batch jobs detecting missing data) and for logging. Defaults to Off (0 seconds)
Refactor save state handling by extracting the state load and save (async and sync versions) into an adapter file. This reduces code in the scheduler and also allows future save handlers, for example direct to redis or a database
Does the new adapter handle when eio_open returns false (or any other call, but eio_open appears to be the most common)?, it's undocumented but if you look into the PECL library you can see the error path that RETURN_FALSE instead of -1
See https://github.com/reactphp/filesystem/issues/43 was the reason we had to move to the child process for file operations
Thanks @oleibman , tested correctly against my spreadsheet.
This is:
Output of =TEXT("09:01","HH:MM:SS") is the time string 09:01:00
Verified with Excel and LibreOffice
Output is 00:00:00
PhpOffice\PhpSpreadsheet\Calculation\TextData\Format::TEXTFORMAT uses DateTimeExcel\DateValue::fromString($value) to parse the text into a numeric value. In the case where only a time is provided DateValue::fromString returns (float)0.0
Possible fix is Format::TEXTFORMAT should check for the return of (float)0.0 and then hand off to DateTimeExcel\TimeValue::fromString($value) to get the correct numeric value
Tested on PhpSpreadsheet 1.28 and PHP8.0