• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Threads & communication performance
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Threads & communication performance


  • Subject: Re: Threads & communication performance
  • From: Hsu <email@hidden>
  • Date: Tue, 9 Aug 2005 19:54:16 -0700

Each time you do a performSelectorOnMainThread: (hereafter pSONMT), you probably end up invoking setNeedsDisplay:YES on some NSView (directly or indirectly). This marks the window as needing update (setViewsNeedDisplay:YES). This means that immediately after handling the pSONMT (before returning, if it's synchronous) the window will draw and (probably) flush. You are probably calling pSONMT, and thereby dirtying the window, quite a bit more frequently than is necessary. You can "fix" this in 2 ways.

The first is to just set a timer on the main thread that updates the UI X times per second (easy to base this on the monitor refresh rate[1]) - just pick up the current state from a shared, locked ivar which is modified by the compute thread. This is pretty easy to do.

The other way is to batch the pSONMT calls in some fashion - once on the main thread, just check if it's been more than X seconds since the last update - if so, just mark the window as clean at the end of the call, and wait for the next update to check again[2]. If you use the second method, make sure you don't end up with a "dangling" update at the end - when the compute thread is finished, make sure that the window is marked dirty for the last update.

[1] http://developer.apple.com/documentation/Performance/Conceptual/ Drawing/Articles/FlushingContent.html#//apple_ref/doc/uid/TP40001835 -117520
[2] Something like[3]:


- (void) updateUI {
	// update UI here ...

	CFTimeInterval now = CFAbsoluteTimeGetCurrent();
	CFTimeInterval diff = _lastUpdateTime - now;
	if (diff < MAX_UPDATE_INTERVAL) {
		[[self window] setViewsNeedDisplay:NO];
	} else {
		_lastUpdateTime = CFAbsoluteTimeGetCurrent();
	}
}


[3]: Not tested.

Karl


On Aug 8, 2005, at 6:34 PM, Laurent Michel wrote:


An interesting observation I just made....

I remember reading hints about the 'virtues' (performance wise) of disabling beam-sync through the Quartz Debug tools... So I went ahead and did this....

Before disabling: The refresh were coming through at a rate of ~35FPS. The application 'felt' sluggish and took 1m10s to complete the same task as the batch version (which does its job in 10s)

After disabling: Refresh rate solid at > 90FPS (the gauge maxed out). The two CPUS are quite busy. Not full use, but way more that 10% and a total running time of 14s!!!!

So... Beam-sync seems to be causing the 'problem'/'pause'.

Now I understand (and saw) that beam-sync is there to prevent horizontal shearing when dragging windows. But still, the window here isn't dragged around and I really wonder what I could do to regain the performance I expect without disabling beam-sync....

Any advice ? Suggestions ?


On Aug 8, 2005, at 8:01 PM, Shaun Wexler wrote:

On Aug 8, 2005, at 3:16 PM, Laurent Michel wrote:


I have a behavior in my application that is somewhat disappointing and puzzling. In a nutshell, the application has two threads, one is a Cocoa thread and manages the UI, the other is compute-bound. The compute bound thread wishes to send 'updates' to the UI thread regularly (when events of interest occurs).


You are using a high-overhead approach which also tightly couples and effectively single-threads the process. You need to uncouple the GUI from the calculations, and minimize your cross-thread messaging. There are many more efficient ways to do this, but for brevity this should serve as an example:


#include <std_mail_disclaimer.h>

static UInt32 dataDirty __attribute__ ((aligned (4))) = 0;

- (void)calculationThread:(id)someObject
{
    while ([self hasWorkToDo])
    {
        [self performOneIterationOfWork];

if (CompareAndSwap(0, 1, &dataDirty)) {
NSData *data = [self copyDataForDisplay];
[self performSelectorOnMainThread:@selector(updateData:) withObject:data waitUntilDone:NO];
}
}
}


- (void)updateData:(NSData *)data
{
    [matrixController setMatrixWithCalculatedData:data];
    [matrix displayIfNeeded];
    CompareAndSwap(1, 0, &dataDirty);
    [data release];
}

If you use a custom matrix, you can add another atomic flag to -drawRect: and nearly eliminate all subsequent cross-thread perform messages, and Tiger will nicely limit drawing rate to max refresh for you.

HTH~
--
Shaun Wexler
MacFOH
http://www.macfoh.com

Efficiency is intelligent laziness.




_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden

--

If you hit a man over the head with a fish, he'll have a headache for a day. But if you teach a man to hit himself over the head with a fish, he'll have headaches for the rest of his life.

Homepage:
     http://homepage.mac.com/khsu/index.html

_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


References: 
 >Threads & communication performance (From: Laurent Michel <email@hidden>)
 >Re: Threads & communication performance (From: Shaun Wexler <email@hidden>)
 >Re: Threads & communication performance (From: Laurent Michel <email@hidden>)

  • Prev by Date: bind to a singleton in interface builder
  • Next by Date: Re: Flipping a window, Dashboard-style
  • Previous by thread: Re: Threads & communication performance
  • Next by thread: [NEWBIE] windowDidBecomeKey ?
  • Index(es):
    • Date
    • Thread