You shouldn't run out of memory
You run out of memory
if($maxPreviewImage !== null){
imagedestroy($maxPreviewImage->resource());
}
return $preview;
Is this the best solution? 馃し does it work for this problem? It appears so.
It seems there may be a memory leak in the underlying php imagecreatefromstring function but this work-around allows things to function as expected, at least for me. I usually do most of my coding these days in python and go, so I may not be the best person to submit a PR for this.
Operating system:
Official nextcloud docker image
Web server: apache - built into docker image base with all optional packages installed per nextcloud docker documentation
Database: mysql
PHP version: 7.4.8
Nextcloud version: 19.0.1
Updated from an older Nextcloud/ownCloud or fresh install: updated from 19.0.0 where issue was also observed
Where did you install Nextcloud from: dockerhub + addition of extra packages

The fix also solves my OOM issues with preview:generate-all. Thanks!
Thanks for digging :+1: I guess that was fun :sunglasses:
Is this the best solution?
It makes sense. Could you try $maxPreviewImage = null (after foreach, before the return)? It should do roughly the same. I'm a bit unsure about imagedestroy($maxPreviewImage->resource()) because it leaves the $maxPreviewImage in a weird state as the used resource is destroyed but the wrapper object is still there. I would expect $maxPreviewImage = null to have the same effect.
Thanks for digging 馃憤 I guess that was fun 馃槑
Is this the best solution?
It makes sense. Could you try
$maxPreviewImage = null(after foreach, before the return)? It should do roughly the same. I'm a bit unsure aboutimagedestroy($maxPreviewImage->resource())because it leaves the $maxPreviewImage in a weird state as the used resource is destroyed but the wrapper object is still there. I would expect$maxPreviewImage = nullto have the same effect.
That doesn't fix the issue. I see the memory leak again with $maxPreviewImage = null.
I believe the issue is related to memory not being cleared by the garbage collector from the imagecreatefromstring call. The variables are all falling out of scope, so garbage collection should be clearing them. However, this isn't happening. Setting $maxPreviewImage = null just queues the variable up for garbage collection, which is what isn't working in the first place. the imagedestroy function appears to be specifically designed to clear all memory associated with an image independent of the garbage collection process. Some of the very old comments on the documentation appear to indicate that this is just the way PHP image processing is designed. The only way to be sure you've cleared the memory associated with an image is to use imagedestroy.
Thanks for digging 馃憤 I guess that was fun 馃槑
Is this the best solution?
It makes sense. Could you try
$maxPreviewImage = null(after foreach, before the return)? It should do roughly the same. I'm a bit unsure aboutimagedestroy($maxPreviewImage->resource())because it leaves the $maxPreviewImage in a weird state as the used resource is destroyed but the wrapper object is still there. I would expect$maxPreviewImage = nullto have the same effect.
the $maxPreviewImage variable is local to the function and isn't returned. In theory, it should only exist in the scope of the function call. Once the function returns, it's reference count should drops to zero, same as setting it to null or calling unset on it.
Once at zero, garbage collection should free the memory. However, I suspect there's a reference being maintained to the image in the PHP image processing libraries which is preventing the memory from being cleared by the garbage collector.
If it helps, I can put together a PR for this, just let me know what's going to be most efficient.
If it helps, I can put together a PR for this, just let me know what's going to be most efficient.
Thanks :+1: Please create a pull request.
if ($maxPreviewImage instanceof IImage) {
$maxPreviewImage->destroy();
}
$maxPreviewImage = null;
Here's what I would do.
I think we can use the destory method as imagedestroy is used internally.
Once at zero, garbage collection should free the memory. However, I suspect there's a reference being maintained to the image in the PHP image processing libraries which is preventing the memory from being cleared by the garbage collector.
I guess that is the reference.
If it helps, I can put together a PR for this, just let me know what's going to be most efficient.
Thanks 馃憤 Please create a pull request.
if ($maxPreviewImage instanceof IImage) { $maxPreviewImage->destroy(); } $maxPreviewImage = null;Here's what I would do.
I think we can use the destory method as
imagedestroyis used internally.Once at zero, garbage collection should free the memory. However, I suspect there's a reference being maintained to the image in the PHP image processing libraries which is preventing the memory from being cleared by the garbage collector.
I guess that is the reference.
Looks great - I'll test this approach and put a PR together
The fix also solves my OOM issues with preview:generate-all. Thanks!
patched generatePreview. now preview preview:generate-all is not dying cuz of oom anymore. Hoping for this to be fixed in 19.0.2 =)
Most helpful comment
patched generatePreview. now preview preview:generate-all is not dying cuz of oom anymore. Hoping for this to be fixed in 19.0.2 =)