Как мы можем измерить время, затраченное на выполнение функции в Swift? Я пытаюсь отобразить прошедшее время следующим образом: «Прошедшее время составляет 0,05 секунды». Видел, что в Java мы можем использовать System.nanoTime (), есть ли в Swift какие-либо эквивалентные методы для этого?
Взгляните на пример программы:
func isPrime(var number:Int) ->Bool {
var i = 0;
for i=2; i<number; i++ {
if(number % i == 0 && i != 0) {
return false;
}
}
return true;
}
var number = 5915587277;
if(isPrime(number)) {
println("Prime number");
} else {
println("NOT a prime number");
}
swift
time
nsdate
elapsedtime
Vaquita
источник
источник
sqrt(number)
вместо этого цикл можно остановитьnumber
, и вы можете сэкономить немного больше времени, но есть гораздо больше идей по оптимизации поиска простых чисел.NSDate
предметы и вы можете измерить разницу между ними.Ответы:
Вот функция Swift, которую я написал для измерения проблем Project Euler в Swift.
Начиная с Swift 3, теперь есть версия Grand Central Dispatch, которая является «быстрой». Так что правильным ответом, вероятно, будет использование DispatchTime API .
Моя функция будет выглядеть примерно так:
Старый ответ
Для Swift 1 и 2 моя функция использует NSDate:
Обратите внимание, что использование NSdate для функций синхронизации не рекомендуется: « Системное время может уменьшиться из-за синхронизации с внешними привязками времени или из-за явной смены часов пользователем ».
источник
Date
рядом, и, конечно же, он сообщает 41,87 секунды. Я не знаю, чтоuptimeNanoseconds
происходит, но не сообщает правильную продолжительность.Это удобный класс таймера, основанный на
CoreFoundation
sCFAbsoluteTime
:Вы можете использовать это так:
источник
mach_absolute_time
который не страдает этой проблемой, поэтому мне интересно, почему он не так широко известен. Может быть, просто потому, что это плохо документировано.Используйте
clock
,ProcessInfo.systemUptime
илиDispatchTime
для простого времени запуска.Насколько мне известно, существует как минимум десять способов измерить прошедшее время:
Монотонные часы на основе:
ProcessInfo.systemUptime
,mach_absolute_time
с ,mach_timebase_info
как указано в этом ответе .clock()
в стандарте POSIX .times()
в стандарте POSIX . (Слишком сложно, поскольку нам нужно учитывать время пользователя и время системы, а также задействованы дочерние процессы.)DispatchTime
(оболочка вокруг API времени Маха), как упоминалось JeremyP в принятом ответе.CACurrentMediaTime()
,Настенные часы на основе:
(никогда не используйте их для показателей: см. ниже, почему)
NSDate
/Date
как упоминалось другими.CFAbsoluteTime
как упоминалось другими.DispatchWallTime
,gettimeofday()
в стандарте POSIX .Варианты 1, 2 и 3 подробно описаны ниже.
Вариант 1. API информации о процессе в Foundation
где
diff:NSTimeInterval
- прошедшее время в секундах.Вариант 2: Mach C API
где
diff:Double
- прошедшее время в наносекундах.Вариант 3: API часов POSIX
где
diff:Double
- прошедшее время в секундах.Почему настенные часы не показывают истекшее время?
В документации
CFAbsoluteTimeGetCurrent
:Причина аналогична
currentTimeMillis
vsnanoTime
в Java :Здесь
CFAbsoluteTime
указано время настенных часов вместо времени запуска.NSDate
время настенных часов.источник
clock()
функцию.ProcessInfo.processInfo.systemUptime
,mach_absolute_time()
,DispatchTime.now()
иCACurrentMediaTime()
. Но решение сclock()
некорректным преобразованием в секунды. Поэтому я бы посоветовал обновить ваше первое предложение следующим образом: « Используйте ProcessInfo.systemUptime или DispatchTime для точного времени запуска ».Swift 4 самый короткий ответ:
Он напечатает вам что-то вроде прошедшего времени 1.02107906341553 секунды (время, конечно, будет варьироваться в зависимости от задачи, я просто показываю это вам, ребята, чтобы увидеть уровень десятичной точности для этого измерения).
Надеюсь, что с этого момента это поможет кому-то в Swift 4!
Обновить
Если вы хотите иметь общий способ тестирования частей кода, я бы предложил следующий фрагмент:
источник
источник
Просто скопируйте и вставьте эту функцию. Написано быстрым 5. Копируем JeremyP сюда.
Используйте это как
источник
Вы можете создать
time
функцию для измерения ваших звонков. Меня вдохновил ответ Клааса .Эта функция позволит вам вызвать ее так,
time (isPrime(7))
что вернет кортеж, содержащий результат и строковое описание прошедшего времени.Если вы хотите только прошедшее время, вы можете сделать это
time (isPrime(7)).duration
источник
Простая вспомогательная функция для измерения времени выполнения с закрытием.
Использование:
Результат:
#Init - execution took 1.00104497105349 seconds
источник
вы можете измерить наносекунды, например, так:
источник
NSCalendar
это дорогостоящая процедура, но вы можете сделать это до того, как начнете запускать свою процедуру, поэтому она не будет добавлена в вашу длинную среду выполнения ... имейте в виду, что вызов созданияNSDate
экземпляра и вызова–components(_:, fromDate:)
метода все еще требует времени, поэтому, вероятно, вы никогда не получите0.0
наносекунды.6.9
микросекунд на моем устройстве.Я использую это:
Я не знаю, более или менее точно, чем было опубликовано ранее. Но секунды имеют много десятичных знаков и, кажется, улавливают небольшие изменения кода в алгоритмах, таких как QuickSort, с использованием swap () по сравнению с реализацией urself подкачки и т. Д.
Не забудьте активизировать оптимизацию сборки при тестировании производительности:
источник
Вот моя попытка найти самый простой ответ:
Ноты
startTime
иendTime
относятся к типуTimeInterval
, который является простоtypealias
forDouble
, поэтому его легко преобразовать вInt
или что-то еще. Время измеряется в секундах с точностью до миллисекунды.DateInterval
, который включает фактическое время начала и окончания.источник
Я позаимствовал идею Клааса, чтобы создать легкую структуру для измерения времени бега и интервалов:
Использование кода:
Функцию остановки вызывать не нужно, так как функция печати покажет истекшее время. Его можно вызывать повторно, чтобы отсчитать время. Но для остановки таймера в определенный момент использования кода
timer.stop()
его также можно использовать для возврата времени в секундах:let seconds = timer.stop()
после остановки таймера интервальный таймер не будет, поэтому онprint("Running: \(timer) ")
будет давать правильное время даже после нескольких строк кода.Ниже приведен код для RunningTimer. Протестировано для Swift 2.1:
источник
Оберните его в блок завершения для удобства использования.
источник
Это фрагмент, который я придумал, и, похоже, он работает для меня на моем Macbook с Swift 4.
Никогда не тестировал на других системах, но подумал, что все равно стоит поделиться.
Вот пример того, как его использовать:
Другой способ - сделать это более явно:
источник
Вот как я это написал.
Чтобы измерить алгоритм, используйте его вот так.
источник
Статический класс Swift3 для синхронизации основных функций. Он будет отслеживать каждый таймер по имени. Назовите это так в точке, с которой хотите начать измерения:
Вызовите это, чтобы зафиксировать и распечатать прошедшее время:
Это результат: *** PhotoCapture elapsed ms: 1402.415125 Есть параметр «useNanos», если вы хотите использовать нано. Пожалуйста, не стесняйтесь вносить изменения по мере необходимости.
}
источник
mach_timebase_info
уже реализована лучше , чем вы делали в исходном коде изProcessInfo.processInfo.systemUptime
. Так что просто делайwatches[name] = ProcessInfo.processInfo.systemUptime
. А* TimeInterval(NSEC_PER_MSEC)
если хотите нан.На основе ответа Франклина Ю и комментариев Кёра
подробности
Решение 1
измерения (_ :)
Решение 2
Использование раствора 2
источник
Date
для измерения ничего крайне не рекомендуется (ноsystemUptime
илиclock()
ОК). Что касается тестов, то мы ихmeasure(_:)
уже сделали .