It seems that about 20% of the time is spent in the Garbage Collector thread!Which is a bit surprising to me, since I don't allocate a large number of objects (I think) -- just a small number of large objects (the images).The collector only chews CPU when there are lots of allocation events (and, hopefully, deallocation events) that are causing the collector to believe it needs to do work. Or when something is triggering the collector manually really often.Have a look at ObjectAlloc & ObjectGraph in Instruments. That should give you an idea if there are lots and lots of allocation events occurring and, if so, what they are. From there, it is a matter of minimizing the number of allocations occurring.
If I understand the output of Instruments/ObjectAlloc correctly, it says there have been about 300,000 allocations withing about 1.5 minutes.
Is that very much?It also says that most of the allocations are CFStrings and small memory blocks (surprise surprise ;-) ), but looking at the instances it seems to me that I don't have much control over those. (For instance, about half of the CFString's occur in the library CFNetwork in the functions initializeTLDMachine() and MemoryCookies::inflateFromData().)
Since I couldn't find a way to export the statistics in ASCII, I have made 3 screenshots, which you can see here:
http://zach.in.tu-clausthal.de/tmp/malloc1.png http://zach.in.tu-clausthal.de/tmp/malloc2.png http://zach.in.tu-clausthal.de/tmp/malloc3.pngFor your information, here is an outline of my main loop (executed in ScreenSaverView's -animateOneFrame):
get a new filename from a list of filenames CGImageSourceRef sourceRef = CGImageSourceCreateWithURL(..) check a few things in the sourceRef, such as image sizeCGImageRef imageRef = CGImageSourceCreateImageAtIndex(sourceRef, 0, NULL) [NSTimer scheduledTimerWithTimeInterval: 2.3 target: self selector: @selector(doGarbageCollection:) userInfo: nil repeats: NO];
create new layer with contents = imageRef create a new animation and attach it to the new layer [CATransaction begin];[CATransaction setValue: [NSNumber numberWithFloat: fading_duration] forKey: kCATransactionAnimationDuration ];
[mainLayer_ replaceSublayer: currentLayer_ with: newlayer]; currentLayer_ = newlayer; [CATransaction commit]; This gets executed every 5 seconds. And here is what doGarbageCollection does: - (void) doGarbageCollection: (NSTimer *) theTimer { if ( [NSGarbageCollector defaultCollector] )[[NSGarbageCollector defaultCollector] collectExhaustively]; // seems to work better than collectIfNeeded
}I have tried omitting doGarbageCollection: , but then the screensaver's memory footprint grows until the memory is full, and then the animation stops for a second or 2 (you can see the memroy being freed in ActivityMonitor).
The judder I am concerned with seems to occur especially during image loading.
Again, the same code, when executed in the reference-counted environment (10.5) runs very smoothly, no judder whatsoever, not even during loading of an image.
Are you sure you aren't just seeing the GC thread sitting and waiting for something to do?
THat would mean that the GC thread does busy waiting, wouldn't it?
What are the "hot" methods/functions you see related to the GC thread? (many folks misread what Shark is telling them...)
Here are the top lines of the call tree that I see in Shark. It seems to me that they all belong to the same thread, the GC thread.So, one of the hot methods is Auto::MemoryScanner::scan_for_unmarked_blocks, isn't it?
0.0% 31.7% libSystem.B.dylib start_wqthread 0.0% 31.7% libSystem.B.dylib _pthread_wqthread 0.0% 31.7% libSystem.B.dylib _dispatch_worker_thread2 0.0% 20.4% libSystem.B.dylib _dispatch_queue_invoke 0.0% 20.4% libSystem.B.dylib _dispatch_queue_drain 0.0% 20.4% libSystem.B.dylib _dispatch_call_block_and_release 0.0% 20.4% libauto.dylib auto_collection_work(Auto::Zone*)0.0% 20.4% libauto.dylib auto_collect_internal(Auto::Zone*, unsigned int) 0.0% 20.3% libauto.dylib Auto::Zone::collect(bool, void*, unsigned long long*)
0.0% 18.5% libauto.dylib Auto::MemoryScanner::scan()0.6% 17.1% libauto.dylib Auto::MemoryScanner::scan_pending_until_done() 0.6% 15.0% libauto.dylib Auto::MemoryScanner::scan_for_unmarked_blocks(Auto::Subzone*, unsigned long, void*) 0.4% 7.3% libauto.dylib Auto::MemoryScanner::scan_object_range(Auto::Range&, Auto::WriteBarrier*) 3.2% 4.7% libauto.dylib Auto::MemoryScanner::scan_range(Auto::Range const&, Auto::WriteBarrier*) 1.4% 1.4% libauto.dylib Auto::MemoryScanner::set_pending(void*) 0.1% 0.1% libauto.dylib Auto::MemoryScanner::check_block(void**, void*)
2.0% 2.0% libobjc.A.dylib objc_layout_for_address 0.1% 0.1% libobjc.A.dylib class_getIvarLayout0.0% 0.0% libauto.dylib Auto::MemoryScanner::set_pending(void*) 0.0% 0.0% libauto.dylib Auto::MemoryScanner::check_block(void**, void*) 5.2% 7.0% libauto.dylib Auto::MemoryScanner::scan_range(Auto::Range const&, Auto::WriteBarrier*) 0.1% 0.1% libauto.dylib Auto::MemoryScanner::set_pending(void*) 0.0% 0.0% libauto.dylib Auto::MemoryScanner::check_block(void**, void*)
0.0% 0.0% libobjc.A.dylib objc_layout_for_address0.9% 1.4% libauto.dylib Auto::MemoryScanner::scan_range(Auto::Range const&, Auto::WriteBarrier*) 0.0% 0.0% libauto.dylib Auto::MemoryScanner::set_pending(void*) 0.0% 0.0% libauto.dylib Auto::MemoryScanner::scan_object_range(Auto::Range&, Auto::WriteBarrier*)
0.0% 1.4% libauto.dylib Auto::Collector::check_roots()0.0% 0.0% libauto.dylib Auto::MemoryScanner::scan_root_ranges() 0.0% 0.0% libauto.dylib Auto::MemoryScanner::scan_thread_ranges(bool, bool)
0.0% 0.0% libauto.dylib Auto::Collector::scan_barrier()1.8% 1.8% libauto.dylib bool Auto::visitAllocatedBlocks<Auto::scavenge_blocks_visitor>(Auto::Zone*, Auto::scavenge_blocks_visitor&)
0.0% 0.0% libauto.dylib weak_clear_references0.0% 0.1% libauto.dylib Auto::Zone::invalidate_garbage(unsigned long, unsigned long const*)
0.0% 0.0% libSystem.B.dylib vm_msync0.0% 0.0% libauto.dylib Auto::Zone::free_garbage(unsigned int, unsigned long, unsigned long*, unsigned long&, unsigned long&)
0.0% 0.0% libauto.dylib Auto::Admin::purge_free_space() 0.0% 11.2% libSystem.B.dylib _dispatch_apply2 0.0% 11.2% RawCamera GetRawPluginsInfo 0.0% 8.2% RawCamera RCCopyMethodsArrayForIdentifier 0.0% 3.0% RawCamera GetRawPluginsInfo 0.0% 2.9% libSystem.B.dylib dispatch_apply_f 0.0% 2.9% libSystem.B.dylib _dispatch_apply2 0.0% 2.9% RawCamera GetRawPluginsInfo 0.0% 2.9% RawCamera RCCopyMethodsArrayForIdentifier 1.7% 2.9% RawCamera GetRawPluginsInfo 0.0% 0.0% RawCamera GetRawPluginsInfo 0.0% 0.0% libSystem.B.dylib calloc 0.0% 0.0% RawCamera RCCopyMethodsArrayForIdentifierThere is another thread, NSApplicationMain, that takes 25% CPU, of which almost everything is spent in CA::Render::copy_image (which seems plausible to me).
Anf then there is one thread that takes about 20% CPU, and which spends almost all time in CA::OGL::Context::render.
Any ideas, suggestions, and insights will be highly appreciated. Best regards, Gabriel.
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) 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: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com