Swift vs Objective-C Сравнение скорости последовательности Фибоначчи

У меня проблема. Я хочу знать, какой из них действительно быстрее (Swift или Objective-C), потому что я хотел бы выбрать более быстрый/лучший, когда приступаю к разработке приложения. Согласно многим источникам (например, Apple WWDC, или http://www.jessesquires.com/apples-to-apples-part-two/), Swift должен быть быстрее.

Я просто написал простую рекурсивную программу последовательности фибоначчи как для Swift, так и для Objective-C.

Однако, когда я запускаю fib (35) на симуляторе, я получаю неожиданные результаты:

Objective-C Результат:

: fib:: 9227465: duration: 0.122813 секунд

Быстрый результат

: fib:: 9227465: duration: 0.606831073760986 секунд

Теперь я даже запускал версию Swift на всех уровнях оптимизации Swift Compiler (для Debug), который является None, Fastest, Fastest-Unchecked. Я также играю с уровнем оптимизации генерации кода до None, Fast.... Fastest Aggressive Optimization. Однако все результаты Swift - это что-то близкое к 0,6 миллисекундам

Теперь последнее, о чем я могу думать, может быть, я сравниваю Apple с Orange? Вы, ребята, видите что-то, что мне не хватает здесь? Есть ли что-нибудь еще, что мне нужно включить (кроме уровней оптимизации для Swfit Compiler и Apple LLVM Code Generation), чтобы заставить программы Swift работать быстрее?

Любые предложения или комментарии приветствуются и оцениваются! ^^!

Objective-C Версия

-(int)fib:(int)num{
    if (num == 0) {
        return 0;
    }
    if (num == 1) {
        return 1;
    }    
    return [self fib:num - 1] + [self fib:num - 2];
}

Быстрая версия

func fib(num: Int) -> Int{
    if(num == 0){
        return 0;
    }
    if(num == 1){
        return 1;
    }
    return fib(num - 1) + fib(num - 2);
}

Objective-C Измерение времени

  NSTimeInterval start = [[NSDate date] timeIntervalSince1970];
  int result = [self fib:35];
  NSTimeInterval end = [[NSDate date] timeIntervalSince1970];

  NSTimeInterval duration = end - start;
  NSLog(@":::fib::::%d:::duration:::%f",result,duration);

Быстрое измерение времени

var start = NSDate().timeIntervalSince1970;
let result = fib(35);
var end = NSDate().timeIntervalSince1970;

var duration = end - start;
println(":::fib::::\(result) :::duration:::\(duration)");

Ответ 1

Много вещей, которые следует учитывать при выборе того, какой из двух языков программирования быстрее. Я сделал пару тестов (https://github.com/vsco/swift-benchmarks) между Swift и Objective-C, и я обнаружил, что в некоторых случаях Swift был быстрее и в других случаях Objective-C был быстрее. Например, использование структурных объектов в Swift позволит получить огромную прибыль, если вам нужно работать с большим количеством данных. Напротив, использование неструктурных объектов сделало Swift значительно медленнее, чем его копии Objective-C.

Также, как вы используете определенные функции в Swift, очень важно, насколько хорошо он будет работать. Возьмите эту функцию, например:

class func shuffleGenericObjects<T>(inout array:[T]) {
    for (var i = 0; i < array.count; i++) {
        let currentObject: T = array[i]
        let randomIndex = Int(arc4random()) % array.count
        let randomObject: T = array[randomIndex]

        array[i] = randomObject;
        array[randomIndex] = currentObject
    }
}

Уверен, что он отлично подходит для минимизации повторяющегося кода, но когда я выполнил этот метод более 1 миллиона объектов Int, потребовалось примерно 32 секунды для завершения. В отличие от нестандартной реализации, которая заняла только 0.181 секунды.

Я также рекомендую не использовать функции NSDate для бенчмаркинга в Swift. Я наткнулся на несколько ошибок, из-за которых NSDate возвращал неправильные времена. Гораздо лучше поставить свои тесты в XCTestCase и использовать функцию measureBlock().

Ответ 2

Выбор Фибоначчи в качестве эталона немного ироничен, потому что в WWDC 2014 видео Advanced Swift они используют последовательность Фибоначчи как пример того, как вы можете написать generic memoize, которая на несколько порядков выше.

func memoize<T: Hashable, U>(body: ((T)->U, T) -> U) -> (T)->U {
    var memo = [T: U]()
    var result: ((T)->U)!
    result = { x in
        if let q = memo[x] { return q }
        let r = body(result, x)
        memo[x] = r
        return r
    }
    return result
}

Где вы можете:

let fib = memoize { fib, x in x < 2 ? x : fib(x - 1) + fib(x - 2) }

let result = fib(35)

Теперь, очевидно, несправедливо сравнивать это с неоптимизированной рекурсивной функцией Фибоначчи Objective-C, потому что это оставит ее в пыли. Я даже не уверен, что согласен со всеми выводами WWDC относительно достоинств реализации memoize Swift generic. Но улучшение производительности поражает.


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

В нижней строке, я лично смутился бы сделать любые простые выводы из Свифта быстрее, чем Objective-C, или наоборот. Я подозреваю, что есть некоторые алгоритмы/приложения, где Swift быстрее, а другие - там, где нет.

Кроме того, вы говорите, что в отношении выбора языка программирования вы "хотели бы выбрать более быстрый/лучший". Я бы оспорил, что "более быстрый" язык всегда "лучше" (в противном случае мы все еще будем писать код сборки). Часто выбор языка - это меньшая вычислительная эффективность кода, а также более высокая эффективность разработчика. Мы все должны выбрать язык, на котором мы можем написать наиболее надежный код, сделать это наиболее экономичным способом, написание кода, который наиболее легко поддерживается в будущем, и обеспечить превосходный пользовательский интерфейс.

Является ли этот язык Swift или Objective-C вопросом мнения и не для этого форума.

Ответ 3

Ваш код выглядит хорошо, но вы не можете обобщать скорость языка программирования в такой ситуации. В Apple Keynote в прошлом году они сказали, что "сложная сортировка объектов" была быстрее в Swift. Вероятно, в Objective-C есть несколько вещей быстрее, но, как правило, Swift должен быть более быстрым.