Re: Message Forwarding Overhead / Performance
Re: Message Forwarding Overhead / Performance
- Subject: Re: Message Forwarding Overhead / Performance
- From: Jerry Krinock <email@hidden>
- Date: Tue, 28 Oct 2008 16:47:37 -0700
On 2008 Oct, 28, at 16:10, Peter Ammon wrote:
If you don't want to store or pick apart the message, but only route
it immediately to another object, you should use the
forwardingTargetForSelector: method, which will be faster than
forwardInvocation:.
forwardingTargetForSelector: is new to Leopard and is mentioned in
the release notes at http://developer.apple.com/ReleaseNotes/Cocoa/Foundation.html
Thank you, Peter. That looks like it might be just what I want.
Another lesson for today: Leopard is a year old but still need to
scrape release notes for some documentation!
On 2008 Oct, 28, at 15:37, Bill Bumgarner wrote:
Oooh... trivial tests! I like those! Can you share the code?
Depends what the message size limit is on this list. We're about to
find out. Pasted from two files but it should work...
#import <Foundation/Foundation.h>
@protocol SSYForwarder
@property (retain) id forwardee ;
/*!
@brief One of the four methods needed to support message forwarding
@detail This is invoked once each time an instance message is
forwarded
*/
- (void)forwardInvocation:(NSInvocation *)invocation ;
/*!
@brief One of the four methods needed to support message forwarding
@detail This is invoked once each time an instance message is
forwarded
*/
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector ;
/*!
@brief One of the four methods needed to support message forwarding
@detail This method is definitely needed if the selectors forwarded
are menu actions, probably because the system is asks if
respondsToSelector in order to enable/disable its menu item.
It does not get invoked for "normal" forwarded instance messages.
*/
- (BOOL)respondsToSelector:(SEL)selector ;
/*!
@brief One of the four methods needed to support message forwarding
@detail This method does not get invoked for forwarded instance
messages.
*/
+ (BOOL)instancesRespondToSelector:(SEL)selector ;
@end
@interface Forwardee : NSObject {
NSInteger forwardSum ;
}
@property (assign) NSInteger forwardSum ;
- (void)forwardlyAdd:(NSInteger)addend ;
@end
@implementation Forwardee
@synthesize forwardSum ;
- (void)forwardlyAdd:(NSInteger)addend {
forwardSum += addend ;
}
@end
@interface Forwarder : NSObject <SSYForwarder> {
NSInteger directSum ;
id forwardee ;
}
@property (assign) NSInteger directSum ;
@property (retain) id forwardee ;
@end
@implementation Forwarder
@synthesize directSum ;
@synthesize forwardee ;
- (void)directlyAdd:(NSInteger)addend {
directSum += addend ;
}
#pragma mark The Four Overrides Needed to Fully Support Message
Forwarding
- (void)forwardInvocation:(NSInvocation *)invocation {
id forwardee_ = [self forwardee] ;
if ([forwardee_ respondsToSelector:[invocation selector]]) {
[invocation invokeWithTarget:forwardee_] ;
}
else {
[super forwardInvocation:invocation] ;
}
}
- (NSMethodSignature*)methodSignatureForSelector:(SEL)selector {
NSMethodSignature* signature =[super
methodSignatureForSelector:selector] ;
if (!signature) {
id forwardee_ = [self forwardee] ;
signature = [forwardee_ methodSignatureForSelector:selector] ;
}
return signature;
}
- (BOOL)respondsToSelector:(SEL)selector {
if ( [super respondsToSelector:selector] ) {
return YES ;
}
else {
id forwardee_ = [self forwardee] ;
return [forwardee_ respondsToSelector:selector] ;
}
}
+ (BOOL)instancesRespondToSelector:(SEL)selector {
if ( [super instancesRespondToSelector:selector] ) {
return YES ;
}
else {
id forwardeeInstance = [[self alloc] init] ;
BOOL instanceResponds = [forwardeeInstance
respondsToSelector:selector] ;
[forwardeeInstance release] ;
return instanceResponds ;
}
}
#pragma mark Basic Infrastructure
- (void)dealloc {
[forwardee release] ; forwardee = nil ;
[super dealloc];
}
@end
/*!
@brief Demo sends a message to add integers, with and without
message forwarding, and logs the difference in performance
@detail In a real application, the Forwarder and Forwardee will
be two of your classes.
*/
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Forwarder* forwarder = [[Forwarder alloc] init] ;
Forwardee* forwardee = [[Forwardee alloc] init] ;
[forwarder setForwardee:forwardee] ;
NSInteger messages = 10000 ;
NSInteger i ;
NSDate* startDate ;
// Directly
startDate = [NSDate date] ;
for (i=0; i<messages; i++) {
[forwarder directlyAdd:i] ;
}
NSTimeInterval elapsedTimeD = -[startDate timeIntervalSinceNow] ;
NSLog(@" directSum = %d. elapsedTime = %0.3e", [forwarder
directSum], elapsedTimeD) ;
// via Message Forwarding
startDate = [NSDate date] ;
for (i=0; i<messages; i++) {
[forwarder forwardlyAdd:i] ;
}
NSTimeInterval elapsedTimeF = -[startDate timeIntervalSinceNow] ;
NSLog(@"forwardSum = %d. elapsedTime = %0.3e", [forwarder
forwardSum], elapsedTimeF) ;
NSLog(@"Avg penalty for 1 forwarded message = %0.3e secs",
(elapsedTimeF - elapsedTimeD)/messages) ;
[forwarder release] ;
[forwardee release] ;
[pool drain];
return 0;
}
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden