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.png


For 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 size
CGImageRef 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_getIvarLayout
0.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_address
0.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_references
0.0% 0.1% libauto.dylib Auto::Zone::invalidate_garbage(unsigned long, unsigned long const*)
        0.0%    0.0%    libSystem.B.dylib               vm_msync
0.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             RCCopyMethodsArrayForIdentifier


There 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.



Attachment: 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

Reply via email to