On Jan 23, 2012, at 9:41 AM, Rob Duarte wrote:
> The project is here: http://dl.dropbox.com/u/15876611/leaktest.zip It's
> literally only a few lines of code at this point.
>
> I just tried leaks with MallocStackLogging=YES but it seems to show the same
> level of detail that Instruments shows?
>
> I'd love it if I were just misunderstanding how leaks/Instruments works, but
> the bar graph getting larger and larger seems to be indicating 'bad' even to
> a memory management novice like me. :)
It's not the "bad" that I'm interested in. It's the "why" that matters, and
stack logging helps identify that (which makes fixing it much easier).
Without stack logging, leaks shows you something like this (heavily abridged):
> Process: leaktest [94491]
> Path:
> /Volumes/Data/Users/cwright/Downloads/leaktest/build/Release/leaktest.app/Contents/MacOS/./leaktest
> Load Address: 0x107760000
> Identifier: com.yourcompany.leaktest
> Version: 2.0 (1.0)
> Code Type: X86-64 (Native)
> Parent Process: bash [283]
>
> Date/Time: 2012-01-23 10:20:52.618 -0800
> OS Version: Mac OS X 10.7.2 (11C74)
> Report Version: 7
>
> leaks Report Version: 2.0
> Process 94491: 30668 nodes malloced for 6159 KB
> Process 94491: 204 leaks for 9104 total leaked bytes.
> Leak: 0x7f91f1429490 size=64 zone: DefaultMallocZone_0x107764000
> __NSCFDictionary ObjC CoreFoundation item count: 1
> Leak: 0x7f91f142a7f0 size=48 zone: DefaultMallocZone_0x107764000
> NSConcreteValue ObjC Foundation
> 0x7b1caea8 0x00007fff 0x00000001 0x00000000 ...{............
> 0x7b1f25f0 0x00007fff 0xc5a32677 0xc0072b2b .%.{....w&..++..
> 0x0c49ba5e 0x3fee5b02 0x00000000 0x00000000 ^.I..[.?........
That tells us there's a dictionary and an NSValue getting leaked. that's about
it though.
With stack logging, you get this (also heavily abridged):
> Process: leaktest [94545]
> Path:
> /Volumes/Data/Users/cwright/Downloads/leaktest/build/Release/leaktest.app/Contents/MacOS/./leaktest
> Load Address: 0x104db1000
> Identifier: com.yourcompany.leaktest
> Version: 2.0 (1.0)
> Code Type: X86-64 (Native)
> Parent Process: bash [283]
>
> Date/Time: 2012-01-23 10:22:10.633 -0800
> OS Version: Mac OS X 10.7.2 (11C74)
> Report Version: 7
>
> leaks Report Version: 2.0
> Process 94545: 30244 nodes malloced for 6082 KB
> Process 94545: 47 leaks for 2112 total leaked bytes.
> Leak: 0x7fa02a46b840 size=64 zone: DefaultMallocZone_0x104db5000
> __NSCFDictionary ObjC CoreFoundation item count: 1
> Call stack: [thread 0x7fff7b024960]: | 0x1 | start | NSApplicationMain
> | -[NSApplication run] | -[NSApplication
> nextEventMatchingMask:untilDate:inMode:dequeue:] | _DPSNextEvent |
> BlockUntilNextEventMatchingListInMode | ReceiveNextEventCommon |
> RunCurrentEventLoopInMode | CFRunLoopRunSpecific | __CFRunLoopRun |
> __CFRunLoopDoTimer |
> __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | _TimerCallback |
> -[QCView _renderTimer] | +[NSDictionary dictionaryWithObject:forKey:] |
> -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] |
> CFDictionaryCreate | __CFDictionaryCreateGeneric | CFBasicHashCreate |
> _CFRuntimeCreateInstance | malloc_zone_malloc
> Leak: 0x7fa02c159550 size=48 zone: DefaultMallocZone_0x104db5000
> NSConcreteValue ObjC Foundation
> 0x7b1caea8 0x00007fff 0x00000001 0x00000000 ...{............
> 0x7b1f25f0 0x00007fff 0xc6f6b70c 0x3ff5c7ea .%.{...........?
> 0xeb851eb8 0xc009dc51 0x00000000 0x00000000 ....Q...........
> Call stack: [thread 0x7fff7b024960]: | 0x1 | start | NSApplicationMain
> | -[NSApplication run] | -[NSApplication
> nextEventMatchingMask:untilDate:inMode:dequeue:] | _DPSNextEvent |
> BlockUntilNextEventMatchingListInMode | ReceiveNextEventCommon |
> RunCurrentEventLoopInMode | CFRunLoopRunSpecific | __CFRunLoopRun |
> __CFRunLoopDoTimer |
> __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ | _TimerCallback |
> -[QCView _renderTimer] | +[NSValue valueWithPoint:] | +[NSValue
> valueWithBytes:objCType:] | _NSNewValue | NSAllocateObject |
> class_createInstance | calloc | malloc_zone_calloc
so there appear to be 2 leaks in QCView, both in QCView _renderTimer (a private
method). It looks like it's leaking a dictionary by way of
dictionaryWithObject:forKey:, and an NSValue by way of valueWithPoint:.
We can assess this further: those two functions are convenience functions
(because there's no new/copy/init in their names), meaning the objects are
autoreleased by default. Since there aren't any complaints about an
autorelease pool not being in place (where these kinds of functions are
intended to leak, with an error log message), it appears that somewhere inside
QC there's an overretain of those values (so when the autorelease pool is
drained, they don't get freed).
We can then explore this even further, but I haven't bothered to do so: you've
minimized the amount of obj-C code employed here, but you haven't minimized the
composition. Does an empty composition reproduce this? Does a particular
patch inside the composition do this? There are plenty of permutations to try.
Instruments, I believe, can also log retains/releases of objects, so it could
also help identify what is actually doing the retain-without-release.
by the way, I can reproduce this on current versions of things (not just
10.6.8), so it's worth filing a bug, especially if you can prune the
composition down some more.
As a second-order analysis, the above example leaked 9k (~2 pages) over the
course of maybe a minute. 1440 minutes in a day (60 minutes per hour * 24
hours per day) * 2 pages = 2880 pages (11.25MB per day). in 64 bit, there are
4503599627370496 pages (2 ^ (64 (host address space bits) -12 (bits per
page))), meaning it'd take 4503599627370496 / 2880 = 1563749870615 days
(4284246220.9 years) to exhaust the address range completely. Assuming a
4GB-of-ram system (1048576 pages), it'd take ~364 days to start paging (1048576
pages / 2880 pages-per-day) assuming there was no other system load (grossly
optimistic). Realistically, you've probably got a good month or two of
per-second reloads before it really starts affecting anything.
So as long as you expect to load compositions much less frequently than once
per second, and you don't plan to run for several months/years at a time,
you're probably not heading towards an imminent system-thrashing leak unless
you plan to run for several months at a time, or have a severely
memory-constrained system. (not trying to downplay the wrongness of the leak,
just trying to put it in perspective).
--
Christopher Wright
[email protected]
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Quartzcomposer-dev mailing list ([email protected])
Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/quartzcomposer-dev/archive%40mail-archive.com
This email sent to [email protected]