Re: Instance Variable access
Re: Instance Variable access
- Subject: Re: Instance Variable access
- From: mmalcolm crawford <email@hidden>
- Date: Fri, 7 May 2004 18:20:59 -0700
On May 7, 2004, at 5:54 PM, Tim Ramsey wrote:
While this is an excellent answer, it does not answer the original
question - at least not for me. The response is about why it is good to
use ObjC_msgSend and makes an excellent point. However, the question is
about how to avoid ObjC_msgSend in favor of a more direct route in the
interest of speed. The answer to that question is also of interest to
me
I thought that had been addressed by Glen's answer -- using IMPs, see:
<
http://developer.apple.com/documentation/Performance/Conceptual/
CodeSpeed/Tasks/CriticalCode.html>
Note, however, the caveats in that article, and the advice in recent
posts here (appended below for convenience).
mmalc
From: email@hidden
Subject: Re: calling method via IMP that returns non id type -
compiler warning
Date: February 15, 2004 6:29:26 PM PST
To: email@hidden
Cc: email@hidden
On Feb 15, 2004, at 4:25 PM, Ben Dougall wrote:
On Sunday, February 15, 2004, at 06:59 pm, b.bum wrote:
On Feb 15, 2004, at 8:59 AM, Ben Dougall wrote:
i've used an IMP to call a method, and that method returns a
typedeffed type that isn't an object pointer -- not an id type that
is. it all works fine apart from it gives a warning. if i cast the
returned value from the IMP call the warning goes away -- but is
that the way to fix that?
Most likely, you haven't declared the type of theMethodIMP
appropriately. It shouldn't just be IMP, but needs to be specific to
the signature of the method you are invoking.
I.e. something like.....
MyType (*theMethodIMP)(id, SEL, unsigned);
i tried amongst other things this in the .h:
extern MyType (*theMethodIMP)(id, SEL, unsigned);
and in the .m:
MyType *theMethodIMP = nil;
or
MyType (*theMethodIMP)(id, SEL, unsigned) = nil;
:/ i don't know.
can't get it to work. i'll just cast the return of the call via IMP --
seems to work fine.
Though it is tempting to go with what appears to work, not
understanding why it does or does not work is a bad idea -- as it is,
it is working merely by coincidence. If you break that coincidence,
you are in for some long hours of not very fun debugging. I would
highly recommend understanding the C language thoroughly before trying
to do things like this -- it'll save you quite a bit of frustration at
some point. (I speak from some rather painfully gained experience --
I took the "oh, look, it just works... yay... i have no idea why, but i
don't care.... oh, crap, 20 hours of debugging in GDB only to figure
out that it was just a coincidence..." approach to understanding C
pointers).
Looking at the docs (searched google for "IMP instanceMethodForSelector
declaration"):
http://developer.apple.com/documentation/Cocoa/Reference/Foundation/
ObjC_classic/Classes/NSObject.html
And it would appear that you likely need a declaration like:
MyType *(*theMethodIMP)(id, SEL, unsigned);
Note the extra *. Isn't C fun?
theMethodIMP = ... instanceMethodForSelector: ...
result = theMethodIMP(self, @selector(theMethod:), value)
(all typed in email -- you'll have to figure out the exact syntax for
the decl if that isn't right).
....
- why are you doing this in the first place? Is there some reason
not to use NSInvocation or just invoke the method as you normally
would? Generally, calling the IMP directly is a performance
optimization only used in extreme cases. Have you identified a
performance hit that warrants such a solution? (You might have -- I
don't know -- but I do know that just about every time this has ever
come up on the list(s), it has been a case of "premature
optimization").
no i haven't identified a performance problem because the app doesn't
exist yet really. the reason i'm doing it is because this is a fixed
method of a singleton that i know will be called many times throughout
the code -- i don't want or need any dynamic/flexible behaviour for
this particular method so because i can access it via an IMP i might
aswell.
This is an extremely uncommon pattern to use. The overhead of a
method invocation is trivial in comparison to drawing, event handling,
I/O or any of a number of other random things that may happen in your
app.
Unless you have some kind of a tight loop or have instrumented your
code and determined that the normal usage pattern really is a
performance bottleneck [extremely unlikely], doing this kind of
optimization this early in the development cycle will cause more
problems than it solves. It makes it very difficult to refactor the
code or generalize the classes into reusable APIs.
In doing performance optimization on various random ObjC apps over the
years, I have yet to run across a situation where direct IMP access has
yielded a useful performance boost outside of the tightest of loops.
Most benefit has come from avoiding the execution of code through the
use of aggressive caching, lazy evaluation, optimized drawing, and/or
communications protocol optimization. All of these are much easier to
do-- both instrument and to refactor the actual code-- if there hasn't
been misdirected optimizations that move the code away from being a
pure OO model.
b.bum
_______________________________________________
From: email@hidden
Subject: Re: calling method via IMP that returns non id type -
compiler warning
Date: February 15, 2004 9:09:51 PM PST
To: email@hidden
Hello...
In doing performance optimization on various random ObjC apps over the
years, I have yet to run across a situation where direct IMP access
has yielded a useful performance boost outside of the tightest of
loops.
Just to provide a concrete example of why doing this specific type of
optimization (using IMPs to access methods instead of using normal
messaging) is rarely needed, and shouldn't really be considered during
the design phase:
At one point I was working on some code for a class that was very
similar to NSMatrix and required calculations for the layout of its
cells. I had a very simple method for doing layout that returned the
rect of a cell at any particular row and column, by calculating the
origin for that cell and using a fixed size (basically the equivalent
of cellFrameAtRow:column:).
When the matrix was being drawn, the layout method was called once for
each "cell" in the matrix. The cell drawing code was using the NSString
method drawInRect:withAttributes:, and I wasn't happy with the
performance, but that was outside my control at that point. So I
figured I would try using an IMP to access the layout method to speed
up the loop that caused the cells to be drawn in the matrix drawing
method (which iterated through all of the cell positions calculating
the location and telling it to draw), since it was being called a
significant number of times (and although inlining the layout code
would have been faster yet, there were several reasons I didn't want to
do that).
So, I wrote a second version of the drawing code for the matrix, with
the only difference being that it used an IMP to access the layout
method as a function during the loop instead of using obj-C messaging.
Let me just say that I was significantly underwhelmed by the
performance boost :)
It turned out that my matrix needed to be have more than a 100x100 cell
area being drawn to see a significant difference in speed. And when I
say significant, I mean a _mathematically_ significant difference, not
a noticable difference. I had an NSLog statement at the beginning and
end of each verison of the drawing code to record the start and end
times. For a matrix that was smaller than about 100x100 cells, the
difference is speed between the two versions (impDone - impStart) and
(messageDone - messageStart) was generally undetectable... even though
NSLog outputs the time down to the millisecond !!! For a 100x100 cell
matrix, the layout method would have been called 10,000 times, and the
difference in the _total_ time for all 10,000 calls was slightly less
than a millisecond (ie more often than not the difference was 0.001
instead of 0.000).
Needless to say, I don't think anyone will notice the difference in
speed between using an IMP and using normal messaging even if your
method is called frequently, unless it is basically called continuously
without anything else happening.
Louis
_______________________________________________
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.