Производительность сортировки массивов в Swift Beta: почему так медленно и как ускорить?
Причина медленной работы
Проблема действительно характерна для ранних бета-версий Swift (Xcode 6). Основная причина — неоптимизированная работа с замыканиями и отсутствие инлайнинга при уровне оптимизации по умолчанию. В Swift Beta компилятор часто не мог эффективно оптимизировать замыкания, переданные в функции высшего порядка, что приводило к многократному созданию и вызову оберток.
Решение: используйте оператор < напрямую
Самый простой способ ускорить сортировку — передать оператор сравнения напрямую, а не замыкание:
let sorted = numbers.sorted(<) // Используем оператор < как функцию
Это работает, потому что операторы в Swift — это обычные функции, и компилятор может их инлайнить. Время сортировки сокращается до 0.05-0.1 секунды — в 10 раз быстрее!
Дополнительные оптимизации
- Включите полную оптимизацию: В настройках проекта (Build Settings) установите
Optimization Levelв-Owholemoduleдля Swift. Это включает межмодульную оптимизацию. - Используйте
sort()вместоsorted()если нужно отсортировать массив на месте:numbers.sort(<)Это избегает создания копии массива.
- Для пользовательских типов: Реализуйте протокол
Comparable:struct Person: Comparable { let name: String let age: Int static func < (lhs: Person, rhs: Person) -> Bool { return lhs.age < rhs.age } }Тогда можно сортировать просто:
people.sort()
Почему это работает?
В Swift Beta компилятор не всегда мог оптимизировать замыкания, особенно если они захватывали внешние переменные. Передача оператора < напрямую позволяет компилятору:
- Инлайнить вызов сравнения
- Избежать создания обертки для замыкания
- Лучше оптимизировать циклы сортировки
В более поздних версиях Swift (начиная с Xcode 7) эта проблема была исправлена, и оба варианта работают одинаково быстро. Но в Xcode 6 Beta это было серьезной проблемой.
<<Альтернативный подход: ручная сортировка для критичных участков
Если вы столкнулись с медленной работой sorted() в бета-версии и не хотите менять код, можно реализовать свою быструю сортировку. Например, используйте sort() из стандартной библиотеки C через qsort:
import Darwin
var numbers = [Int]()
// заполнение массива...
numbers.withUnsafeMutableBufferPointer { buffer in
qsort(buffer.baseAddress, buffer.count, MemoryLayout<Int>.size) { a, b in
let aValue = a.load(as: Int.self)
let bValue = b.load(as: Int.self)
if aValue < bValue { return -1 }
if aValue > bValue { return 1 }
return 0
}
}
Этот подход использует нативную C-функцию, которая работает очень быстро. Однако он менее безопасен и не рекомендуется для production-кода. Лучше дождаться стабильной версии Swift или использовать sorted(by: <) как в первом ответе.
Также имейте в виду, что в бета-версиях часто встречаются проблемы с производительностью, которые исправляются к релизу. Поэтому не стоит паниковать — просто используйте обходные пути до выхода финальной версии.
Ответов пока нет.
Войдите чтобы оставить ответ
Блоги