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

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Fastest way to push strings to the screen in an NSView?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fastest way to push strings to the screen in an NSView?


  • Subject: Re: Fastest way to push strings to the screen in an NSView?
  • From: Douglas Davidson <email@hidden>
  • Date: Thu, 18 Nov 2004 10:46:27 -0800


On Nov 17, 2004, at 6:45 PM, Robbie Haertel wrote:


I got that quote straight from Apple's documentation.  I agree that
NSLayoutManager should only be used if it is really worth it, but he
asked why he might be having problems so I'm assuming there's a
possibility that he thinks it is worth it or he wouldn't of asked.  I
also agree that things aren't always optimized for all cases, but hey,
he wanted to know why he was having a bottleneck and I offered an
answer :)!

I quite agree, and I think your recommendation was the right one for this case. I just want to make sure that more detailed information is out there for others who might be in slightly different situations.


I'm the engineer responsible for large portions of the string drawing code, and its performance characteristics are something I spend quite a bit of time on, so please forgive me if I go on at some length about it. :)

I do believe that NSLayoutManager also caches glyphs.  So, even if the
same letter and attribute (I believe he said his attributes are always
the same) are reused more than once (versus say entire strings that
are the same), there should still be an increase in performance.  The
amount of the increase will depend on the amount of redudancy, in this
case I imagine certain letters will be used with very high frequency
(the vowels, t, n, etc.)

The situation is this: text drawing requires a fair bit of work to get from characters and their attributes to pixels on the screen. In most cases performance depends heavily on how much of that work can be avoided by caching. There are several steps in the process and several ways in which that can be accomplished.


The string drawing methods--drawAtPoint:, drawInRect:, etc.--are the simplest APIs for drawing arbitrary text in a view. They also offer the least opportunity for caching, because they don't provide an object to retain any of the information used when drawing. Under the hood, we do make attempts to cache as much information as we reasonably can, but our ability to do so is inherently limited. There is definitely a large class of texts for which we have made these methods quite fast--principally the sort of strings commonly seen in drawing user interfaces. I won't attempt to characterize them, because the class expands from release to release; what I can recommend is that you sample to see whether text drawing is a significant portion of your drawing time, and if so whether methods and functions with "layout" in the name take up most of it. If so, then you might consider moving to the use of NSLayoutManager methods for your drawing.

(One performance hint with string drawing is that the string drawing methods are designed to be used in a flipped view; they can be used in a non-flipped view, but there often is a performance penalty for this. NSLayoutManager drawing, on the other hand, assumes a flipped view and is not intended to be used in a non-flipped view.)

When you create an NSTextStorage/NSTextContainer/NSLayoutManager combination, as in the CircleView and Worm examples, you have control over the caching of layout information. NSLayoutManager stores the identities of the glyphs, and their positions in the layout. All of this information is calculated the first time it is needed, and then reused as long as the text remains the same. Even if the text changes, NSLayoutManager recalculates only the portion actually affected by the change. Drawing then is just a matter of sending the glyphs and their locations to Quartz to be rendered into bits on the screen. In most cases this would be the combination I would recommend for performance-sensitive drawing.

It is also possible to use Quartz glyph drawing APIs directly. However, in most cases the performance gain over the use of NSLayoutManager will be slight. The primary performance difference is that with the Quartz APIs you have control over the setting of the font, color, and other portions of the graphics state. NSLayoutManager must do this for each drawing call, but you could potentially avoid some repetition if you were to do it yourself. One case that might benefit from this would be EvenBetterWormView, in which glyphs are drawn one at a time; this is a bit exceptional, though, as in most cases glyphs will be drawn in larger chunks, and graphics state manipulation becomes less significant.

The primary caution about using Quartz directly is that Quartz does not do any of the work of properly converting characters to glyphs and laying these glyphs out relative to each other, which is necessary for correct text display. The right thing to do would be to use NSLayoutManager for this, and to obtain from it the glyphs and their relative positions. Alternatively, one could use ATSUI, which provides similar functionality in a lower-level API, giving you somewhat more control but requiring more work. An additional caution about using Quartz directly is that NSLayoutManager provides certain additional drawing such as underlines and shadows; if you needed these, with Quartz you would have to do it yourself.

Some developers go beyond this to avoid even the work of having Quartz render the glyphs, by caching the actual pixels in an NSImage. If you have only a few strings to draw and your performance needs are extreme, this can be a useful technique. The problem is that it requires significant amounts of memory. I should warn you, also, that Quartz glyph rendering has been the subject of a great deal of performance work, and is something that has improved and will improve significantly from release to release. It is likely that in some cases use of cached images will actually be detrimental to performance, because of the VRAM impact of the images. The performance characteristics of Quartz glyph rendering vary based on the range of glyphs that are used--not really at the level of character frequency in English, but more at the level of the dozens of glyphs used in English vs. the thousands used in Japanese or Chinese. I would not use image caching without careful performance measurement.

For certain special needs it is possible to go beyond image caching, and actually draw the text once in a separate window, then move or order that window as needed. That would avoid the drawing stage altogether, and put the text on screen directly through the window compositor. If you needed to have a piece of text move rapidly across the screen, especially if it was to go beyond the bounds of ordinary windows, that could be something to consider. It's not really suitable for ordinary string drawing, however, and the overhead is quite large; I would use this only with a very small number of windows, and only in very special cases.

Douglas Davidson




_______________________________________________ Do not post admin requests to the list. They will be ignored. Cocoa-dev mailing list (email@hidden) Help/Unsubscribe/Update your Subscription: This email sent to email@hidden
References: 
 >Fastest way to push strings to the screen in an NSView? (From: Scott Ellsworth <email@hidden>)
 >Re: Fastest way to push strings to the screen in an NSView? (From: Robbie Haertel <email@hidden>)
 >Re: Fastest way to push strings to the screen in an NSView? (From: Douglas Davidson <email@hidden>)
 >Re: Fastest way to push strings to the screen in an NSView? (From: Robbie Haertel <email@hidden>)

  • Prev by Date: Problem with some clicks not registering in 10.3.6?
  • Next by Date: Re: NSImage question
  • Previous by thread: Re: Fastest way to push strings to the screen in an NSView?
  • Next by thread: Re: Fastest way to push strings to the screen in an NSView?
  • Index(es):
    • Date
    • Thread