Re: Problem with garbage collection in server application [solved]
Re: Problem with garbage collection in server application [solved]
- Subject: Re: Problem with garbage collection in server application [solved]
- From: Rick Hoge <email@hidden>
- Date: Sun, 23 Jan 2011 20:50:33 -0500
Hi Quincey,
The way you broke this down was very helpful, and it turned out to be a combination of two things you alluded to. I'd been on the right track that it had to do with NIB objects, and thinking about it as you laid out helped identify the problem.
On 2011-01-23, at 12:28 AM, Quincey Morris wrote:
> 1. Too much "live" (i.e. uncollectible) data at once. This breaks down into three subcategories:
>
> 1a. Objects that you create, and keep strong references to, use too much memory in total.
>
> 1b. Your code depends on a confusion between the end of the lifetimes of your objects and the collection times of the memory they use. You shouldn't be designing with collection times in mind.
>
> 1c. Objects that are created by the frameworks internally, but which somehow support objects that you create (think of a cache, for example), have lifetimes not under your control, and remain live after your own objects' lifetimes are over.
I think it's mostly 1c.
So in the end the problem was that I had some NIB files with NSArrayControllers bound to my 'datasets' array. The large dataset objects are removed from the array when I am done with them, and since this constitutes the last strong reference I'd (deliberately) created I expected them to be eligible for collection. However I initially assumed that removing the objects from the array would also remove any references in bound NIB objects right away. This turned out to be the source of what to me was unexpected behaviour. Although the UI objects seem to be removed from the view on cue, it's up to the collector when they will actually be reaped. As soon as my server app exits the method invoked by the client via an NSConnection, there is typically another message waiting that gets executed right away. This seems to block collection of the UI objects, which must have strong references to my dataset objects. The UI objects only get collected after the last message is sent from the client, and the server resumes the 'waiting for user input' state.
In my app the UI content that is bound to attributes of the datasets is largely for logging purposes, and I can just as easily bind to an array of lightweight proxy objects that have all of the relevant information. As soon as I removed the single binding of an NSArrayController to my 'datasets' array, the objects were collected pretty much right away (right after collectExhaustively).
Now I know I shouldn't be thinking about collection times, but now I think I understand the problem better. By creating strong references between NIB objects and my internal objects, I no longer had control of the last strong reference to the object. The rapidly successive client connections to the server in script mode were blocking collection of the UI objects, guaranteeing that all of the large dataset objects would be kept alive as long as the script was running. After removing direct NIB bindings to the dataset objects, the memory usage behaves exactly as expected.
This all jives with a clue I'd noticed all along - the server app basically manipulates two types of object: datasets, and processing operations. From the start I had been binding the UI to lightweight proxies of the processing operations. I'd noticed that the processing operations had always been collected very promptly after the last reference was removed. Now it makes perfect sense!
Oh garbage collector, I am sorry that I ever doubted you...
Rick
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden