C vs Objective-C with Loop Unrolling (-O3)

Member
Posts: 21
Joined: 2003.01
Post: #1
I did some test with C vs Objective-C for function/methods in tight loops that are unrolled with the -O3 flag. I am assuming my code is all correct, I checked it a couple times. I know this isn't a totally accurate overhead calculation but I thought it would be worth posting.

Notice how the IMP method call is faster then C function pointers. Objective-C methods are nearly 4.5x slower then the IMP method. The IMP is a little bit over being 2x as slow as regular C functions. Inline was slower then regular C functions? I wonder if it is messing up the onrolling optimization?

BTW, does anybody know of NSObject's replacement for methodFor, if any?

Code:
Define: 3221ms

Inline: 7316ms

Function: 6473ms

Function Pointer: 20593ms

Object: 64035ms

Object IMP: 13969ms

NSObject: 64066ms

2006-07-19 20:23:56.150 a[650] *** -[double6 methodFor:]: warning: Object compatibility method has been executed at least once.  Convert source code off it NOW!
NSObject IMP: 14662ms

Code:
// gcc -O3 -lobjc -framework Cocoa main.m -o a

#import <objc/Object.h>
#import <Cocoa/Cocoa.h>
#import <CoreServices/CoreServices.h>


/* Define */
#define double1(x) (x + x)

/* Inline Function */
inline int double2(int x);
inline int double2(int x) { return x + x; }

/* Function */
int double3(int x);
int double3(int x) { return x + x; }

/* Function Pointer */
int (*double4)(int) = double3;

/* Object Method */
@interface double5: Object {}
    - (int)doit:(int)x;
@end

@implementation double5
    - (int)doit:(int)x { return x + x; }
@end

/* NSObject Method */
@interface double6: NSObject {}
    - (int)doit:(int)x;
@end

@implementation double6
    - (int)doit:(int)x { return x + x; }
@end


/* Timer */
unsigned long seed();
unsigned long seed() {
    AbsoluteTime atime = UpTime();
    Nanoseconds time = AbsoluteToNanoseconds(atime);
    return ((unsigned long *)&time)[1];
}

int main() {
    
    unsigned long i, timed;

    /* Code Cache */
    for(i = 0; i < 100; i++)
        timed = seed();
    
    /* Define */
    for(i = 0; i < 100; i++)
        double1(i);
    
    timed = seed();
    for(i = 0; i < 1000; i++)
        double1(i);
    printf("Define: %dms\n\n", seed() - timed);
    
    
    /* Inline */
    for(i = 0; i < 100; i++)
        double2(i);
    
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        double2(i);
    printf("Inline: %dms\n\n", seed(0) - timed);
    
    
    /* Function */
    for(i = 0; i < 100; i++)
        double3(i);
    
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        double3(i);
    printf("Function: %dms\n\n", seed(0) - timed);
    
    
    /* Function Pointer */
    for(i = 0; i < 100; i++)
        (*double4)(i);
    
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        (*double4)(i);
    printf("Function Pointer: %dms\n\n", seed(0) - timed);
    
    
    /* Object */
    id obj = [[double5 alloc] init];
    for(i = 0; i < 100; i++)
        [obj doit:i];
        
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        [obj doit:i];
    printf("Object: %dms\n\n", seed(0) - timed);
    
    
    /* Object IMP */
    IMP imp = [obj methodFor:@selector(doit:)];
    for(i = 0; i < 100; i++)
        imp(obj, @selector(doit), i);
        
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        imp(obj, @selector(doit), i);
    printf("Object IMP: %dms\n\n", seed(0) - timed);
    
    
    /* NSObject */
    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
    obj = [[double6 alloc] init];
    for(i = 0; i < 100; i++)
        [obj doit:i];
        
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        [obj doit:i];
    printf("NSObject: %dms\n\n", seed(0) - timed);
    
    
    /* NSObject IMP */
    imp = [obj methodFor:@selector(doit:)];
    for(i = 0; i < 100; i++)
        imp(obj, @selector(doit), i);
        
    timed = seed(0);
    for(i = 0; i < 1000; i++)
        imp(obj, @selector(doit), i);
    printf("NSObject IMP: %dms\n\n", seed(0) - timed);
    [autoreleasepool release];
    
    return 0;
        
}
Quote this message in a reply
Member
Posts: 469
Joined: 2002.10
Post: #2

---Kelvin--
15.4" MacBook Pro revA
1.83GHz/2GB/250GB
Quote this message in a reply
Luminary
Posts: 5,143
Joined: 2002.04
Post: #3
Make sure you've checked the assembly code to ensure that it's really doing what you think it is (eg. it's not inlining the "function" case, is inlining the inline case, is unrolling all the loops the same amount, etc.)
Quote this message in a reply
Post Reply