उपाय स्विफ्ट में बीता हुआ समय


132

स्विफ्ट में फ़ंक्शन चलाने के लिए हम समय को कैसे माप सकते हैं? मैं इस तरह बीता हुआ समय प्रदर्शित करने की कोशिश कर रहा हूं: "बीता हुआ समय .05 सेकंड है"। देखा कि जावा में , हम System.nanoTime () का उपयोग कर सकते हैं, क्या इसे पूरा करने के लिए स्विफ्ट में कोई समकक्ष विधियां उपलब्ध हैं?

कृपया नमूना कार्यक्रम पर एक नज़र:

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");
}

1
यह आपके समय-मापने के मुद्दे से संबंधित नहीं है, लेकिन लूप को sqrt(number)इसके स्थान पर रोका जा सकता है number, और आप थोड़ा और समय बचा सकते हैं - लेकिन बहुत अधिक विचार हैं, जो primes की मांग कर रहे हैं।
Holex

@होलेक्स कृपया उपयोग किए गए एल्गोरिदम को अनदेखा करें। मैं यह पता लगाने की कोशिश कर रहा हूं कि हम बीता हुआ समय कैसे माप सकते हैं?
वाक्विता

1
आप NSDateवस्तुओं का उपयोग कर सकते हैं और आप उनके बीच के अंतर को माप सकते हैं।
होलेक्स

4
यदि आप XCode का उपयोग कर रहे हैं, तो मैं आपको नए प्रदर्शन परीक्षण सुविधा का उपयोग करने की सलाह देता हूं। यह आपके लिए सभी भारी भार उठाता है और यहां तक ​​कि इसे कई बार चलाता है और आपको अपने मानक विचलन के साथ औसत समय देता है ...
रोशन

1
@ डंबलड आप सीधे यूनिट परीक्षणों में पूरे ब्लॉकों के प्रदर्शन को माप सकते हैं। उदाहरण के लिए, इसे देखें । यदि आप रन डाउन को आगे तोड़ना चाहते हैं (जैसे, लाइन बाय लाइन कोड), तो टाइम प्रोफाइलर देखें जो इंस्ट्रूमेंट्स का हिस्सा है। यह बहुत अधिक शक्तिशाली और व्यापक है।
रोशन 13

जवाबों:


229

यहां एक स्विफ्ट फ़ंक्शन है जो मैंने स्विफ्ट में प्रोजेक्ट यूलर समस्याओं को मापने के लिए लिखा था

स्विफ्ट 3 के रूप में, अब ग्रैंड सेंट्रल डिस्पैच का एक संस्करण है जो "स्विफ्टिफ़ाइड" है। इसलिए सही उत्तर संभवतः डिस्पैचटाइम एपीआई का उपयोग करना है

मेरा कार्य कुछ इस तरह दिखेगा:

// Swift 3
func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer
{
    print("Evaluating problem \(problemNumber)")

    let start = DispatchTime.now() // <<<<<<<<<< Start time
    let myGuess = problemBlock()
    let end = DispatchTime.now()   // <<<<<<<<<<   end time

    let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess)

    let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds // <<<<< Difference in nano seconds (UInt64)
    let timeInterval = Double(nanoTime) / 1_000_000_000 // Technically could overflow for long running tests

    print("Time to evaluate problem \(problemNumber): \(timeInterval) seconds")
    return theAnswer
}

पुराना उत्तर

स्विफ्ट 1 और 2 के लिए, मेरा फ़ंक्शन NSDate का उपयोग करता है:

// Swift 1
func evaluateProblem(problemNumber: Int, problemBlock: () -> Int) -> Answer
{
    println("Evaluating problem \(problemNumber)")

    let start = NSDate() // <<<<<<<<<< Start time
    let myGuess = problemBlock()
    let end = NSDate()   // <<<<<<<<<<   end time

    let theAnswer = self.checkAnswer(answerNum: "\(problemNumber)", guess: myGuess)

    let timeInterval: Double = end.timeIntervalSinceDate(start) // <<<<< Difference in seconds (double)

    println("Time to evaluate problem \(problemNumber): \(timeInterval) seconds")
    return theAnswer
}

ध्यान दें कि समय कार्यों के लिए NSdate का उपयोग करना हतोत्साहित किया जाता है: " बाहरी समय संदर्भों के साथ सिंक्रनाइज़ेशन के कारण या घड़ी के स्पष्ट उपयोगकर्ता परिवर्तन के कारण सिस्टम समय घट सकता है। "


यह लगभग +/- 2microsec को अच्छा परिणाम देता प्रतीत होता है। हो सकता है कि यह प्लेटफॉर्म से भिन्न हो, लेकिन।
user1021430

6
स्विफ्ट 3 मेरे लिए काम नहीं करता है, यह 0.0114653027 लौटाता है जो मैं एक तथ्य के लिए जानता हूं जो सच नहीं है, तारीखों के साथ एक 4.77720803022385sec
Cristi Băluță

5
दुर्भाग्य से नहीं। अपटाइम किसी कारण से पूरी तरह से समाप्त हो गया है। मेरे पास एक परीक्षण है जो कहता है कि 1004959766 नैनोसेकंड (लगभग एक सेकंड) लिया गया, लेकिन निश्चित रूप से लगभग 40 सेकंड के लिए चल रहा था। मैंने Dateसाथ में प्रयोग किया, और निश्चित रूप से पर्याप्त है कि 41.87 सेकंड की रिपोर्ट करता है। मुझे नहीं पता कि क्या uptimeNanosecondsकर रहा है, लेकिन यह सही अवधि की रिपोर्ट नहीं कर रहा है।
jowie

2
बड़े संपादन के लिए क्षमा करें, आपके नए समाधान को प्राथमिकता देते हुए, लेकिन मैं आपके NSDate कोड को पूरी तरह से हटाने की सिफारिश करूंगा: NSDate का उपयोग करना पूरी तरह से अविश्वसनीय है: NSDate सिस्टम क्लॉक पर आधारित है, जो कई अलग-अलग कारणों से किसी भी समय बदल सकता है, जैसे नेटवर्क टाइम सिंक (NTP) के रूप में घड़ी को अपडेट करना (बहाव के लिए समायोजित करने के लिए अक्सर होता है), DST समायोजन, छलांग सेकंड, और घड़ी के उपयोगकर्ता मैनुअल समायोजन। इसके अतिरिक्त, आप स्विफ्ट 1: स्विफ्ट 3 नंगे न्यूनतम का उपयोग करते हुए ऐपस्टोर पर अब किसी भी ऐप को प्रकाशित नहीं कर सकते हैं। तो आपके NSDate कोड को "यह मत करो" कहने के अलावा रखने का कोई मतलब नहीं है।
कूर

1
@ NSDate संस्करण की आपकी आलोचना वैध है (DST परिवर्तनों को छोड़कर NSDate जो हमेशा GMT में होता है) को प्रभावित नहीं करेगा, और आदेश को उलटने के लिए आपका संपादन निश्चित रूप से एक सुधार है।
जेरेमीप

69

यह CoreFoundationएस पर आधारित एक आसान टाइमर क्लास है CFAbsoluteTime:

import CoreFoundation

class ParkBenchTimer {

    let startTime:CFAbsoluteTime
    var endTime:CFAbsoluteTime?

    init() {
        startTime = CFAbsoluteTimeGetCurrent()
    }

    func stop() -> CFAbsoluteTime {
        endTime = CFAbsoluteTimeGetCurrent()

        return duration!
    }

    var duration:CFAbsoluteTime? {
        if let endTime = endTime {
            return endTime - startTime
        } else {
            return nil
        }
    }
}

आप इसे इस तरह से उपयोग कर सकते हैं:

let timer = ParkBenchTimer()

// ... a long runnig task ...

println("The task took \(timer.stop()) seconds.")

4
" यह कार्य करने के लिए बार-बार कॉल होगा- परिणाम में वृद्धि की गारंटी नहीं देते। इसकी के अनुसार," प्रलेखन
फ्रैंकलिन यू

8
अधिक संदर्भ: "इस फ़ंक्शन के लिए बार-बार कॉल करना, मोनोटोनिक रूप से बढ़ते परिणामों की गारंटी नहीं देता है। बाहरी समय संदर्भों के साथ सिंक्रनाइज़ेशन या घड़ी के स्पष्ट उपयोगकर्ता परिवर्तन के कारण सिस्टम समय घट सकता है ।"
कालस

डेवलपर को "बाह्य समय संदर्भों के साथ सिंक्रनाइज़ेशन" और "घड़ी का एक स्पष्ट उपयोगकर्ता परिवर्तन" लेना चाहिए। क्या आपका मतलब है कि दो स्थिति के लिए ऐसा होना असंभव है?
फ्रैंकलिन यू

@FranklinYu नहीं, मैं सिर्फ यह बताना चाहता हूं कि ये दो संभावित कारण हैं। यदि आप हमेशा नीरसता से बढ़ते मूल्यों पर भरोसा करते हैं तो अन्य विकल्प हैं।
कालस

कभी-कभी मैं समय की एक छोटी अवधि को मापना चाहता हूं; यदि उस दौरान सिंक्रनाइज़ेशन होता है, तो मैं नकारात्मक समय के साथ समाप्त हो सकता हूं। वास्तव में mach_absolute_timeऐसा नहीं है जो इस समस्या से ग्रस्त नहीं है, इसलिए मैं सोच रहा हूं कि एक व्यापक रूप से ज्ञात क्यों नहीं है। शायद सिर्फ इसलिए कि यह अच्छी तरह से प्रलेखित नहीं है।
फ्रैंकलिन यू

54

उपयोग करें clock, ProcessInfo.systemUptimeया DispatchTimeसरल स्टार्ट-अप समय के लिए।


जहाँ तक मुझे पता है, बीते हुए समय को मापने के कम से कम दस तरीके हैं:

मोनोटोनिक घड़ी आधारित:

  1. ProcessInfo.systemUptime
  2. mach_absolute_timeसाथ mach_timebase_infoके रूप में में वर्णित इस जवाब
  3. clock()में POSIX मानक
  4. times()में POSIX मानक । (तब से जटिल है जब हमें उपयोगकर्ता-समय बनाम सिस्टम-टाइम पर विचार करने की आवश्यकता होती है, और बच्चे प्रक्रिया में शामिल होते हैं।)
  5. DispatchTime (स्वीकार समय एपीआई के आसपास एक आवरण) जेरेमीप द्वारा स्वीकार किए जाते हैं।
  6. CACurrentMediaTime()

दीवार घड़ी आधारित:

(कभी भी मैट्रिक्स के लिए उन का उपयोग न करें: नीचे देखें क्यों)

  1. NSDate/ Dateजैसा कि दूसरों द्वारा उल्लेख किया गया है।
  2. CFAbsoluteTime जैसा कि दूसरों द्वारा बताया गया है।
  3. DispatchWallTime
  4. gettimeofday()में POSIX मानक

विकल्प 1, 2 और 3 नीचे विस्तृत हैं।

विकल्प 1: फाउंडेशन में प्रोसेस इंफो एपीआई

do {
    let info = ProcessInfo.processInfo
    let begin = info.systemUptime
    // do something
    let diff = (info.systemUptime - begin)
}

कहाँ पे diff:NSTimeInterval बीता हुआ समय सेकंडों से है।

विकल्प 2: मच सी एपीआई

do {
    var info = mach_timebase_info(numer: 0, denom: 0)
    mach_timebase_info(&info)
    let begin = mach_absolute_time()
    // do something
    let diff = Double(mach_absolute_time() - begin) * Double(info.numer) / Double(info.denom)
}

कहाँ पे diff:Doubleनैनो-सेकंड द्वारा बीता हुआ समय है।

विकल्प 3: POSIX घड़ी एपीआई

do {
    let begin = clock()
    // do something
    let diff = Double(clock() - begin) / Double(CLOCKS_PER_SEC)
}

कहाँ पे diff:Double बीता हुआ समय सेकंडों से है।

बीते हुए समय के लिए दीवार-घड़ी का समय क्यों नहीं?

के प्रलेखन में CFAbsoluteTimeGetCurrent:

इस फ़ंक्शन के लिए बार-बार कॉल करने से नीरस रूप से बढ़ते परिणामों की गारंटी नहीं मिलती है।

कारण जावा में currentTimeMillisबनाम केnanoTime समान है :

आप दूसरे उद्देश्य के लिए एक का उपयोग नहीं कर सकते। कारण यह है कि किसी भी कंप्यूटर की घड़ी सही नहीं है; यह हमेशा बहता है और कभी-कभी इसे ठीक करने की आवश्यकता होती है। यह सुधार या तो मैन्युअल रूप से हो सकता है, या अधिकांश मशीनों के मामले में, एक ऐसी प्रक्रिया है जो चलती है और सिस्टम घड़ी ("दीवार घड़ी") में छोटे सुधार जारी करती है। ये अक्सर होते रहते हैं। एक और ऐसा सुधार तब होता है जब कोई लीप सेकंड होता है।

यहाँ CFAbsoluteTimeस्टार्ट-अप समय के बजाय दीवार घड़ी समय प्रदान करता है। NSDateदीवार घड़ी का समय भी है।


सबसे अच्छा जवाब - लेकिन क्या, नरक, लेने के लिए सबसे अच्छा तरीका है ?!
फेटी

1
विकल्प 5 मेरे लिए सबसे उपयुक्त है। यदि आप मल्टी-प्लेटफ़ॉर्म कोड पर विचार कर रहे हैं तो इसे आज़माएँ। डार्विन और ग्लिबेक दोनों पुस्तकालयों का clock()कार्य है।
मिशा Svyatoshenko

सिस्टम घड़ी आधारित समाधान के लिए: मैं के साथ सफलता मिली ProcessInfo.processInfo.systemUptime, mach_absolute_time(), DispatchTime.now()और CACurrentMediaTime()। लेकिन साथ समाधान clock()सेकंड के लिए ठीक से परिवर्तित नहीं हो रहा था। इसलिए मैं आपको अपना पहला वाक्य अपडेट करने की सलाह दूंगा : " सटीक स्टार्ट-अप समय के लिए ProcessInfo.systemUptime या DispatchTime का उपयोग करें। "
C 29ur

36

स्विफ्ट 4 सबसे छोटा जवाब:

let startingPoint = Date()
//  ... intensive task
print("\(startingPoint.timeIntervalSinceNow * -1) seconds elapsed")

यह आपको 1.02107906341553 सेकंड्स की तरह प्रिंट करेगा (बेशक समय कार्य के आधार पर अलग-अलग होगा, मैं सिर्फ आप लोगों को इस माप के लिए दशमलव सटीक स्तर देखने के लिए यह दिखा रहा हूं)।

आशा है कि यह अब से 4 स्विफ्ट 4 में किसी की मदद करता है!

अपडेट करें

यदि आप कोड के भागों के परीक्षण का एक सामान्य तरीका चाहते हैं, तो मैं अगले स्निपेट का सुझाव दूंगा:

func measureTime(for closure: @autoclosure () -> Any) {
    let start = CFAbsoluteTimeGetCurrent()
    closure()
    let diff = CFAbsoluteTimeGetCurrent() - start
    print("Took \(diff) seconds")
}

*Usage*

measureTime(for: <insert method signature here>)

**Console log**
Took xx.xxxxx seconds

क्या कोई समझा सकता है कि क्यों * -1?
मक्सिम नियाज़ेव

1
@MaksimKniazev क्योंकि यह नकारात्मक मूल्य है, लोग सकारात्मक चाहते हैं!
थानेब

@thachnb मुझे पता नहीं था कि "startPoint.timeIntervalSinceNow" नकारात्मक मूल्य पैदा करता है ...
मक्सिम नियाज़ेव

1
@MaksimKniazev Apple का कहना है कि: यदि दिनांक ऑब्जेक्ट वर्तमान दिनांक और समय से पहले है, तो इस गुण का मान ऋणात्मक है।
पीटर गुआन

13
let start = NSDate()

for index in 1...10000 {
    // do nothing
}

let elapsed = start.timeIntervalSinceNow

// elapsed is a negative value.

2
abs (start.timeIntervalSinceNow) // <- सकारात्मक मूल्य
eonist

बहुत अधिक सीधे आगे का समाधान मैंने देखा है, धन्यवाद
मिलादीउएम

10

बस इस फ़ंक्शन को कॉपी और पेस्ट करें। स्विफ्ट में लिखा है 5. यहां जेरेमीपी को कॉपी करना।

func calculateTime(block : (() -> Void)) {
        let start = DispatchTime.now()
        block()
        let end = DispatchTime.now()
        let nanoTime = end.uptimeNanoseconds - start.uptimeNanoseconds
        let timeInterval = Double(nanoTime) / 1_000_000_000
        print("Time: \(timeInterval) seconds")
    }

इसका उपयोग करें

calculateTime {
     exampleFunc()// function whose execution time to be calculated
}

6

आप timeकॉल को मापने के लिए एक फ़ंक्शन बना सकते हैं । मैं कैलास के उत्तर से प्रेरित हूं ।

func time <A> (f: @autoclosure () -> A) -> (result:A, duration: String) {
    let startTime = CFAbsoluteTimeGetCurrent()
    let result = f()
    let endTime = CFAbsoluteTimeGetCurrent()
    return (result, "Elapsed time is \(endTime - startTime) seconds.")
}

यह फ़ंक्शन आपको इसे इस तरह से कॉल करने की अनुमति देगा time (isPrime(7))जो परिणाम के साथ एक ट्यूपल लौटाएगा और बीता समय का एक स्ट्रिंग विवरण।

यदि आप केवल बीता हुआ समय चाहते हैं तो आप ऐसा कर सकते हैं time (isPrime(7)).duration


3
"इस फ़ंक्शन के लिए बार-बार कॉल करने से नीरस रूप से बढ़ते परिणामों की गारंटी नहीं मिलती है।" प्रलेखन के अनुसार ।
फ्रैंकलिन यू

3

बंद करने के साथ निष्पादन समय को मापने के लिए सरल सहायक कार्य।

func printExecutionTime(withTag tag: String, of closure: () -> ()) {
    let start = CACurrentMediaTime()
    closure()
    print("#\(tag) - execution took \(CACurrentMediaTime() - start) seconds")
}

उपयोग:

printExecutionTime(withTag: "Init") {
    // Do your work here
}

परिणाम: #Init - execution took 1.00104497105349 seconds


2

आप इस तरह से नैनोसेकंड को माप सकते हैं :

let startDate: NSDate = NSDate()

// your long procedure

let endDate: NSDate = NSDate()
let dateComponents: NSDateComponents = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian).components(NSCalendarUnit.CalendarUnitNanosecond, fromDate: startDate, toDate: endDate, options: NSCalendarOptions(0))
println("runtime is nanosecs : \(dateComponents.nanosecond)")

मैंने इसे "// आपकी लंबी प्रक्रिया" में रखे कोड के साथ नहीं चलाया, और इसने 240900993 का परिणाम दिया, जो 0.24 सेकंड था।
user1021430

एक NSCalendarको इंस्टेंट करना एक महंगी प्रक्रिया है, लेकिन आप अपनी प्रक्रिया को चलाने के लिए शुरू करने से पहले इसे कर सकते हैं , इसलिए इसे आपकी लंबी प्रक्रिया के रनटाइम में नहीं जोड़ा जाएगा ... एक NSDateउदाहरण और कॉलिंग –components(_:, fromDate:)विधि को ध्यान में रखते हुए अभी भी समय लगता है, इसलिए शायद आपको कभी भी 0.0नैनोसेकंड नहीं मिलेगा ।
holex

NSCalendar कंस्ट्रक्टर के लुक से, ऐसा प्रतीत होता है कि समय से पहले इसे बनाना संभव नहीं हो सकता है (startDate एक आवश्यक इनपुट है)। यह आश्चर्य की बात है कि यह एक ऐसा हॉग लगता है।
user1021430

आप ऐसा कर सकते हैं (मेरा अद्यतन उत्तर), बिना किसी अतिरिक्त प्रक्रिया के मापा समय 6.9मेरे डिवाइस पर माइक्रोसेकंड के बारे में है।
हॉलेक्स

धन्यवाद। मूल प्रक्रिया अब जेरेमीप के उत्तर के समान है, लेकिन रिपोर्टिंग अलग है।
user1021430

2

मैं इसका उपयोग करता हूं:

public class Stopwatch {
    public init() { }
    private var start_: NSTimeInterval = 0.0;
    private var end_: NSTimeInterval = 0.0;

    public func start() {
        start_ = NSDate().timeIntervalSince1970;
    }

    public func stop() {
        end_ = NSDate().timeIntervalSince1970;
    }

    public func durationSeconds() -> NSTimeInterval {
        return end_ - start_;
    }
}

मुझे नहीं पता कि यह पहले से कम या ज्यादा सटीक है। लेकिन सेकंड में बहुत अधिक दशमलव होते हैं और एल्गोरिदम में छोटे कोड परिवर्तन को पकड़ने के लिए लगता है जैसे क्विकॉर्ट का उपयोग स्वैप () बनाम स्वैप स्वयं को लागू करना आदि।

प्रदर्शन का परीक्षण करते समय अपनी बिल्ड ऑप्टिमाइज़ेशन को क्रैंक करना याद रखें:

स्विफ्ट कंपाइलर ऑप्टिमाइजेशन


2

यहाँ सरल उत्तर के लिए मेरी कोशिश है:

let startTime = Date().timeIntervalSince1970  // 1512538946.5705 seconds

// time passes (about 10 seconds)

let endTime = Date().timeIntervalSince1970    // 1512538956.57195 seconds
let elapsedTime = endTime - startTime         // 10.0014500617981 seconds

टिप्पणियाँ

  • startTimeऔर endTimeप्रकार के होते हैं TimeInterval, जो सिर्फ एक के typealiasलिए है Double, इसलिए इसे एक में बदलना आसान हैInt या जो भी रूप में । उप-मिलीसेकंड परिशुद्धता के साथ सेकंड में समय मापा जाता है।
  • यह सभी देखें DateInterval , जिसमें एक वास्तविक शुरुआत और अंत समय शामिल है।
  • 1970 के बाद के समय का उपयोग करना जावा टाइमस्टैम्प के समान है ।

सबसे आसान तरीका है, इसे दो तार में पसंद करेंगे, दूसरा है elapsedTime = Date ()। timeIntervalSince1970
startTime

1

रनिंग और अंतराल समय को मापने के लिए एक हल्के ढांचे को बनाने के लिए मैंने कलस से विचार उधार लिया है:

कोड उपयोग:

var timer = RunningTimer.init()
// Code to be timed
print("Running: \(timer) ") // Gives time interval
// Second code to be timed
print("Running: \(timer) ") // Gives final time

स्टॉप फ़ंक्शन को कॉल करने की आवश्यकता नहीं है, क्योंकि प्रिंट फ़ंक्शन लैप्स किए गए समय देगा। समय व्यतीत हो जाने के लिए इसे बार-बार कहा जा सकता है। लेकिन कोड के उपयोग में कुछ बिंदु पर टाइमर को रोकने के लिए timer.stop()इसका उपयोग सेकंड में समय वापस करने के लिए भी किया जा सकता है: let seconds = timer.stop() टाइमर बंद हो जाने के बाद अंतराल टाइमर नहीं होगा, इसलिए print("Running: \(timer) ")कोड की कुछ पंक्तियों के बाद भी सही समय देगा।

निम्नलिखित RunTimer के लिए कोड है। यह स्विफ्ट 2.1 के लिए परीक्षण किया गया है:

import CoreFoundation
// Usage:    var timer = RunningTimer.init()
// Start:    timer.start() to restart the timer
// Stop:     timer.stop() returns the time and stops the timer
// Duration: timer.duration returns the time
// May also be used with print(" \(timer) ")

struct RunningTimer: CustomStringConvertible {
    var begin:CFAbsoluteTime
    var end:CFAbsoluteTime

    init() {
        begin = CFAbsoluteTimeGetCurrent()
        end = 0
    }
    mutating func start() {
        begin = CFAbsoluteTimeGetCurrent()
        end = 0
    }
    mutating func stop() -> Double {
        if (end == 0) { end = CFAbsoluteTimeGetCurrent() }
        return Double(end - begin)
    }
    var duration:CFAbsoluteTime {
        get {
            if (end == 0) { return CFAbsoluteTimeGetCurrent() - begin } 
            else { return end - begin }
        }
    }
    var description:String {
    let time = duration
    if (time > 100) {return " \(time/60) min"}
    else if (time < 1e-6) {return " \(time*1e9) ns"}
    else if (time < 1e-3) {return " \(time*1e6) µs"}
    else if (time < 1) {return " \(time*1000) ms"}
    else {return " \(time) s"}
    }
}

1

आसान उपयोग के लिए इसे एक पूर्ण ब्लॉक में लपेटें।

public class func secElapsed(completion: () -> Void) {
    let startDate: NSDate = NSDate()
    completion()
    let endDate: NSDate = NSDate()
    let timeInterval: Double = endDate.timeIntervalSinceDate(startDate)
    println("seconds: \(timeInterval)")
}

0

यह वह स्निपेट है जिसके साथ मैं आया था और यह स्विफ्ट 4 के साथ मेरी मैकबुक पर मेरे लिए काम करता है।

कभी भी अन्य प्रणालियों पर परीक्षण नहीं किया गया, लेकिन मुझे लगा कि यह वैसे भी साझा करने लायक है।

typealias MonotonicTS = UInt64
let monotonic_now: () -> MonotonicTS = mach_absolute_time

let time_numer: UInt64
let time_denom: UInt64
do {
    var time_info = mach_timebase_info(numer: 0, denom: 0)
    mach_timebase_info(&time_info)
    time_numer = UInt64(time_info.numer)
    time_denom = UInt64(time_info.denom)
}

// returns time interval in seconds
func monotonic_diff(from: MonotonicTS, to: MonotonicTS) -> TimeInterval {
    let diff = (to - from)
    let nanos = Double(diff * time_numer / time_denom)
    return nanos / 1_000_000_000
}

func seconds_elapsed(since: MonotonicTS) -> TimeInterval {
    return monotonic_diff(from: since, to:monotonic_now())
}

इसका उपयोग कैसे करना है, इसका एक उदाहरण यहां दिया गया है:

let t1 = monotonic_now()
// .. some code to run ..
let elapsed = seconds_elapsed(since: t1)
print("Time elapsed: \(elapsed*1000)ms")

दूसरा तरीका यह है कि इसे और अधिक स्पष्ट रूप से करें:

let t1 = monotonic_now()
// .. some code to run ..
let t2 = monotonic_now()
let elapsed = monotonic_diff(from: t1, to: t2)
print("Time elapsed: \(elapsed*1000)ms")

0

यह मैंने इसे कैसे लिखा है।

 func measure<T>(task: () -> T) -> Double {
        let startTime = CFAbsoluteTimeGetCurrent()
        task()
        let endTime = CFAbsoluteTimeGetCurrent()
        let result = endTime - startTime
        return result
    }

एक एल्गोरिथ्म को मापने के लिए इसे उसी तरह उपयोग करें

let time = measure {
    var array = [2,4,5,2,5,7,3,123,213,12]
    array.sorted()
}

print("Block is running \(time) seconds.")

वह समय कितना सही है? क्योंकि मैंने हर 0.1 सेकंड में अपडेट करने से पहले टाइमर का इस्तेमाल किया। मैंने इस उत्तर की तुलना की और टाइमर के साथ एक और इस उत्तर से परिणाम 0.1 सेकंड अधिक टाइमर के साथ है ..
मक्सिम नियाज़ेव

0

बेसिक फंक्शन टाइमिंग के लिए स्टेटिक स्विफ्ट 3 क्लास। यह नाम से प्रत्येक टाइमर का ट्रैक रखेगा। उस बिंदु पर इसे इस तरह से कॉल करें जिसे आप मापना शुरू करना चाहते हैं:

Stopwatch.start(name: "PhotoCapture")

कैप्चर किए गए समय को पकड़ने और प्रिंट करने के लिए इसे कॉल करें:

Stopwatch.timeElapsed(name: "PhotoCapture")

यह आउटपुट है: *** PhotoCapture elapsed ms: 1402.415125 यदि आप नैनो का उपयोग करना चाहते हैं, तो "उपयोगनोस" पैरामीटर है। कृपया आवश्यकतानुसार बदलने के लिए स्वतंत्र महसूस करें।

   class Stopwatch: NSObject {

  private static var watches = [String:TimeInterval]()

  private static func intervalFromMachTime(time: TimeInterval, useNanos: Bool) -> TimeInterval {
     var info = mach_timebase_info()
     guard mach_timebase_info(&info) == KERN_SUCCESS else { return -1 }
     let currentTime = mach_absolute_time()
     let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom)
     if useNanos {
        return (TimeInterval(nanos) - time)
     }
     else {
        return (TimeInterval(nanos) - time) / TimeInterval(NSEC_PER_MSEC)
     }
  }

  static func start(name: String) {
     var info = mach_timebase_info()
     guard mach_timebase_info(&info) == KERN_SUCCESS else { return }
     let currentTime = mach_absolute_time()
     let nanos = currentTime * UInt64(info.numer) / UInt64(info.denom)
     watches[name] = TimeInterval(nanos)
  }

  static func timeElapsed(name: String) {
     return timeElapsed(name: name, useNanos: false)
  }

  static func timeElapsed(name: String, useNanos: Bool) {
     if let start = watches[name] {
        let unit = useNanos ? "nanos" : "ms"
        print("*** \(name) elapsed \(unit): \(intervalFromMachTime(time: start, useNanos: useNanos))")
     }
  }

}


के साथ आपके पूरे काम mach_timebase_infoको पहले से ही लागू किया गया है जो आपने स्रोत कोड में किया था ProcessInfo.processInfo.systemUptime। तो बस करो watches[name] = ProcessInfo.processInfo.systemUptime। और * TimeInterval(NSEC_PER_MSEC)अगर आप नैनो चाहते हैं।
कूर

0

फ्रेंकलिन यू जवाब और Cœur टिप्पणियों के आधार पर

विवरण

  • Xcode 10.1 (10B61)
  • स्विफ्ट 4.2

समाधान 1

मापने (_ :)

समाधान २

import Foundation

class Measurer<T: Numeric> {

    private let startClosure: ()->(T)
    private let endClosure: (_ beginningTime: T)->(T)

    init (startClosure: @escaping ()->(T), endClosure: @escaping (_ beginningTime: T)->(T)) {
        self.startClosure = startClosure
        self.endClosure = endClosure
    }

    init (getCurrentTimeClosure: @escaping ()->(T)) {
        startClosure = getCurrentTimeClosure
        endClosure = { beginningTime in
            return getCurrentTimeClosure() - beginningTime
        }
    }

    func measure(closure: ()->()) -> T {
        let value = startClosure()
        closure()
        return endClosure(value)
    }
}

समाधान 2 का उपयोग

// Sample with ProcessInfo class

m = Measurer { ProcessInfo.processInfo.systemUptime }
time = m.measure {
    _ = (1...1000).map{_ in Int(arc4random()%100)}
}
print("ProcessInfo: \(time)")

// Sample with Posix clock API

m = Measurer(startClosure: {Double(clock())}) { (Double(clock()) - $0 ) / Double(CLOCKS_PER_SEC) }
time = m.measure {
    _ = (1...1000).map{_ in Int(arc4random()%100)}
}
print("POSIX: \(time)")

यह निश्चित नहीं है कि हमें चर कार्यान्वयन का उपयोग करने की आवश्यकता क्यों होगी। Dateकिसी भी चीज़ को मापने के लिए उपयोग करना अत्यंत हतोत्साहित करता है (लेकिन systemUptimeया clock()ठीक है)। परीक्षणों के लिए, हमारे पास measure(_:)पहले से ही है।
Cœur

1
एक और नोट: बंद करने को वैकल्पिक क्यों बनाया जाए?
कूर

@ आप सही हैं! आपकी टिप्पणियों के लिए आभार। बाद में पोस्ट अपडेट करूंगा।
वासिली बोर्नार्चुक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.