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 должен быть более быстрым.