Mar 2007

WWDC 2007: infinite possibilities

I was looking at the WWDC 2007 site and saw this: “Six session tracks. Infinite possibilities.”

If the possibilities are truly infinite, then we’re getting an SDK for iPhone development. ;)

Not that I’m holding my breath.

NetNewsWire 3.0d62: new sneak peek release

I just posted a new sneak peek release: NetNewsWire 3.0d62. Still dangerous!

You can get it from the beta page (even though it’s not even a beta).

The change notes page lists things like automatic updates via Sparkle, choice between vertical and horizontal tabs, tabs export command, hide/show tabs, easy crash reporting, restored enclosures and dinosaurs features, memory use and performance enhancements, cache cleanups, removal of the Bonjour feature, lots of bug fixes, and more. (Plenty more. ;)

This weblog frobs the receiver(s)

If you’ve used Property List Editor to edit script terminology plist files you’ve seen something like this before:

Screen shot of Property List Editor: This command frobs the receiver(s)

(Yes, I know we’re supposed to switch to sdef: I’d already done so for MarsEdit, but haven’t yet for NetNewsWire.)

Anyway, I’ve always liked how it puts “This command frobs the receiver(s).” in there for me automatically.

[RSDev:~] brent% whois frobsreceiver.com
...
No match for "FROBSRECEIVER.COM".
>>> Last update of whois database: Thu, 15 Mar 2007 23:06:35 UTC <<<

[WebBaseNetscapePluginView pluginViewWithCheesyAntichristReference]

For the past week or so I’ve been running NetNewsWire in MallocDebug—I’m working on memory use. What I’ve found is that, at least for typical uses, WebKit uses most of the memory. (Images, especially. By the way, I’ve tried running with recent WebKit builds, and I’m excited—from my testing so far it appears that memory use is much improved. Looking good.)

Anyway, I just ran across the plugin-view of the beast, which sums up my feelings about plugins and the evil in their scummy hearts.

Screenshot from MallocDebug

Workaround for CIImage to NSImage memory issue

This is another of those things posted for the benefit of other Mac developers using Google to research a problem...

NetNewsWire 3 uses Core Image to do a few things, most noticeably to tint the feed and folder icons to match the subscriptions list background.

Core Image, as I was pleased to discover, makes doing stuff like this really, really easy, and it’s fun to use. It takes just a few lines of code to run a filter on an image.

Now, the only slightly tricky part is I’m working with NSImage everywhere in NetNewsWire, but Core Image uses CIImage. So I have to take an NSImage, create a CIImage based on it, run a filter on the CIImage (the tinting or whatever)—and then create an NSImage from the altered CIImage. (The NSImage is what gets displayed.)

Both Dan Wood and Scott Stevenson have written about doing the conversions, so you can see that it’s not particularly hard.

Anyway...

I’ve been working on NetNewsWire’s memory use by using leaks, ObjectAlloc, and MallocDebug. And I saw that my CIImage to NSImage conversion was using a lot of memory. It wasn’t reported as a leak but as an allocation by MallocDebug—and I saw that memory use kept going up and up when I triggered it.

I discovered that creating an NSImage from a CIImage—if the CIImage has had a filter run on it—can cause unnecessary memory use on some systems. On my development machine, for instance, but not on the PowerBook sitting next to me.

So... after a couple days of doing a bunch of research, emailing with people, pulling hair, reporting a bug to Apple (rdar://5046037), getting help reporting a bug to Apple, complaining on Twitter, complaining to the private testers, explaining the issue to my cat, I finally found a workaround.

Here’s an app (with source) that shows the leak.

What it does is create an NSImage from a CIImage over and over. You can watch the app’s memory use go up in top or Activity Monitor. (Unless it doesn’t, because it doesn’t leak on every system.)

CIImageLeakDemo

It also includes the workaround, which is, in a nutshell, to use the software renderer, rather than the GPU.

For any case where performance is an issue, this workaround isn’t usable. But in my case it’s fine.

The leaking code (re-formatted for the web) looks like this:

NSImage *image = [[[NSImage alloc] initWithSize:
	NSMakeSize([ciImage extent].size.width,
	[ciImage extent].size.height)]
	autorelease];
[image lockFocus];
[[[NSGraphicsContext currentContext] CIContext]
	drawImage:ciImage atPoint:CGPointMake(0, 0)
	fromRect:[ciImage extent]];
	/*This appears to be the line that leaks*/
[image unlockFocus];

The non-leaking code looks like this:

NSImage *image = [[[NSImage alloc] initWithSize:
	NSMakeSize([ciImage extent].size.width,
	[ciImage extent].size.height)]
	autorelease];
[image lockFocus];
CGContextRef contextRef =
	[[NSGraphicsContext currentContext]
	graphicsPort];
CIContext *ciContext =
	[CIContext contextWithCGContext:contextRef
	options:[NSDictionary dictionaryWithObject:
	[NSNumber numberWithBool:YES]
	forKey:kCIContextUseSoftwareRenderer]];
[ciContext drawImage:ciImage
	atPoint:CGPointMake(0, 0) fromRect:[ciImage extent]];
	/*Does not leak when using the software renderer!*/
[image unlockFocus];

My hope, of course, is that this workaround is needed temporarily, that it will get fixed. Obviously, using the software renderer defeats much of what’s cool about Core Image. But, for now, hey, cool, no leak, at least.

Archive