Re: Threads & communication performance
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