-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Behaviors cause memoy leaks #1329
Comments
Yes, that's confirmed issue. Would be great if it will be solved but I think it's not critical currently since Yii primary use is web applications where memory is cleaned up after each request-response cycle. |
You can use "CComponent::detachBehaviors()" to strip the object from behaviors and ensure garbage collection. |
PHP core team declares, that PHP 5.3 solves the problem of cycle references: http://www.php.net/manual/en/features.gc.collecting-cycles.php @bwoester, can you confirm, this problem is actual for PHP 5.3? |
PHP 5.3 will detect the cyclic dependency. I didn't notice it when writing the issue, because the cycle detection doesn't run permanently. But you can trigger it manually using gc_enable() / gc_collect_cycles() / dump mem_usage in the test to verify. So I think this issue won't affect many people. |
@samdark, I think the Yii documentation related to the behavior mechanism should be updated: the warning about possible memoy leaks should be added as well as an instructions, how avoid it. |
@klimov-paul I think we should simply fix it by implementing |
@cebe, just how implementing Before making anything rush, you should make yourself familiar with "cycle references" problem and garabage collection mechanism in PHP. |
@klimov-paul I know well about cycle references. As said I haven't really looked into this, so if it can not be easily resolved as you said it should be documented of course. |
Sorry, no offence. |
I think there isn't much you can do to solve or avoid this. Best will be to use PHP >= 5.3 and to ensure circular reference collector is enabled. I played with destructors, but as klimov-paul mentioned it doesn't help, because it will only be invoked when the the refcount reaches 0. I tried attaching owners to behaviors via reference, but the refcount will still be increased by php. I found some suggestions to invoke tear-down methods manually to clean up references (CComponent::detachBehaviors could be used as/in such a tear-down method). But this is not only cumbersome, it also required you to know about internas of the attached behaviors. For example if one of them passed its owner to some other component, the owner must not be destroyed. And as long as it won't be destroyed, you don't want its behaviors to be detached... Whatever I come up with, it feels like running in circles. Maybe there is no solution as long as php doesn't provide a way to query and/or manually modify the refcount. |
Agree with @bwoester. We had this issue logged before, and we ended closing it without doing anything. We have to keep a reference to the behavior in the owner object so that we can support the access to behavior methods/properties via the owner. On the other hand, we also need the reference to the owner in the behavior in case the behavior needs to access something in the owner. So this cyclic reference seems unavoidable. I'm closing this issue for the reason as described by bwoester. |
@klimov-paul didn't take it as serious as it might have sounded, everything is fine :) |
i use some old YII version with php 5.3 and it still leaks. i tried calling GC and still leaks |
@sisoje the obvious suggestion is to update Yii. |
any idea when this will be fixed? i'm also facing this issue now (using PHP 5.3). Many of my models use the CTimeStampBehavior and a custom SoftDeleteBahavior.... With 128Mb of RAM allocated to php, I'm only able to generate 400+ instances of my ActiveRecord. This means I can't display >400 items in a single page in GridView without using SqlDataProvider. I also have background php scripts that loop many times. It's going to be painful to have to rewrite all the code in my models in SQL (not to mention code duplication). please help! |
@pohnean, this issue can not be resolved in framework.
I am sorry but can not be resolve anyhow: PHP consumes a lot of memory per each object, when you have 400 models, each having 2 behaviors, means you have 1200 objects - no wonder you approach memory limit. All I can suggest is reducing page size - is it really necessary to show 400 records at the same page?
You should try to invoke "detachBehaviors()" for the models.
|
@pohnean you may want to use |
@cebe Thanks for the feedback, i'll try CDataProviderIterator... @klimov-paul The function i'm using it in is a background process. I'm actually creating the variable repeatly using the same variable, and not storing it in an array... (see example below) example: This rightfully it should not take up additional memory if memory doesn't leak.... unless my understanding of PHP is mistaken... |
@pohnean, this happens because of objects linking recursion (model links to behavior and behavior links to model as its owner). Try to call This may happen when you have two-side parent-child links in objects. GC doesn't destroy them properly. Looks like this bug |
Try to update your code to the following:
|
Basically, whenever you attach a CBehavior to a CComponent, this prevents the CComponent instance from being destroyed. As far as I can tell, this happens because you create a cyclic dependency: The component holds a reference to the attached behavior, the behavior holds a reference to its owner.
So this bug is by design and I have no idea if it can be solved. But maybe someone has an idea about it.
To reproduce:
Run the action and you will see that normally, the heavy weight components will be cleaned up when leaving the local function scope (memory increases a little bit, maybe it's the log messages). But whenever a behavior is attached to the components, the memory won't be cleaned up.
The text was updated successfully, but these errors were encountered: