Jak możemy zmierzyć czas, który upłynął do uruchomienia funkcji w języku Swift? Próbuję wyświetlić upływający czas w następujący sposób: „Upłynęło 0,05 sekundy”. Widziałem, że w Javie możemy użyć System.nanoTime (), czy w języku Swift są dostępne równoważne metody, aby to osiągnąć?
Proszę spojrzeć na przykładowy program:
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
źródło
źródło
sqrt(number)
zamiastnumber
i możesz zaoszczędzić trochę więcej czasu - ale jest o wiele więcej pomysłów optymalizujących wyszukiwanie liczb pierwszych.NSDate
obiektów i możesz zmierzyć różnicę między nimi.Odpowiedzi:
Oto funkcja języka Swift, którą napisałem, aby zmierzyć problemy projektu Euler w języku Swift
Od wersji Swift 3 dostępna jest teraz wersja Grand Central Dispatch, która jest „szybka”. Zatem prawidłowa odpowiedź to prawdopodobnie użycie interfejsu API DispatchTime .
Moja funkcja wyglądałaby tak:
Stara odpowiedź
W przypadku Swift 1 i 2 moja funkcja używa NSDate:
Należy zwrócić uwagę, że używanie NSdate do funkcji czasowych jest odradzane: „ Czas systemowy może ulec skróceniu z powodu synchronizacji z zewnętrznymi odniesieniami czasu lub z powodu jawnej zmiany zegara przez użytkownika. ”.
źródło
Date
obok i na pewno zgłasza 41,87 sekundy. Nie wiem, couptimeNanoseconds
robi, ale nie zgłasza prawidłowego czasu trwania.To jest przydatna klasa timera oparta na
CoreFoundation
sCFAbsoluteTime
:Możesz go używać w ten sposób:
źródło
mach_absolute_time
który nie cierpi na ten problem, więc zastanawiam się, dlaczego nie jest on powszechnie znany. Może tylko dlatego, że nie jest dobrze udokumentowany.Użyj
clock
,ProcessInfo.systemUptime
lubDispatchTime
dla prostego czasu uruchamiania.O ile wiem, istnieje co najmniej dziesięć sposobów mierzenia upływającego czasu:
Na podstawie zegara monotonicznego:
ProcessInfo.systemUptime
.mach_absolute_time
zmach_timebase_info
jak wspomniano w tej odpowiedzi .clock()
w standardzie POSIX .times()
w standardzie POSIX . (Zbyt skomplikowane, ponieważ musimy rozważyć czas użytkownika w porównaniu z czasem systemowym, a procesy potomne są zaangażowane).DispatchTime
(wrapper wokół Mach time API), jak wspomniał JeremyP w zaakceptowanej odpowiedzi.CACurrentMediaTime()
.Na podstawie zegara ściennego:
(nigdy nie używaj ich do pomiarów: zobacz poniżej, dlaczego)
NSDate
/Date
jak wspominali inni.CFAbsoluteTime
jak wspominali inni.DispatchWallTime
.gettimeofday()
w standardzie POSIX .Opcje 1, 2 i 3 omówiono poniżej.
Opcja 1: Process Info API w Foundation
gdzie
diff:NSTimeInterval
jest upływający czas w sekundach.Opcja 2: Mach C API
gdzie
diff:Double
jest upływający czas o nano-sekundy.Opcja 3: API zegara POSIX
gdzie
diff:Double
jest upływający czas w sekundach.Dlaczego nie czas na zegarze ściennym dla upływającego czasu?
W dokumentacji
CFAbsoluteTimeGetCurrent
:Powód jest podobny do
currentTimeMillis
vsnanoTime
w Javie :Tutaj
CFAbsoluteTime
podaje czas zegara ściennego zamiast czasu uruchomienia.NSDate
to również zegar ścienny.źródło
clock()
funkcje.ProcessInfo.processInfo.systemUptime
,mach_absolute_time()
,DispatchTime.now()
iCACurrentMediaTime()
. Ale rozwiązanie zclock()
nie było poprawnie konwertowane na sekundy. Dlatego radziłbym zaktualizować swoje pierwsze zdanie do: „ Użyj ProcessInfo.systemUptime lub DispatchTime, aby uzyskać dokładny czas uruchamiania. ”Szybka 4 najkrótsza odpowiedź:
Wydrukuje ci około 1.02107906341553 sekund, które upłynęły (czas oczywiście będzie się różnił w zależności od zadania, pokazuję to tylko, aby zobaczyć poziom dokładności dziesiętnej dla tego pomiaru).
Mam nadzieję, że od teraz pomoże to komuś w Swift 4!
Aktualizacja
Jeśli chcesz mieć ogólny sposób testowania fragmentów kodu, proponuję następny fragment:
źródło
źródło
Po prostu skopiuj i wklej tę funkcję. Napisane w szybkim 5. Kopiowanie JeremyP tutaj.
Użyj tego jak
źródło
Możesz stworzyć
time
funkcję do mierzenia połączeń. Inspiruje mnie odpowiedź Klaasa .Ta funkcja pozwoli ci wywołać to w ten sposób,
time (isPrime(7))
co zwróci krotkę zawierającą wynik i opis ciągu, który upłynął.Jeśli chcesz tylko upływającego czasu, możesz to zrobić
time (isPrime(7)).duration
źródło
Prosta funkcja pomocnicza do pomiaru czasu wykonania z zamknięciem.
Stosowanie:
Wynik:
#Init - execution took 1.00104497105349 seconds
źródło
możesz mierzyć nanosekundy w ten sposób:
źródło
NSCalendar
jest kosztowną procedurą, ale możesz to zrobić przed rozpoczęciem wykonywania procedury, więc nie zostanie ona dodana do czasu wykonywania Twojej długiej procedury ... pamiętaj, że wywołanie tworzeniaNSDate
instancji i wywoływania–components(_:, fromDate:)
metody nadal wymaga czasu, więc prawdopodobnie nigdy nie dostaniesz0.0
nanosekund.6.9
mikrosekund na moim urządzeniu.Używam tego:
Nie wiem, czy jest bardziej czy mniej dokładny niż poprzednio opublikowany. Ale sekundy mają dużo miejsc po przecinku i wydają się wychwytywać niewielkie zmiany w kodzie w algorytmach, takich jak QuickSort przy użyciu funkcji swap (), w porównaniu z implementacją samego swapu itp.
Pamiętaj, aby zwiększyć optymalizację kompilacji podczas testowania wydajności:
źródło
Oto moja próba najprostszej odpowiedzi:
Uwagi
startTime
iendTime
są typuTimeInterval
, który jest po prostutypealias
forDouble
, więc łatwo jest przekształcić go wInt
lub cokolwiek. Czas jest mierzony w sekundach z dokładnością do milisekund.DateInterval
, który zawiera rzeczywisty czas rozpoczęcia i zakończenia.źródło
Zapożyczyłem pomysł od Klaasa, aby stworzyć lekką strukturę do pomiaru czasu biegu i interwałów:
Wykorzystanie kodu:
Funkcja stop nie musi być wywoływana, ponieważ funkcja drukowania poda upływ czasu. Może być wywoływane wielokrotnie, aby uzyskać upływ czasu. Ale aby zatrzymać licznik czasu w określonym punkcie kodu
timer.stop()
, można go również użyć do zwrócenia czasu w sekundach:let seconds = timer.stop()
Po zatrzymaniu licznika czasu interwał nie będzie, więcprint("Running: \(timer) ")
poda prawidłowy czas nawet po kilku wierszach kodu.Poniżej znajduje się kod RunningTimer. Jest testowany dla Swift 2.1:
źródło
Zapakuj go w blok uzupełniający, aby był łatwy w użyciu.
źródło
To jest fragment, który wymyśliłem i wydaje się, że działa dla mnie na moim Macbooku ze Swift 4.
Nigdy nie testowałem na innych systemach, ale pomyślałem, że i tak warto się nim podzielić.
Oto przykład, jak go używać:
Innym sposobem jest zrobienie tego bardziej szczegółowo:
źródło
Tak to napisałem.
Aby zmierzyć algorytm, użyj go w ten sposób.
źródło
Statyczna klasa Swift3 dla podstawowego taktowania funkcji. Będzie śledzić każdy timer według nazwy. Nazwij to w ten sposób w miejscu, w którym chcesz rozpocząć pomiar:
Wywołaj to, aby uchwycić i wydrukować czas, który upłynął:
Oto wynik: *** PhotoCapture upłynął ms: 1402.415125 Istnieje parametr „useNanos”, jeśli chcesz używać nanos. W razie potrzeby możesz je zmienić.
}
źródło
mach_timebase_info
już wdrożone lepiej niż ty w kodzie źródłowym zProcessInfo.processInfo.systemUptime
. Więc po prostu zróbwatches[name] = ProcessInfo.processInfo.systemUptime
. A* TimeInterval(NSEC_PER_MSEC)
jeśli chcesz nanos.Na podstawie odpowiedzi Franklina Yu i Cœura komentarzy
Detale
Rozwiązanie 1
pomiar(_:)
Rozwiązanie 2
Zastosowanie rozwiązania 2
źródło
Date
do mierzenia czegokolwiek jest bardzo odradzane (alesystemUptime
lubclock()
jest OK). Jeśli chodzi o testy, tomeasure(_:)
już mamy .