Re: Optimizing NSRectFill
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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