Re: Optimizing NSRectFill

2008-12-22 Thread Peter Ammon
setNeedsDisplay: and setNeedsDisplayInRect: do not integrate with  
coalesced updates as well as they might.  If you call setNeedsDisplay:  
faster than 60 times per second, then you will encounter the problem  
described in the technote.


Did turning off coalesced updates in Quartz Debug help?  If so, do not  
call setNeedsDisplay: or setNeedsDisplayInRect: for every event, but  
only if the time since the previous call is at least 1/60th of a  
second.  This should give you the responsiveness you expect.


On Dec 20, 2008, at 6:22 AM, Oleg Krupnov wrote:


Here is how I arrived at the conclusion that NSRectFill is the
bottleneck. (I cannot show the code because it's spread over objects).

The slowness of redraw is only noticeable when I drag the mouse, e.g.
to resize an object in the custom view. I see that update of the
resized object is always late after the actual position of the mouse
pointer, and the latency is sometimes pretty great to not be excused.
Especially when the size of the rectangle to be updated is large.

My custom view supports zooming, so I call NSRectFill after setting an
NSAffineTransform. Larger zooms, as I said, seem to cause greater
latency. Sometimes I also use clipping ([NSBezierPath addClip]) before
calling NSRectFill.

I never call -[NSView displayIfNeeded] or use other ways of forcing
the view to update itself. I always rely on -[NSView
setNeedsDisplayInRect:] to invalidate the rectangle(s) that need to be
updated and then wait until the next refresh. What is true, that
-[NSView setNeedsDisplayInRect:] are often called multiple times for
the same rectangles, but I don't think it matters.

I run my app with the Shark tool and drag the mouse to resize an
object, to and fro, for few seconds, then check the sample. It always
shows that 20-30% of time is taken by the NSRectFill function, which
is called only once to simply draw the background of the view with
solid white! This is ridiculous. I tried to put an NSLog  near the
NSRectFill call to check if it is called extra times, but it seems
that it is being called exactly one time per single mouse drag
message. When I comment out the call to NSRectFill, then the refresh
becomes noticeably smoother, and the Shark gives leadership to other
bottlenecks, in my case the NSBezierPath stroke and fill messages, for
the objects drawn in the view.

Any ideas?


On Sat, Dec 20, 2008 at 1:45 AM, Peter Ammon pam...@apple.com wrote:


On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the  
hood)

that I use to draw the background of the view.


A common cause of apparently excessive time in graphics related ops  
is that
you are running afoul of coalesced updates by attempting to refresh  
faster

than 60 times a second.

See
http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html 
 .
Try disabling coalesced updates in Quartz Debug and see if it  
speeds up
your drawing.  If so, ensure your app does not refresh faster than  
60 Hz.


-Peter




___

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


Re: Optimizing NSRectFill

2008-12-21 Thread Scott Ribe
 I did a quick test.
 I have a 1ms timer which just do -setNeedDisplay: on a small view.
 And the result is that my timer callback is called 60 times per seconds.
 If I remove the seetNeedDisplay: call, it is called 1000 times (as
 expected).
 
 So I think that you're right (and that everything is synchronous) but
 I also think that the 'flush results to screen' blocks until the
 screen is ready and so limit the number of redraw to the refresh rate
 of the screen.
 If this is effectively the case, your timer trick will not be very
 helpful.

That was a surprise to me. My understanding was that the entire purpose of
setNeedsDisplay was to queue up deferred drawing requests so that they'd be
taken care of in a single later drawRect call on the effected objects.

And when I checked the tech note that you referenced, I found that it makes
this explicit:

 In Cocoa use NSView's setNeedsDisplay: to request an update for a view instead
 of the more immediate display:

I guess what Mike is proposing is that redrawing in response to
setNeedsDisplay is only deferred until the end of handling the current
event? (And therefore only improves things when there are multiple calls on
the same view.) This is at least consistent with the documentation, as far
as I know. But I had assumed that somewhere the system was putting more of
an effort into deciding when to redraw marked views. And my assumption, as
far as I can tell, was also consistent with the available documentation.

Unless I've missed something, the documentation needs clarification on this
point, *especially* that tech note.

-- 
Scott Ribe
scott_r...@killerbytes.com
http://www.killerbytes.com/
(303) 722-0567 voice


___

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


Re: Optimizing NSRectFill

2008-12-21 Thread Michael Ash
On Sun, Dec 21, 2008 at 11:49 AM, Scott Ribe scott_r...@killerbytes.com wrote:
 I guess what Mike is proposing is that redrawing in response to
 setNeedsDisplay is only deferred until the end of handling the current
 event? (And therefore only improves things when there are multiple calls on
 the same view.) This is at least consistent with the documentation, as far
 as I know. But I had assumed that somewhere the system was putting more of
 an effort into deciding when to redraw marked views. And my assumption, as
 far as I can tell, was also consistent with the available documentation.

That is indeed what I'm proposing. In other words, you'll always have this:

event: invalidate view
view: redraw
event: invalidate view
view: redraw

And never this:

event: invalidate view
event: invalidate view
view: redraw

This is how I believe it works based on my knowledge of the frameworks
and my experience. As to whether it matches up with reality, I would
not go so far as to make any claims there

Mike
___

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


Re: Optimizing NSRectFill

2008-12-21 Thread Glenn L. Austin

On Dec 21, 2008, at 9:43 AM, Michael Ash wrote:

On Sun, Dec 21, 2008 at 11:49 AM, Scott Ribe scott_r...@killerbytes.com 
 wrote:

I guess what Mike is proposing is that redrawing in response to
setNeedsDisplay is only deferred until the end of handling the  
current
event? (And therefore only improves things when there are multiple  
calls on
the same view.) This is at least consistent with the documentation,  
as far
as I know. But I had assumed that somewhere the system was putting  
more of
an effort into deciding when to redraw marked views. And my  
assumption, as
far as I can tell, was also consistent with the available  
documentation.


That is indeed what I'm proposing. In other words, you'll always  
have this:


event: invalidate view
view: redraw
event: invalidate view
view: redraw

And never this:

event: invalidate view
event: invalidate view
view: redraw


I've seen both -- you can't guarantee one or the other.

IIRC, user events have priority over system-generated events (like  
redraws).


___

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


Re: Optimizing NSRectFill

2008-12-21 Thread Michael Ash
On Sun, Dec 21, 2008 at 3:58 PM, Glenn L. Austin gl...@austin-soft.com wrote:
 On Dec 21, 2008, at 9:43 AM, Michael Ash wrote:

 On Sun, Dec 21, 2008 at 11:49 AM, Scott Ribe scott_r...@killerbytes.com
 wrote:

 I guess what Mike is proposing is that redrawing in response to
 setNeedsDisplay is only deferred until the end of handling the current
 event? (And therefore only improves things when there are multiple calls
 on
 the same view.) This is at least consistent with the documentation, as
 far
 as I know. But I had assumed that somewhere the system was putting more
 of
 an effort into deciding when to redraw marked views. And my assumption,
 as
 far as I can tell, was also consistent with the available documentation.

 That is indeed what I'm proposing. In other words, you'll always have
 this:

 event: invalidate view
 view: redraw
 event: invalidate view
 view: redraw

 And never this:

 event: invalidate view
 event: invalidate view
 view: redraw

 I've seen both -- you can't guarantee one or the other.

 IIRC, user events have priority over system-generated events (like redraws).

I figured I ought to quit pontificating and offer some real data.

I wrote a really basic NSView subclass:

- (void)drawRect: (NSRect)r
{
NSLog(@%s, __func__);
sleep(1);
}

- (void)mouseDragged: (NSEvent *)e
{
NSLog(@%s: %@, __func__, e);
[self setNeedsDisplay:YES];
}

- (void)mouseDown: (NSEvent *)e
{
NSLog(@%s: %@, __func__, e);
[self setNeedsDisplay:YES];
}

And then stuck it in a basic Cocoa project and tried it out.

The basic outline of what I said above appears to be correct. The log
always showed one event handling message followed by one draw, no
matter what I did.

However, something I didn't know: it appears that something coalesces
mouseDragged: events. They don't pile up the way I thought I would.
Rather, when you come back around, you only get one mouseDragged: with
the latest location. In other words, while the framework always
follows a consistent event, draw, event, draw sequence (at least in my
testing) it will not build up a long queue of events simply from
dragging the mouse around.

It *does* build up a long queue by clicking. I can make the app freeze
up for an arbitrary amount of time by just clicking the mouse over and
over again in the view. So beware of that.

Also if you actually care about the path that the user's mouse took in
the time between drawing, you'll have to do something fancier. If all
you care about is following it around, it seems that there is no need
to do anything special. And note that this applies to slowdowns both
from crappy code (like mine) and from beam sync, so the OP who was
seeing a bunch of lag and very delayed processing of mouse dragged
events must have been seeing something else.

Mike
___

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


Re: Optimizing NSRectFill

2008-12-21 Thread Ken Thomases

On Dec 21, 2008, at 3:45 PM, Michael Ash wrote:


However, something I didn't know: it appears that something coalesces
mouseDragged: events. They don't pile up the way I thought I would.
Rather, when you come back around, you only get one mouseDragged: with
the latest location. In other words, while the framework always
follows a consistent event, draw, event, draw sequence (at least in my
testing) it will not build up a long queue of events simply from
dragging the mouse around.

[...]

Also if you actually care about the path that the user's mouse took in
the time between drawing, you'll have to do something fancier.


See SetMouseCoalescingEnabled and IsMouseCoalescingEnabled.

Cheers,
Ken

___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Oleg Krupnov
Here is how I arrived at the conclusion that NSRectFill is the
bottleneck. (I cannot show the code because it's spread over objects).

The slowness of redraw is only noticeable when I drag the mouse, e.g.
to resize an object in the custom view. I see that update of the
resized object is always late after the actual position of the mouse
pointer, and the latency is sometimes pretty great to not be excused.
Especially when the size of the rectangle to be updated is large.

My custom view supports zooming, so I call NSRectFill after setting an
NSAffineTransform. Larger zooms, as I said, seem to cause greater
latency. Sometimes I also use clipping ([NSBezierPath addClip]) before
calling NSRectFill.

I never call -[NSView displayIfNeeded] or use other ways of forcing
the view to update itself. I always rely on -[NSView
setNeedsDisplayInRect:] to invalidate the rectangle(s) that need to be
updated and then wait until the next refresh. What is true, that
-[NSView setNeedsDisplayInRect:] are often called multiple times for
the same rectangles, but I don't think it matters.

I run my app with the Shark tool and drag the mouse to resize an
object, to and fro, for few seconds, then check the sample. It always
shows that 20-30% of time is taken by the NSRectFill function, which
is called only once to simply draw the background of the view with
solid white! This is ridiculous. I tried to put an NSLog  near the
NSRectFill call to check if it is called extra times, but it seems
that it is being called exactly one time per single mouse drag
message. When I comment out the call to NSRectFill, then the refresh
becomes noticeably smoother, and the Shark gives leadership to other
bottlenecks, in my case the NSBezierPath stroke and fill messages, for
the objects drawn in the view.

Any ideas?


On Sat, Dec 20, 2008 at 1:45 AM, Peter Ammon pam...@apple.com wrote:

 On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:

 I'm developing a custom view and noticed that drawRect is becoming
 increasingly slow. The Shark has pointed out that the bottleneck is
 the NSRectFill function (that calls CGContextFillRect under the hood)
 that I use to draw the background of the view.

 A common cause of apparently excessive time in graphics related ops is that
 you are running afoul of coalesced updates by attempting to refresh faster
 than 60 times a second.

 See
 http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html
  .
  Try disabling coalesced updates in Quartz Debug and see if it speeds up
 your drawing.  If so, ensure your app does not refresh faster than 60 Hz.

 -Peter


___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Jean-Daniel Dupas


Le 20 déc. 08 à 15:22, Oleg Krupnov a écrit :


Here is how I arrived at the conclusion that NSRectFill is the
bottleneck. (I cannot show the code because it's spread over objects).

The slowness of redraw is only noticeable when I drag the mouse, e.g.
to resize an object in the custom view. I see that update of the
resized object is always late after the actual position of the mouse
pointer, and the latency is sometimes pretty great to not be excused.
Especially when the size of the rectangle to be updated is large.

My custom view supports zooming, so I call NSRectFill after setting an
NSAffineTransform. Larger zooms, as I said, seem to cause greater
latency. Sometimes I also use clipping ([NSBezierPath addClip]) before
calling NSRectFill.

I never call -[NSView displayIfNeeded] or use other ways of forcing
the view to update itself. I always rely on -[NSView
setNeedsDisplayInRect:] to invalidate the rectangle(s) that need to be
updated and then wait until the next refresh. What is true, that
-[NSView setNeedsDisplayInRect:] are often called multiple times for
the same rectangles, but I don't think it matters.

I run my app with the Shark tool and drag the mouse to resize an
object, to and fro, for few seconds, then check the sample. It always
shows that 20-30% of time is taken by the NSRectFill function, which
is called only once to simply draw the background of the view with
solid white! This is ridiculous. I tried to put an NSLog  near the
NSRectFill call to check if it is called extra times, but it seems
that it is being called exactly one time per single mouse drag
message. When I comment out the call to NSRectFill, then the refresh
becomes noticeably smoother, and the Shark gives leadership to other
bottlenecks, in my case the NSBezierPath stroke and fill messages, for
the objects drawn in the view.

Any ideas?


On Sat, Dec 20, 2008 at 1:45 AM, Peter Ammon pam...@apple.com wrote:


On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the  
hood)

that I use to draw the background of the view.


A common cause of apparently excessive time in graphics related ops  
is that
you are running afoul of coalesced updates by attempting to refresh  
faster

than 60 times a second.

See
http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html 
 .
Try disabling coalesced updates in Quartz Debug and see if it  
speeds up
your drawing.  If so, ensure your app does not refresh faster than  
60 Hz.


-Peter



___

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/devlists%40shadowlab.org

This email sent to devli...@shadowlab.org



___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Jean-Daniel Dupas

Sorry for the blank previous mail.

Try to call NSFillRect with the rect pased as parameter in drawRect:  
and before applying the scaling method.
As the rect parameter contains the invalid rect in screen coordinates,  
you don't have to transform it before filling the rect with white.



Le 20 déc. 08 à 15:22, Oleg Krupnov a écrit :


Here is how I arrived at the conclusion that NSRectFill is the
bottleneck. (I cannot show the code because it's spread over objects).

The slowness of redraw is only noticeable when I drag the mouse, e.g.
to resize an object in the custom view. I see that update of the
resized object is always late after the actual position of the mouse
pointer, and the latency is sometimes pretty great to not be excused.
Especially when the size of the rectangle to be updated is large.

My custom view supports zooming, so I call NSRectFill after setting an
NSAffineTransform. Larger zooms, as I said, seem to cause greater
latency. Sometimes I also use clipping ([NSBezierPath addClip]) before
calling NSRectFill.

I never call -[NSView displayIfNeeded] or use other ways of forcing
the view to update itself. I always rely on -[NSView
setNeedsDisplayInRect:] to invalidate the rectangle(s) that need to be
updated and then wait until the next refresh. What is true, that
-[NSView setNeedsDisplayInRect:] are often called multiple times for
the same rectangles, but I don't think it matters.

I run my app with the Shark tool and drag the mouse to resize an
object, to and fro, for few seconds, then check the sample. It always
shows that 20-30% of time is taken by the NSRectFill function, which
is called only once to simply draw the background of the view with
solid white! This is ridiculous. I tried to put an NSLog  near the
NSRectFill call to check if it is called extra times, but it seems
that it is being called exactly one time per single mouse drag
message. When I comment out the call to NSRectFill, then the refresh
becomes noticeably smoother, and the Shark gives leadership to other
bottlenecks, in my case the NSBezierPath stroke and fill messages, for
the objects drawn in the view.

Any ideas?


On Sat, Dec 20, 2008 at 1:45 AM, Peter Ammon pam...@apple.com wrote:


On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the  
hood)

that I use to draw the background of the view.


A common cause of apparently excessive time in graphics related ops  
is that
you are running afoul of coalesced updates by attempting to refresh  
faster

than 60 times a second.

See
http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html 
 .
Try disabling coalesced updates in Quartz Debug and see if it  
speeds up
your drawing.  If so, ensure your app does not refresh faster than  
60 Hz.


-Peter



___

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/devlists%40shadowlab.org

This email sent to devli...@shadowlab.org



___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Jean-Daniel Dupas


Le 20 déc. 08 à 15:33, Jean-Daniel Dupas a écrit :


Sorry for the blank previous mail.

Try to call NSFillRect with the rect pased as parameter in drawRect:  
and before applying the scaling method.
As the rect parameter contains the invalid rect in screen  
coordinates, you don't have to transform it before filling the rect  
with white.




To be exact, the rect parameter is in screen coordinates. So you have  
to convert it to your view coordinates before drawing.
And so, you have to apply to it the reverse of your view - screen  
transform (that you apply to the context).


And so, this is what append:
- You apply scaling to the context.
- You apply reverse scalling to the rect.
- You call Fill Rect =The system applies the context's transformation  
to your rect (and revert it back to screen coord) and fills it.


That's why I suggest you can fill it directly before applying the  
transform to the context.
But for other drawing, you should use the transformed rect to compute  
what should be refreshed.




Le 20 déc. 08 à 15:22, Oleg Krupnov a écrit :


Here is how I arrived at the conclusion that NSRectFill is the
bottleneck. (I cannot show the code because it's spread over  
objects).


The slowness of redraw is only noticeable when I drag the mouse, e.g.
to resize an object in the custom view. I see that update of the
resized object is always late after the actual position of the mouse
pointer, and the latency is sometimes pretty great to not be excused.
Especially when the size of the rectangle to be updated is large.

My custom view supports zooming, so I call NSRectFill after setting  
an

NSAffineTransform. Larger zooms, as I said, seem to cause greater
latency. Sometimes I also use clipping ([NSBezierPath addClip])  
before

calling NSRectFill.

I never call -[NSView displayIfNeeded] or use other ways of forcing
the view to update itself. I always rely on -[NSView
setNeedsDisplayInRect:] to invalidate the rectangle(s) that need to  
be

updated and then wait until the next refresh. What is true, that
-[NSView setNeedsDisplayInRect:] are often called multiple times for
the same rectangles, but I don't think it matters.

I run my app with the Shark tool and drag the mouse to resize an
object, to and fro, for few seconds, then check the sample. It always
shows that 20-30% of time is taken by the NSRectFill function, which
is called only once to simply draw the background of the view with
solid white! This is ridiculous. I tried to put an NSLog  near the
NSRectFill call to check if it is called extra times, but it seems
that it is being called exactly one time per single mouse drag
message. When I comment out the call to NSRectFill, then the refresh
becomes noticeably smoother, and the Shark gives leadership to other
bottlenecks, in my case the NSBezierPath stroke and fill messages,  
for

the objects drawn in the view.

Any ideas?


On Sat, Dec 20, 2008 at 1:45 AM, Peter Ammon pam...@apple.com  
wrote:


On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the  
hood)

that I use to draw the background of the view.


A common cause of apparently excessive time in graphics related  
ops is that
you are running afoul of coalesced updates by attempting to  
refresh faster

than 60 times a second.

See
http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html 
 .
Try disabling coalesced updates in Quartz Debug and see if it  
speeds up
your drawing.  If so, ensure your app does not refresh faster than  
60 Hz.


-Peter



___

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/devlists%40shadowlab.org

This email sent to devli...@shadowlab.org



___

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/devlists%40shadowlab.org

This email sent to devli...@shadowlab.org



___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Michael Ash
On Sat, Dec 20, 2008 at 9:22 AM, Oleg Krupnov oleg.krup...@gmail.com wrote:
 Here is how I arrived at the conclusion that NSRectFill is the
 bottleneck. (I cannot show the code because it's spread over objects).

 The slowness of redraw is only noticeable when I drag the mouse, e.g.
 to resize an object in the custom view. I see that update of the
 resized object is always late after the actual position of the mouse
 pointer, and the latency is sometimes pretty great to not be excused.
 Especially when the size of the rectangle to be updated is large.

When doing things like this you always need to coalesce events before
drawing. If you're triggering a redraw for every event then you always
leave yourself open to problems. The moment that your events come in
faster than your redraws can occur, you lose. This doesn't necessarily
only happen when your code is really slow. Maybe you find a user on a
really slow computer. Maybe the computer starts to swap. Maybe the
computer is running 300 CPU intensive processes simultaneously. Maybe
the mouse is sending events at 120Hz and the screen is only refreshing
at 60Hz.

A simple way to do this is to avoid calling setNeedsDisplay: (or its
friends) directly from your event handler. Instead start a timer with
some suitably small interval, and set a flag. If the flag is already
set, don't start the timer, it's already been started. When the timer
fires, invalidate the view and clear the flag.

Once you've done this, if it's still too slow then it will manifest as
simply being unsmooth, but it will still follow your mouse movements
in realtime, which is a substantial improvement. If it's still too
slow at that point then you can see what else might be going on and
try to fix it from a better position.

Mike
___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Bill Bumgarner

On Dec 20, 2008, at 9:18 AM, Michael Ash wrote:

When doing things like this you always need to coalesce events before
drawing. If you're triggering a redraw for every event then you always
leave yourself open to problems. The moment that your events come in
faster than your redraws can occur, you lose. This doesn't necessarily
only happen when your code is really slow. Maybe you find a user on a
really slow computer. Maybe the computer starts to swap. Maybe the
computer is running 300 CPU intensive processes simultaneously. Maybe
the mouse is sending events at 120Hz and the screen is only refreshing
at 60Hz.


And... maybe the test case involves grabbing something w/the mouse and  
then rapidly waving the object back and forth over the view to  
quickly grab some data to sample, thus making the original problem  
seem much, much, worse.


(No -- I'm not saying the problem doesn't exist... just that we  
developers tend toward spastic monkey behavior when optimizing  
something that a real user would perform with directness.)


b.bum
___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Kyle Sluder
On Sat, Dec 20, 2008 at 12:18 PM, Michael Ash michael@gmail.com wrote:
 A simple way to do this is to avoid calling setNeedsDisplay: (or its
 friends) directly from your event handler. Instead start a timer with
 some suitably small interval, and set a flag. If the flag is already
 set, don't start the timer, it's already been started. When the timer
 fires, invalidate the view and clear the flag.

Alright, perhaps I don't completely understand how the drawing model
works at a low enough level, but why would this be helpful?  Doesn't
AppKit just coalesce updates received by -setNeedsDisplayInRect: until
Quartz has finished pushing pixels?  So if you are accumulating dirty
rects in your event handler, your drawing should still be limited to
min(as fast as possible, 60hz).

Or am I thinking of the Quartz GL pipeline?

--Kyle Sluder
___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Jean-Daniel Dupas


Le 20 déc. 08 à 21:14, Michael Ash a écrit :

On Sat, Dec 20, 2008 at 1:51 PM, Kyle Sluder kyle.slu...@gmail.com  
wrote:
On Sat, Dec 20, 2008 at 12:18 PM, Michael Ash  
michael@gmail.com wrote:

A simple way to do this is to avoid calling setNeedsDisplay: (or its
friends) directly from your event handler. Instead start a timer  
with

some suitably small interval, and set a flag. If the flag is already
set, don't start the timer, it's already been started. When the  
timer

fires, invalidate the view and clear the flag.


Alright, perhaps I don't completely understand how the drawing model
works at a low enough level, but why would this be helpful?  Doesn't
AppKit just coalesce updates received by -setNeedsDisplayInRect:  
until

Quartz has finished pushing pixels?  So if you are accumulating dirty
rects in your event handler, your drawing should still be limited to
min(as fast as possible, 60hz).

Or am I thinking of the Quartz GL pipeline?


My understanding is that everything is sychronous. So if you call
setNeedsDisplay: in your event handler, then the sequence will always
look like this:

event handler
  mark view invalid
check for invalidated views
  redraw invalidated view
  flush results to screen
event handler
  mark view invalid
check for invalidated views
  redraw invalidated view
  flush results to screen

And so forth. I could be wrong about this, and if anyone knows better
please pipe up!


I did a quick test.
I have a 1ms timer which just do -setNeedDisplay: on a small view.
And the result is that my timer callback is called 60 times per seconds.
If I remove the seetNeedDisplay: call, it is called 1000 times (as  
expected).


So I think that you're right (and that everything is synchronous) but  
I also think that the 'flush results to screen' blocks until the  
screen is ready and so limit the number of redraw to the refresh rate  
of the screen.
If this is effectively the case, your timer trick will not be very  
helpful.






___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Jean-Daniel Dupas


Le 20 déc. 08 à 22:47, Jean-Daniel Dupas a écrit :



Le 20 déc. 08 à 21:14, Michael Ash a écrit :

On Sat, Dec 20, 2008 at 1:51 PM, Kyle Sluder  
kyle.slu...@gmail.com wrote:
On Sat, Dec 20, 2008 at 12:18 PM, Michael Ash  
michael@gmail.com wrote:
A simple way to do this is to avoid calling setNeedsDisplay: (or  
its
friends) directly from your event handler. Instead start a timer  
with
some suitably small interval, and set a flag. If the flag is  
already
set, don't start the timer, it's already been started. When the  
timer

fires, invalidate the view and clear the flag.


Alright, perhaps I don't completely understand how the drawing model
works at a low enough level, but why would this be helpful?  Doesn't
AppKit just coalesce updates received by -setNeedsDisplayInRect:  
until
Quartz has finished pushing pixels?  So if you are accumulating  
dirty

rects in your event handler, your drawing should still be limited to
min(as fast as possible, 60hz).

Or am I thinking of the Quartz GL pipeline?


My understanding is that everything is sychronous. So if you call
setNeedsDisplay: in your event handler, then the sequence will always
look like this:

event handler
 mark view invalid
check for invalidated views
 redraw invalidated view
 flush results to screen
event handler
 mark view invalid
check for invalidated views
 redraw invalidated view
 flush results to screen

And so forth. I could be wrong about this, and if anyone knows better
please pipe up!


I did a quick test.
I have a 1ms timer which just do -setNeedDisplay: on a small view.
And the result is that my timer callback is called 60 times per  
seconds.
If I remove the seetNeedDisplay: call, it is called 1000 times (as  
expected).


So I think that you're right (and that everything is synchronous)  
but I also think that the 'flush results to screen' blocks until the  
screen is ready and so limit the number of redraw to the refresh  
rate of the screen.
If this is effectively the case, your timer trick will not be very  
helpful.




How, and I found that too:

http://developer.apple.com/technotes/tn2005/tn2133.html






___

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


Re: Optimizing NSRectFill

2008-12-20 Thread Michael Ash
On Sat, Dec 20, 2008 at 4:47 PM, Jean-Daniel Dupas
devli...@shadowlab.org wrote:
 So I think that you're right (and that everything is synchronous) but I also
 think that the 'flush results to screen' blocks until the screen is ready
 and so limit the number of redraw to the refresh rate of the screen.
 If this is effectively the case, your timer trick will not be very helpful.

As long as the timer's time interval is less than the screen refresh
interval (and the technote says to simply assume 60Hz and that most
drawing doesn't need more than 30Hz, so that's easy enough to assure)
then it will work. And even if the timer is more, it will depend on
the behavior of the event loop. If the event loop is smart it will
process all queued events before running the next timer, in which case
the technique will work even for a zero-interval timer, but I don't
know if it actually works this way.

Mike
___

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


Optimizing NSRectFill

2008-12-19 Thread Oleg Krupnov
I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the hood)
that I use to draw the background of the view. I am disappointed that
such a basic operation could ever impair performance, but it does. It
looks like the bigger is the rectangle, the slower is performance.

I have read the list regarding this issue, but I haven't found any
solution. NSRectFillList, CGContextFillRect do not give any
performance gain.

My question is - is there a way to bypass the advanced path-related
stuff that causes the slow-down, and just get down to some kind of
fast drawing?
___

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


Re: Optimizing NSRectFill

2008-12-19 Thread Stéphane Sudre


On Dec 19, 2008, at 4:37 PM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the hood)
that I use to draw the background of the view. I am disappointed that
such a basic operation could ever impair performance, but it does. It
looks like the bigger is the rectangle, the slower is performance.

I have read the list regarding this issue, but I haven't found any
solution. NSRectFillList, CGContextFillRect do not give any
performance gain.

My question is - is there a way to bypass the advanced path-related
stuff that causes the slow-down, and just get down to some kind of
fast drawing?


There are different ways to optimize drawRect: drawings.

Most of them involves only refreshing the parts of the view that are  
really needed to be refreshed. You have different APIs and pieces of  
information that can help you with this task.


The first one being the NSRect used as the parameter for drawRect:. It  
describes the bounding box of the refresh area. If your issue is with  
the background of the view and your background pattern is just a  
color, use this NSRect for NSRectFill.



___

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


Re: Optimizing NSRectFill

2008-12-19 Thread Bill Bumgarner

On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:

I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the hood)
that I use to draw the background of the view. I am disappointed that
such a basic operation could ever impair performance, but it does. It
looks like the bigger is the rectangle, the slower is performance.

I have read the list regarding this issue, but I haven't found any
solution. NSRectFillList, CGContextFillRect do not give any
performance gain.

My question is - is there a way to bypass the advanced path-related
stuff that causes the slow-down, and just get down to some kind of
fast drawing?


NSRectFill is really damned fast.   Very very fast.   In my  
experience, it was the fastest way to draw points into a view (and  
then cache the points into bitmap images for subsequent renderings).   
See:


http://svn.red-bean.com/restedit/trunk/source/HopView.py

(It is in python, but it is Cocoa and uses the same APIs as you'd use  
in ObjC).


That code is literally rendering 10,000 points -- 10,000 1x1 rects --  
at a time in a few milliseconds.  From what anyone could tell, it was  
the fastest way to get individual points to the screen without going  
to Open GL.


That makes me suspect that there is something else going on in your  
drawing code.  That it becomes increasingly slow indicates that you  
are accumulating and then drawing more and more stuff over time?


Are you doing the calculations necessary to not draw the overlapping  
bits?   A little bit of math is always going to be faster than drawing  
to the screen.


b.bum


___

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


Re: Optimizing NSRectFill

2008-12-19 Thread Graham Cox


On 20 Dec 2008, at 2:37 am, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the hood)
that I use to draw the background of the view. I am disappointed that
such a basic operation could ever impair performance, but it does. It
looks like the bigger is the rectangle, the slower is performance.

I have read the list regarding this issue, but I haven't found any
solution. NSRectFillList, CGContextFillRect do not give any
performance gain.

My question is - is there a way to bypass the advanced path-related
stuff that causes the slow-down, and just get down to some kind of
fast drawing?


Show your code.

As Bill suggests, there's no way that NSRectFill is slow. If Shark is  
pointing the finger at it, it's probably because you are calling it  
much more often than necessary.


--Graham


___

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


Re: Optimizing NSRectFill

2008-12-19 Thread Peter Ammon


On Dec 19, 2008, at 7:37 AM, Oleg Krupnov wrote:


I'm developing a custom view and noticed that drawRect is becoming
increasingly slow. The Shark has pointed out that the bottleneck is
the NSRectFill function (that calls CGContextFillRect under the hood)
that I use to draw the background of the view.


A common cause of apparently excessive time in graphics related ops is  
that you are running afoul of coalesced updates by attempting to  
refresh faster than 60 times a second.


See http://developer.apple.com/documentation/Performance/Conceptual/Drawing/Articles/FlushingContent.html 
 .  Try disabling coalesced updates in Quartz Debug and see if it  
speeds up your drawing.  If so, ensure your app does not refresh  
faster than 60 Hz.


-Peter

___

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