Garbage Collection in commandline applications
Garbage Collection in commandline applications
- Subject: Garbage Collection in commandline applications
- From: Adam P Jenkins <email@hidden>
- Date: Sat, 9 Feb 2008 02:07:52 -0500
I'm using Objective-C 2.0 and using the new garbage collection. This
works great for normal GUI applications, but it doesn't seem to work
as transparently as GC in other languages like Java or C#. In
particular, as far as I can tell there needs to be some thread running
which calls NSGarbageCollector collectIfNeeded method occasionally,
otherwise GC never occurs. Apparently the run loop in a Cocoa GUI app
does this. This means if I write an app with no GUI, then GC never
occurs automatically. I have to insert calls to
[[NSGarbageCollector defaultCollector] collectIfNeeded];
or GC never happens.
For example if I create a command line program like this:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSGarbageCollector *collector = [NSGarbageCollector defaultCollector];
NSLog(@"gc enabled = %d", [collector isEnabled]);
while (1) {
[NSArray arrayWithObject:@"Hello World"];
// unless this is uncommented, this will leak memory
//[collector collectIfNeeded];
}
return 0;
}
and build it with -fobjc-gc-only, it will leak memory unless you
uncomment the line for collectIfNeeded. If you watch the process
running in Activity Monitor you'll see its memory increasing forever
until it's killed. Uncomment the collectIfNeeded line and it'll stay
at around 1 or 2 MB memory usage. This clearly defeats the purpose of
having GC if I were writing any large non-GUI program and had to
sprinkle explicit calls to invoke the GC throughout my code. Does
anyone know what I'd need to do to make GC happen automatically in
commandline programs?
You can see that something like this in GUI apps as well. For
instance, create a Cocoa Application, enable the -fobjc-gc-only build
option, and then create an event handler for a button which blocks the
GUI thread and keeps allocating objects in a loop: something like this:
- (IBAction)action:(id)sender {
while (1) {
[NSArray arrayWithObject:@"just something to use up memory"];
}
}
Watch the process in Activity Monitor after you click the button and
you'll see the memory usage will just keep going up until you kill the
process. If on the other hand you run the same loop in a background
thread, so that the GUI thread isn't blocked, then the process
maintains a constant memory usage. I.e. change the action to
something like this:
- (void)allocateForever {
while (1) {
[NSArray arrayWithObject:@"just something to use up memory"];
}
}
- (IBAction) action:(id)sender {
[self performSelectorInBackground:@selector(allocateForever)
withObject:nil];
}
Now when you click the button you'll see the CPU usage go to 100%, but
the memory usage will stay constant. So it seems that something in
the run loop in the GUI thread needs to be running regularly in order
for GC to work.
I've read through the Garbage Collection Programming Guide on Apple's
site, and it claims that GC is handled in its own thread, and doesn't
mention anything special you need to to do enable it other than
building with -fobjc-gc. So does anyone know what explains the
limitations I've described above, or what the run loop is doing in GUI
apps that makes GC work correctly?
Thank you,
Adam
_______________________________________________
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