Производительность Swift vs Objective-C

Я просто сравниваю производительность Swift и Objective-C. Для этого я использую NSDate для измерения времени, но я получаю большую разницу между Swift и Objective-C. Я просто запускал пустой цикл for 100 000 раз. Вот мой код,

В Objective-C,

NSDate * start = [NSDate date];

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

}

NSDate * end = [NSDate date];

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

timeTaken составляет 0,24 миллисекунды

В Swift,

var start = NSDate()

    for i in 0...100000

    {

    }

    var end = NSDate()

    var timeTaken = end.timeIntervalSinceDate(start) * 1000

timeTaken составляет 74 миллисекунды в Swift, что является большой разницей по сравнению с Objective-C.

Я делаю что-то не так в этом измерении?

Ответы

Ответ 1

Я не думаю, что это очень справедливое сравнение. Вы только просите Objective-C выполнить цикл, но вы попросите Swift создать массивный диапазон (в частности Range<Int>), а затем повторите его. На моем компьютере требуется примерно 0,53 секунды для перехода по диапазону до миллиона, но всего около 0,012 секунды для выполнения цикла for до миллиона, что сравнивается с 0,002 секундами, которое требуется программе в Objective-C.

Мои программы (оба проекта устанавливаются как инструменты командной строки)

import Foundation

let start = CFAbsoluteTimeGetCurrent()

//for i in 0...1000000 {
//
//}

for var i = 0; i <= 1000000; ++i {

}

let timeTaken = CFAbsoluteTimeGetCurrent() - start

println(timeTaken)

И Objective-C

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        double start = CFAbsoluteTimeGetCurrent();

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

        }

        double timeTaken = CFAbsoluteTimeGetCurrent() - start;

        NSLog(@"%f",timeTaken);

    }
    return 0;
}

Удаление пула авторешетки даже сбрасывает еще одну тысячную доли секунды. Но, в целом, разница не так велика, как кажется.

Ответ 2

То, что вы делаете, - это чистая чепуха. Не имеет значения, какова производительность этого цикла, потому что это не происходит в реальном коде. Существенное различие заключается в том, что в Swift цикл будет выполнять проверки переполнения на каждом шаге, которые являются обязательным побочным эффектом из-за определения языка. В Objective-C это не так.

По крайней мере, вам нужно сделать код, который действительно имеет смысл.

Я провел некоторые реальные тесты, и результаты были следующими: 1. Скорость Swift и простая C для операций низкого уровня сопоставимы. 2. Когда при переполнении произойдет, Swift убьет программу, чтобы вы могли заметить переполнение, а C и Objective-C будут молча давать вам бессмысленные результаты. Попробуйте следующее:

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

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

Swift выйдет из строя. (Любой, кто считает, что плохое не имеет понятия о программировании). То же самое в Objective-C приведет к бессмысленному результату. Замените петлю на

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

и оба работают со сравнимой скоростью.

Ответ 3

По умолчанию уровень оптимизации компилятора установлен в None [-Onone] в режиме отладки...

Изменение этого параметра на Fastest [-O] (например, release) дает следующие результаты:

Enter image description here

Ответ 4

Я провел несколько тестов с функцией сортировки, которая использовала собственный массив Swift и строку Swift по сравнению с переменным массивом Objective C и NSString.

Функция упорядочивала 1000 строк, и она выполняла сравнение строк milion и перетасовывала массив.

Результаты были следующими:

  • Цель C (используя примитивные целые числа и логические значения): 0,32 секунды

  • Цель C (с использованием NSNumber для целых чисел и логических элементов): 0.45 секунд

  • Swift в режиме отладки: 13 секунд:)

  • Swift с уровнем оптимизации (самый быстрый [-O]): 1,32 секунды

  • Swift с уровнем оптимизации (Fastest, Unchecked [-Ofast]): 0.67 секунд

Кажется, что в быстром режиме Swift довольно близок к Objective C, но он все еще не быстрее, чем Apple (ed).

Это код сортировки, который я использовал:

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)

Цель C с примитивными булевыми и целыми числами

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];

Цель C с NSNumber для логических и целых чисел

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];

Ответ 5

Попробуйте выполнить компиляцию с включенными оптимизациями. Если это не изменит ситуацию, сообщите об ошибке с Apple. Swift все еще находится в состоянии бета-тестирования, поэтому могут быть грубые пятна.

Ответ 6

Я не думаю, что с сегодняшнего дня вы можете запускать эти тесты и с какой-либо определенностью определить, будет ли Swift 1.0 быстрее или медленнее, чем Objective-C. Весь язык Swift все еще находится в стадии разработки, синтаксис и способ реализации аспектов языка. Это видно из изменений в языке между Xcode 6 Betas 2 и 3, и если вы посмотрите на Apple Dev Forums, вы можете увидеть парня Apple, который работает на этом языке, четко заявив, что материал не является полным или оптимизированным, и что это будет не до версии Swift 1.0, которая должна произойти наряду с публичным выпуском Xcode 6.

Итак, я не говорю, что сейчас нет смысла делать эти тесты, но до тех пор, пока Swift 1.0 не будет завершен, мы не можем сказать ничего убедительного в отношении окончательной производительности.

Ответ 7

Посмотрите https://softwareengineering.stackexchange.com/info/242816/how-can-swift-be-so-much-faster-than-objective-c-in-these-comparisons и http://www.splasmata.com/?p=2798 учебник, возможно быть может, вы получите ответ. Но главное, что язык Swift все еще находится в стадии бета-тестирования. А также яблоко делает/не может уверенно объявить, что Swift быстрее, чем objective-c во всех случаях. Apple сообщила нам, что средняя производительность. Мое мнение состоит в том, что если в некоторых случаях obj-c быстрее, чем быстрее, это не означает, что все более быстрые показатели производительности медленнее. Мы просто уделяем больше времени Apple для этого.