Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Performance of Swift vs Objective-C

I am just comparing the performance of Swift and Objective-C. For that, I am using NSDate to measure the time taken, but I am getting a big difference between Swift and Objective-C. I just ran an empty for loop 100,000 times. Here is my code,

In Objective-C,

NSDate * start = [NSDate date];

for (int i=0; i<=100000; i++) {

}

NSDate * end = [NSDate date];

double timeTaken = [end timeIntervalSinceDate:start] * 1000;

timeTaken is 0.24 milliseconds

In Swift,

var start = NSDate()

    for i in 0...100000

    {

    }

    var end = NSDate()

    var timeTaken = end.timeIntervalSinceDate(start) * 1000

timeTaken is 74 milliseconds in Swift, which is a big difference when compared to Objective-C.

Am I doing anything wrong here in the measurement?

like image 249
user3714324 Avatar asked Jun 06 '14 08:06

user3714324


2 Answers

What you are doing is pure nonsense. It doesn't matter what the performance of this loop is, because it doesn't happen in real code. The essential difference is that in Swift, the loop will do overflow checks at each step which are a required side effect due to the language definition. In Objective-C, that's not the case.

At the very least you need to do code that does actually meaningful things.

I've done some real tests, and the results were: 1. Speed of Swift and plain C for low-level operations are comparable. 2. When on overflow happens, Swift will kill the program so you can notice the overflow, while C and Objective-C will silently give you nonsense results. Try this:

var i: Int = 0
var s: Double = 0.0

for (i in 1 .. 10_000_000_000) { s += Double (i * i) }

Swift will crash. (Anyone who thinks that's bad hasn't got a clue about programming). The same thing in Objective-C will produce a nonsense result. Replace the loop with

for (i in 1 .. 10_000_000_000) { s += Double (i) * Double (i) }

and both run at comparable speed.

like image 118
gnasher729 Avatar answered Oct 12 '22 11:10

gnasher729


I did some tests with sort function which used native Swift array and Swift string compared to Objective C mutable array and NSString.

Function was ordering 1000 strings and it performed ~ milion string comparisons and it shuffled the array.

Results were the following:

  • Objective C (using primitive integers and booleans): 0.32 seconds

  • Objective C (using NSNumber for integers and booleans): 0.45 seconds

  • Swift in debug mode: 13 seconds :)

  • Swift with Optimization level (Fastest [-O]): 1.32 seconds

  • Swift with Optimization level (Fastest, Unchecked [-Ofast]): 0.67 seconds

Seems in fastest mode Swift came pretty close to Objective C but it is still not faster as Apple claim(ed).

This is sort code I used:

Swift:

var strFile = String.stringWithContentsOfFile("1000strings.txt", encoding: NSUTF8StringEncoding, error: nil)
var strings:String[] = strFile!.componentsSeparatedByString("\n")
var startDate = NSDate()
var shouldLoopAgain = true
var numberOfLoops = 0
while shouldLoopAgain {
    shouldLoopAgain = false
    ++numberOfLoops
    for var i = 0; i < strings.count-1; ++i {
        if (strings[i] > strings[i+1]) {
            let temp = strings[i]
            strings[i] = strings[i+1]
            strings[i+1] = temp;
            if !shouldLoopAgain {
                shouldLoopAgain = true
            }
        }
    }
}
var time = NSDate().timeIntervalSinceDate(startDate)

Objective C with primitive boolean and integers

NSMutableArray *strings = [NSMutableArray arrayWithArray:[strFile componentsSeparatedByString:@"\n"]];
NSDate *startDate = [NSDate date];
BOOL shouldLoopAgain = YES;
int numberOfLoops = 0;
while (shouldLoopAgain) {
    shouldLoopAgain = NO;
    ++numberOfLoops;
    for (int i = 0; i < strings.count-1; ++i) {
        if ([strings[i] compare:strings[i+1]] == NSOrderedDescending) {
            NSString *temp = strings[i];
            strings[i] = strings[i+1];
            strings[i+1] = temp;
            if (!shouldLoopAgain) {
                shouldLoopAgain = YES;
            }
        }
    }
}

NSTimeInterval time = [[NSDate date] timeIntervalSinceDate:startDate];

Objective C with NSNumber for boolean and integers

NSDate *startDate = [NSDate date];
NSNumber *shouldLoopAgain = @YES;
NSNumber *numberOfLoops = @(0);
while ([shouldLoopAgain boolValue]) {
    shouldLoopAgain = @NO;
    numberOfLoops = @([numberOfLoops intValue]+1);
    for (NSNumber *i = 0; [i intValue] < strings.count-1; i = @([i intValue]+1)) {
        if ([strings[[i intValue]] compare:strings[[i intValue]+1]] == NSOrderedDescending) {
            NSString *temp = strings[[i intValue]];
            strings[[i intValue]] = strings[[i intValue]+1];
            strings[[i intValue]+1] = temp;
            if (![shouldLoopAgain boolValue]) {
                shouldLoopAgain = @YES;
            }
        }
    }
}
NSTimeInterval time = [[NSDate date] timeIntervalSinceDate:startDate];
like image 38
Matej Ukmar Avatar answered Oct 12 '22 11:10

Matej Ukmar