2015-01-27 2 views
12

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

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

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

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

::: выдумка :::: 9227465 ::: Продолжительность ::: 0.122813 секунд

Swift Результат

::: Фибо :::: 9227465 ::: продолжительность ::: 0.606831073760986 секунд

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

Теперь последнее, о чем я могу думать, может быть, я сравниваю Apple с Orange? Вы, ребята, видите, что мне не хватает здесь? Есть ли что-нибудь еще, что мне нужно включить (кроме уровней оптимизации для компилятора Swfit & 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); 

Swift Время измерения

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

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

как вы измеряете время? –

+0

@BryanChen Я только что обновил вопрос с помощью кодов измерения времени, я использую NSDate как для Swift, так и для Objective-C – xiaowoo

+0

NSDate не подходит для теста. и> 1 мс слишком мал, вам лучше повторять тест много раз, чтобы они оба выполняли хотя бы секунду для запуска.Кроме того, ваш код будет показывать только разницу между динамической отправкой и статической отправкой. –

ответ

1

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

+0

OP хочет видеть, что Swift на самом деле быстрее. это не отвечает на вопрос. –

+2

Что значит? В настоящее время ОП тестирует конкретный метод и пытается обобщить производительность всего языка. Есть так много других факторов, которые должны входить в это решение, отличное от того, какой язык способен быстрее вычислять последовательность Фибоначчи. Это похоже на попытку выбрать лучшего футболиста и просто посмотреть на их 40 раз. – AdamPro13

5

Выбор Фибоначчи в качестве ориентира немного иронично, потому что в WWDC 2014 видео Advanced Swift они используют последовательность Фибоначчи в качестве примера того, как вы можете написать общий 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 относительно достоинств реализации Swift generic memoize. Но улучшение производительности поражает.


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

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

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

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

+0

+1 Esp для двух последних абзацев. В настоящее время производительность не является большой проблемой разработки приложений. Если это так, это скорее проблема структуры, чем одно вычисление. –

+0

Вы пишете о не оптимизированных функциях, возможно, вы знаете какие-то хорошие источники, где вы можете узнать, как улучшить кодирование в этом направлении? Так что больше профайлов, нет простых начинающих уроков –

+0

В этот момент я думаю, что вы перешли из сферы простых веб-уроков и в мир университетских классов и учебников, которые вникают в мир теории и дизайна алгоритмов. Я просто искал «алгоритм» в книгах Амазонки, и на вершине есть куча многообещающих текстов. Я был бы склонен получить тот, который уравновешивает теорию (например, «большое о» обозначение, NP полные проблемы и т. Д.) С более практическими соображениями (например, анализ и сравнение различных алгоритмов сортировки, методы оптимизации, такие как хеши и кеши и т. Д.). – Rob

7

Много вещей, которые следует учитывать при выборе того, какой из двух языков программирования выполняется быстрее. Я сделал пару тестов (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

Интересные вещи – Andrea

+1

Отличный пример. Кстати, эта перетасовка [не распространяется] (https://en.wikipedia.org/wiki/Fisher-Yates_shuffle#Potential_sources_of_bias). Лучше, используйте 'let randomIndex = Int (arc4random_uniform (UInt32 (count-i))) + i'. – Rob

+1

Спасибо за подсказку! По сути, моя универсальная реализация принимает '[Int]' вместо '[T]'. Вы можете проверить мои различные реализации с помощью тестов [здесь] (https://github.com/vsco/swift-benchmarks). Реализация '[Int]' также быстрее, чем версия 'NSMutableArray'. Повышение производительности происходит каждый раз, когда вы можете использовать объекты структуры, которые, я уверен, вы знаете, что Int и String. Недостатком использования структурных объектов является то, что вы не можете привязать их к Objective-C. Насколько я знаю, Int и String являются единственными структурами, которые могут переходить в Objective-C. – fyell

Смежные вопросы