[Openmcl-devel] Re: Hemlock performance investigation

Gary Byers gb at clozure.com
Thu Aug 26 21:39:42 UTC 2004

On Thu, 26 Aug 2004, Hamilton Link wrote:

> We have a winner!
> *character-at-index-callback*: 20.995 seconds
> *hemlock-char-at-index*: 5.06 seconds
> *update-line-cache-for-index*: 1.411 seconds
> *mark-absolute-position*: 0.021 seconds
> *reset-buffer-cache*: 0.014 seconds
> *move-hemlock-mark-to-absolute-position*: 0.001 seconds
> So, a couple more questions for the panel:
> - can we set up something in the ObjC world so that this specific
> callback is invoked less (crossing the FFI boundary can't be all that
> great to begin with) than the hundreds of thousands of times that it
> is?

I think that the only way to get Cocoa to call characterAtIndex: less
often is to make smaller files.  It's possible (I don't remember for
sure) that the text system would call some substring-related method
(instead of repeatedly asking for each character) if the
HemlockBufferString class implemented that method.  If this is the
case, it might be possible to cons up a string every now and then
instead of finding a character very often.

characterAtIndex: is supposed to be a primitive, relatively low-cost
operation.  The FFI callback overhead doesn't seem to be significant;
the cost of determining that SELF was an ObjC instance does.  When I
tried metering this with Shark (a step that still requires trying to
look up the lisp functions associated with an address range manually),
I saw that the busiest function was CCL::BIGNUM-COMPARE.  These calls
came from code which compared the address of a possible ObjC pointer
to the addresses of known ObjC library data segments (that might
contain NSStrings); all of these addresses were represented as
integers, and all happened to be bignums.

Another similar (potential) bottleneck is the
attributesAtIndex:effectiveRange: callback.

> - better still, since we are 100% certain that self is an objc object
> (or it wouldn't have been in an objc callback as self, right?) is there
> a way the bridge can be tweaked to skip checking on 'self' in all
> callbacks?

Yes. It's also reasonable to skip the sanity-checking on arguments
declared to be of foreign-type :ID.

> - alternatively is a lower-level high-performance slot accessor
> available that skips checking on any object that we're comfy with that
> can be substituted for the safe, slow one during optimization?

Back in the 0.13 Cocoa, there was a scheme to associate small integers
with lisp objects; a foreign object could retain the "object id" of a
lisp object and method callbacks could fetch the object associated
with an id.  Foreign objects were responsible for freeing these
identifiers (I don't know that they always did.)

Using SLOT-VALUE is probably saner and simpler (for the user), but
it involves a hash lookup and a generic function call, at least. If
there's evidence that we're spending a lot of time doing these things
in the characterAtIndex: callback and other bottlenecks, I guess that
we could revive the old object-id scheme.

I'm not sure (it's pretty tedious to analyze Shark's output manually)
whether using SLOT-VALUE's a problem, assuming that it's cheap to
determine that SELF is "an instance of the HEMLOCK-BUFFER-STRING class".

> thanks,
> h

More information about the Openmcl-devel mailing list