[Openmcl-devel] Re: Hemlock performance investigation
mikel at evins.net
Sat Aug 28 04:35:44 EDT 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
>> - (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
> 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