it-swarm.asia

Bagaimana cara mencatat waktu eksekusi metode dalam milidetik?

Apakah ada cara untuk menentukan berapa banyak waktu yang dibutuhkan suatu metode untuk dieksekusi (dalam milidetik)?

203
dan
NSDate *methodStart = [NSDate date];

/* ... Do whatever you need to do ... */

NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);

Swift:

let methodStart = NSDate()

/* ... Do whatever you need to do ... */

let methodFinish = NSDate()
let executionTime = methodFinish.timeIntervalSinceDate(methodStart)
print("Execution time: \(executionTime)")

Swift3:

let methodStart = Date()

/* ... Do whatever you need to do ... */

let methodFinish = Date()
let executionTime = methodFinish.timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")

Mudah digunakan dan memiliki presisi sub-milidetik.

414
Matthew McGoogan

Berikut adalah dua makro satu baris yang saya gunakan:

#define TICK   NSDate *startTime = [NSDate date]
#define TOCK   NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])

Gunakan seperti ini:

TICK;

/* ... Do Some Work Here ... */

TOCK;
243
Ron

Untuk pengaturan waktu halus pada OS X, Anda harus menggunakan mach_absolute_time( ) yang dideklarasikan dalam <mach/mach_time.h>:

#include <mach/mach_time.h>
#include <stdint.h>

// Do some stuff to setup for timing
const uint64_t startTime = mach_absolute_time();
// Do some stuff that you want to time
const uint64_t endTime = mach_absolute_time();

// Time elapsed in Mach time units.
const uint64_t elapsedMTU = endTime - startTime;

// Get information for converting from MTU to nanoseconds
mach_timebase_info_data_t info;
if (mach_timebase_info(&info))
   handleErrorConditionIfYoureBeingCareful();

// Get elapsed time in nanoseconds:
const double elapsedNS = (double)elapsedMTU * (double)info.numer / (double)info.denom;

Tentu saja peringatan biasa tentang pengukuran berbutir halus berlaku; Anda mungkin sebaiknya menjalankan rutin yang sedang diuji berkali-kali, dan rata-rata/mengambil minimum/beberapa bentuk pemrosesan lainnya.

Selain itu, harap perhatikan bahwa Anda mungkin merasa lebih berguna untuk profil aplikasi Anda berjalan menggunakan alat seperti Shark. Ini tidak akan memberi Anda informasi waktu yang tepat, tetapi akan memberi tahu Anda berapa persentase dari waktu aplikasi yang dihabiskan di mana, yang seringkali lebih bermanfaat (tetapi tidak selalu).

48
Stephen Canon

Di Swift, saya menggunakan:

Di Macro saya. Saya baru saja menambahkan

var startTime = NSDate()
func TICK(){ startTime =  NSDate() }
func TOCK(function: String = __FUNCTION__, file: String = __FILE__, line: Int = __LINE__){
    println("\(function) Time: \(startTime.timeIntervalSinceNow)\nLine:\(line) File: \(file)")
}

anda sekarang dapat menelepon ke mana saja 

TICK()

// your code to be tracked

TOCK()
  • kode ini didasarkan pada kode Ron yang diterjemahkan ke Swift, ia memiliki kredit
  • Saya menggunakan tanggal mulai di tingkat global, saran untuk meningkatkan dipersilahkan 
11
Adriano Spadoni

Saya tahu ini sudah lama tetapi bahkan saya mendapati diri saya melewatinya lagi, jadi saya pikir saya akan menyerahkan pilihan saya sendiri di sini.

Taruhan terbaik adalah untuk memeriksa posting blog saya di ini: Mengatur waktu hal-hal di Objective-C: A stopwatch

Pada dasarnya, saya menulis sebuah kelas yang tidak berhenti menonton dengan cara yang sangat dasar tetapi dienkapsulasi sehingga Anda hanya perlu melakukan hal berikut:

[MMStopwatchARC start:@"My Timer"];
// your work here ...
[MMStopwatchARC stop:@"My Timer"];

Dan Anda berakhir dengan:

MyApp[4090:15203]  -> Stopwatch: [My Timer] runtime: [0.029]

dalam log ...

Sekali lagi, lihat posting saya untuk lebih banyak atau unduh di sini: MMStopwatch.Zip

9
bladnman

Saya menggunakan makro berdasarkan Ron's solusi.

#define TICK(XXX) NSDate *XXX = [NSDate date]
#define TOCK(XXX) NSLog(@"%s: %f", #XXX, -[XXX timeIntervalSinceNow])

Untuk baris kode:

TICK(TIME1);
/// do job here
TOCK(TIME1);

kita akan melihat di konsol sesuatu seperti: TIME1: 0,096618

7
Sergey Teryokhin

Saya menggunakan sangat minim, implementasi satu halaman kelas terinspirasi oleh kode dari posting blog ini :

#import <mach/mach_time.h>

@interface DBGStopwatch : NSObject

+ (void)start:(NSString *)name;
+ (void)stop:(NSString *)name;

@end

@implementation DBGStopwatch

+ (NSMutableDictionary *)watches {
    static NSMutableDictionary *Watches = nil;
    static dispatch_once_t OnceToken;
    dispatch_once(&OnceToken, ^{
        Watches = @{}.mutableCopy;
    });
    return Watches;
}

+ (double)secondsFromMachTime:(uint64_t)time {
    mach_timebase_info_data_t timebase;
    mach_timebase_info(&timebase);
    return (double)time * (double)timebase.numer /
        (double)timebase.denom / 1e9;
}

+ (void)start:(NSString *)name {
    uint64_t begin = mach_absolute_time();
    self.watches[name] = @(begin);
}

+ (void)stop:(NSString *)name {
    uint64_t end = mach_absolute_time();
    uint64_t begin = [self.watches[name] unsignedLongLongValue];
    DDLogInfo(@"Time taken for %@ %g s",
              name, [self secondsFromMachTime:(end - begin)]);
    [self.watches removeObjectForKey:name];
}

@end

Penggunaannya sangat sederhana: 

  • cukup panggil [DBGStopwatch start:@"slow-operation"]; di awal
  • dan kemudian [DBGStopwatch stop:@"slow-operation"]; setelah selesai, untuk mendapatkan waktu
4
zubko

Anda bisa mendapatkan benar-benar pengaturan waktu yang baik (seconds.parts detik) menggunakan kelas StopWatch ini. Menggunakan pengatur waktu presisi tinggi di iPhone. Menggunakan NSDate hanya akan memberi Anda akurasi kedua. Versi ini dirancang khusus untuk autorelease dan objektif-c. Saya memiliki versi c ++ juga jika diperlukan. Anda dapat menemukan versi c ++ di sini .

StopWatch.h

#import <Foundation/Foundation.h>


@interface StopWatch : NSObject 
{
    uint64_t _start;
    uint64_t _stop;
    uint64_t _elapsed;
}

-(void) Start;
-(void) Stop;
-(void) StopWithContext:(NSString*) context;
-(double) seconds;
-(NSString*) description;
+(StopWatch*) stopWatch;
-(StopWatch*) init;
@end

StopWatch.m

#import "StopWatch.h"
#include <mach/mach_time.h>

@implementation StopWatch

-(void) Start
{
    _stop = 0;
    _elapsed = 0;
    _start = mach_absolute_time();
}
-(void) Stop
{
    _stop = mach_absolute_time();   
    if(_stop > _start)
    {
        _elapsed = _stop - _start;
    }
    else 
    {
        _elapsed = 0;
    }
    _start = mach_absolute_time();
}

-(void) StopWithContext:(NSString*) context
{
    _stop = mach_absolute_time();   
    if(_stop > _start)
    {
        _elapsed = _stop - _start;
    }
    else 
    {
        _elapsed = 0;
    }
    NSLog([NSString stringWithFormat:@"[%@] Stopped at %f",context,[self seconds]]);

    _start = mach_absolute_time();
}


-(double) seconds
{
    if(_elapsed > 0)
    {
        uint64_t elapsedTimeNano = 0;

        mach_timebase_info_data_t timeBaseInfo;
        mach_timebase_info(&timeBaseInfo);
        elapsedTimeNano = _elapsed * timeBaseInfo.numer / timeBaseInfo.denom;
        double elapsedSeconds = elapsedTimeNano * 1.0E-9;
        return elapsedSeconds;
    }
    return 0.0;
}
-(NSString*) description
{
    return [NSString stringWithFormat:@"%f secs.",[self seconds]];
}
+(StopWatch*) stopWatch
{
    StopWatch* obj = [[[StopWatch alloc] init] autorelease];
    return obj;
}
-(StopWatch*) init
{
    [super   init];
    return self;
}

@end

Kelas memiliki metode stopWatch statis yang mengembalikan objek autoreleased. 

Setelah Anda memanggil start, gunakan metode seconds untuk mendapatkan waktu yang telah berlalu. Panggil start lagi untuk memulai kembali. Atau stop untuk menghentikannya. Anda masih dapat membaca waktu (panggilan seconds) kapan saja setelah menelepon stop.

Contoh Dalam Fungsi (Panggilan waktu eksekusi)

-(void)SomeFunc
{
   StopWatch* stopWatch = [StopWatch stopWatch];
   [stopWatch Start];

   ... do stuff

   [stopWatch StopWithContext:[NSString stringWithFormat:@"Created %d Records",[records count]]];
}
3

Contoh pengaturan waktu halus menggunakan mach_absolute_time() di Swift 4:

let start = mach_absolute_time()

// do something

let elapsedMTU = mach_absolute_time() - start
var timebase = mach_timebase_info()
if mach_timebase_info(&timebase) == 0 {
    let elapsed = Double(elapsedMTU) * Double(timebase.numer) / Double(timebase.denom)
    print("render took \(elapsed)")
}
else {
    print("timebase error")
}
2
jbg

Saya menggunakan kode ini:

#import <mach/mach_time.h>

float TIME_BLOCK(NSString *key, void (^block)(void)) {
    mach_timebase_info_data_t info;
    if (mach_timebase_info(&info) != KERN_SUCCESS)
    {
        return -1.0;
    }

    uint64_t start = mach_absolute_time();
    block();
    uint64_t end = mach_absolute_time();
    uint64_t elapsed = end - start;

    uint64_t nanos = elapsed * info.numer / info.denom;
    float cost = (float)nanos / NSEC_PER_SEC;

    NSLog(@"key: %@ (%f ms)\n", key, cost * 1000);
    return cost;
}
2
cleexiang

Oke, jika tujuan Anda adalah mencari tahu apa yang dapat Anda perbaiki untuk membuatnya lebih cepat, itu adalah tujuan yang sedikit berbeda. Mengukur waktu yang dibutuhkan fungsi adalah cara yang baik untuk mengetahui apakah apa yang Anda lakukan membuat perbedaan, tetapi untuk mencari tahu apa yang harus dilakukan Anda memerlukan teknik yang berbeda. Ini yang saya rekomendasikan , dan saya tahu Anda bisa melakukannya di iPhone.

Sunting: Peninjau menyarankan agar saya menguraikan jawabannya, jadi saya mencoba memikirkan cara singkat untuk mengatakannya.
.__ Program keseluruhan Anda membutuhkan cukup waktu jam untuk mengganggu Anda. Misalkan itu N detik.
Anda berasumsi Anda dapat mempercepatnya. Satu-satunya cara Anda dapat melakukan itu adalah dengan membuatnya tidak melakukan sesuatu yang dilakukannya saat itu, terhitung m detik.
Anda awalnya tidak tahu benda apa itu. Anda bisa menebak, seperti yang dilakukan semua programmer, tetapi bisa dengan mudah menjadi sesuatu yang lain. Apa pun itu, inilah cara Anda dapat menemukannya:

Karena benda itu, apa pun itu, menyumbang fraksi m/N pada saat itu, itu berarti jika Anda menjeda secara acak kemungkinannya adalah m/N bahwa Anda akan menangkapnya saat melakukan itu. Tentu saja itu mungkin melakukan sesuatu yang lain, tetapi berhenti sebentar dan lihat apa yang dilakukannya.
.__ Sekarang lakukan lagi. Jika Anda melihatnya melakukan hal yang sama lagi, Anda bisa lebih curiga.

Lakukan 10 kali, atau 20. Sekarang jika Anda melihatnya melakukan hal tertentu (tidak peduli bagaimana Anda menggambarkannya) pada beberapa jeda, yang dapat Anda singkirkan, Anda tahu dua hal. Anda tahu kira-kira berapa lama waktu yang dibutuhkan, tetapi Anda tahu sangat tepat apa yang harus diperbaiki.
Jika Anda juga ingin tahu dengan sangat tepat berapa banyak waktu yang akan dihemat, itu mudah. Ukur sebelum, perbaiki, dan ukur sesudahnya. Jika Anda benar-benar kecewa, mundurlah perbaiki.

Apakah Anda melihat bagaimana ini berbeda dari mengukur? Ini menemukan, bukan mengukur. Kebanyakan profiling didasarkan pada pengukuran setepat mungkin berapa banyak waktu yang dibutuhkan, seolah-olah itu penting, dan menggerakkan tangan masalah mengidentifikasi apa yang perlu diperbaiki. Pembuatan profil tidak menemukan setiap masalah, tetapi metode ini menemukan setiap masalah, dan masalah yang menurut Anda tidak merugikan Anda.

2
Mike Dunlavey

Saya menggunakan ini:

clock_t start, end;
double elapsed;
start = clock();

//Start code to time

//End code to time

end = clock();
elapsed = ((double) (end - start)) / CLOCKS_PER_SEC;
NSLog(@"Time: %f",elapsed);

Tapi saya tidak yakin tentang CLOCKS_PER_SEC di iPhone. Anda mungkin ingin meninggalkannya.

2
David Kanarek

Ada pembungkus yang nyaman untuk mach_absolute_time() - ini adalah fungsi CACurrentMediaTime().

Tidak seperti offset NSDate atau CFAbsoluteTimeGetCurrent(), mach_absolute_time() dan CACurrentMediaTime() didasarkan pada Jam Host internal, ukuran monatomik yang presisi, dan tidak tunduk pada perubahan dalam referensi waktu eksternal, seperti yang disebabkan oleh waktu zona, penghematan siang hari, atau detik kabisat.


ObjC

CFTimeInterval startTime = CACurrentMediaTime();
// Do your stuff here
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(@"Total Runtime: %g s", endTime - startTime);

Swift

let startTime = CACurrentMediaTime()
// Do your stuff here
let endTime = CACurrentMediaTime()
print("Total Runtime: \(endTime - startTime) s")
2
Alex Nazaroff

Saya menggunakan ini di perpustakaan utils saya ( Swift 4.2 ):

public class PrintTimer {
    let start = Date()
    let name: String

    public init(file: String=#file, line: Int=#line, function: String=#function, name: String?=nil) {
        let file = file.split(separator: "/").last!
        self.name = name ?? "\(file):\(line) - \(function)"
    }

    public func done() {
        let end = Date()
        print("\(self.name) took \((end.timeIntervalSinceReferenceDate - self.start.timeIntervalSinceReferenceDate).roundToSigFigs(5)) s.")
    }
}

... lalu panggil dengan metode seperti:

func myFunctionCall() {
    let timer = PrintTimer()
    // ...
    timer.done()
}

... yang pada gilirannya terlihat seperti ini di konsol setelah dijalankan:

MyFile.Swift:225 - myFunctionCall() took 1.8623 s.

Tidak sesingkat TICK/TOCK di atas, tetapi cukup jelas untuk melihat apa yang dilakukannya dan secara otomatis menyertakan apa yang sedang dihitung waktunya (berdasarkan file, baris pada awal metode, dan nama fungsi). Jelas jika saya ingin lebih detail (mis., Jika saya tidak hanya menghitung waktu pemanggilan metode seperti kasus biasa tetapi saya menghitung waktu blok dalam metode itu) Saya dapat menambahkan parameter "name =" Foo "" pada init PrintTimer menamakannya sesuatu selain default.

0
Tom Dibble

Berikut cara lain, di Swift, untuk melakukannya menggunakan kata kunci penangguhan

func methodName() {
  let methodStart = Date()
  defer {
    let executionTime = Date().timeIntervalSince(methodStart)
    print("Execution time: \(executionTime)")
  }
  // do your stuff here
}

Dari Apple docs : Pernyataan penundaan digunakan untuk mengeksekusi kode sesaat sebelum mentransfer kontrol program di luar lingkup di mana pernyataan penundaan muncul.

Ini mirip dengan blok coba/akhirnya dengan keuntungan memiliki kode terkait yang dikelompokkan.

0
CMont