The very simple PHP code below works perfectly, I mean, it does nothing and at the same time it does not use almost any system memory.
<?php
set_time_limit(0);
ini_set('memory_limit','-1');
for ($i=0;$i<100000000;$i++) {
$bbb = function() {
return true;
};
unset($bbb);
}
?>
While the code below is very similar BUT if you run it, after a few minutes you will crash your system because it will consume all your system RAM.
<?php
set_time_limit(0);
ini_set('memory_limit','-1');
for ($i=0;$i<100000000;$i++) {
eval('
$bbb = function() {
return true;
};
');
unset($bbb);
}
?>
My actual $bbb
function is much more complex and it is a result of my AI output, so I really need to use eval
in this case. I am totally aware of security implications.
I just wanna know how to solve this problem. How can I make PHP/APACHE release memory (the GC probably is the curlprit) in the second case?
NOTE: I am using Windows 10 with PHP 7.4
EDIT
As per suggestion of @Nigel Ren (which looks very good) I tried this:
<?php
set_time_limit(0);
ini_set('memory_limit','-1');
for ($i=0;$i<100000000;$i++) {
require("test.php");
unset($bbb);
}
?>
And the "test.php" file has this:
<?php
$bbb = function() {
return true;
};
?>
But this suggestion still consumes lots of memory, it’s not getting cleared! Even if I use gc_mem_caches();
GC is still not clearing memory. Maybe I understood something wrong from your suggestion @@Nigel Ren?
3
Answers
After lots of reseraching I discovered runkit7 is the way to go! It allows clearing RAM even from functions included/required/evaluated! You can use include/require/eval and it will wisely clean the memory footprint. It's a pretty awesome extension and I was amazed as soon as I tested it, my ram dropped 90% from the previous run I did without runkit7.
See the last comment by Chris on this bug report.
For posterity’s sake I’ll copy it here:
So the reason your memory usages increases when using
eval
is that it’s including temporary files. There’s nu way to un-include files, so the more you useeval
, the more memory you’re going to end up using.Disclaimer: the following is pure speculation, I have not verified if this will work
As for a potential workaround to get around this issue, since you say you need to use
eval
, you could look into using thepcntl
extension to fork a process.It’s probably going to be slower, but if you can fork the
eval
-ing piece of your code off to a separate process which can then terminate gracefully once finished, the "include" performed in that child process should be cleared up. That might be one way to limit the memory usage in your application.As a test, this code starts with a template for the source code in your first listing minus the definition but with a place holder to insert the code. The script just reads this file, replaces the marker with the AI script and writes a new file (abc1.php), then uses
require
to run the script. This removes any need foreval
and the overheads associated with it…So abc.php is
The bootstrap script is, where
$aiSrc
is the code you generate (note this also runs the function)…After this the script abc1.php contains…