[Openmcl-devel] Re: Hemlock performance investigation

mikel evins mikel at evins.net
Sat Aug 28 01:35:44 PDT 2004

On Aug 28, 2004, at 12:04 AM, Hamilton Link wrote:

>>> Would the buffer happen to be one monolithic Unicode NSString (or is  
>>> something expecting to be accessing an NSString)?  If so, O(n)  
>>> accesses occur for every call to character-at-index since this is  
>>> Unicode.  It has to walk the entire string from the beginning since  
>>> the size in bytes of a character is not fixed.  If you scan every  
>>> character in the file, then that is also O(n).
>> This certainly might be the culprit.  Quoting the NSString  
>> documentation:
>> http://developer.apple.com/documentation/Cocoa/Reference/Foundation/ 
>> ObjC_classic/Classes/NSString.html#//apple_ref/doc/uid/20000154/ 
>> getCharacters_range_
>> getCharacters:range:
>> - (void)getCharacters:(unichar *)buffer range:(NSRange)aRange
>> Copies characters from aRange in the receiver into buffer, which must  
>> be large enough to contain them. Does not add a zero character.  
>> Raises an NSRangeException if any part of aRange lies beyond the end  
>> of the receiver.
>> The abstract implementation of this method uses characterAtIndex:  
>> repeatedly, correctly extracting the characters, though very  
>> inefficiently. Subclasses should override it to provide a fast  
>> implementation.
> By now you have seen that hemlock-buffer-string is a subclass of  
> ns-string, so I agree this should be a way to make layout faster.  
> Disabling background layout solves the problem completely, and if  
> layout calls this or (more likely) getCharacters, that would explain  
> everything we are seeing. Good find.
> Specializing get-characters is necessary and should speed up initial  
> layout and re-layout, but mind you this still won't make things less  
> than linear, it will just be a faster linear. Disabling background  
> layout during most of editing is probably a better way to go (given  
> that even a several-times speedup would only prevent the problem up to  
> somewhat-larger files).
> I will see if I can squeeze this in this weekend.

So the ns-string object belongs to the text storage object, which  
cooperates with the layout manager and the text container and the text  
view to display the text. One thing to try is messing around with the  
layout manager. When you edit an attributed string it posts  
notifications that end up causing a call to  
textStorage:edited:range:changeInLength:invalidatedRange: on the  
NSLayoutManager, and you might be able to arrange, for example to defer  
layout until something happens that makes it necessary.

The set of messages that gets sent is intricate, but there's a useful  
diagram about the subject at


With a little experimentation I think you could puzzle out which of  
those messages to hook by subclassing or use of delegates to suppress  
most of the unnecessary layout recalculation.

One thing that Alpaca does is it imposes a page size that doesn't  
change with window resizing. It therefore does not layout calculation  
when a window is resized. This might not work with a code editor, of  
course, but, on the other hand, if other people, like me, tend to use  
code windows that are sized horizontally to a common line width then it  
might be an option. For example, I can imagine maing small changes to  
the custom text views in Alpaca such that the horizontal page size  
would be 'sticky' (though changeable if you really want to change it),  
and the vertical page size would be unbounded, thus preserving the  
natural feel of code editing, but eliminating the need to recalculate  
layout in some common situations.


More information about the Openmcl-devel mailing list