Bagaimana cara mencatat waktu eksekusi metode dalam milidetik?


222

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


2
Apakah Anda kebetulan bertanya karena Anda ingin mencari tahu apa yang dapat Anda optimalkan untuk membuatnya lebih cepat?
Mike Dunlavey

1
Ya, saya menggunakan UIWebView yang memuat beberapa halaman. Saya ingin mengoptimalkan pageloading dengan memeriksa waktu metode perlu memuat halaman 1 ke halaman 10.
dan

2
Ini tampaknya merupakan duplikat dari pertanyaan ini: stackoverflow.com/questions/889380/…
Brad Larson

@BradLarson Meskipun tampaknya merupakan duplikat, pertanyaan lain memiliki jawaban yang lebih baik, yaitu ada jawaban yang menonjol tidak menyarankan untuk menggunakan NSDate (yang salah) tetapi menjelaskan dengan baik mengapa NSDate adalah cara yang salah untuk melakukan untuk tujuan ini.
Thomas Tempelmann

Jawaban:


437
NSDate *methodStart = [NSDate date];

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

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

Cepat:

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.


3
@PeterWarbo NSTimeInterval adalah jenis ganda dan didefinisikan sebagai detik - lihat developer.apple.com/library/mac/#documentation/Cocoa/Reference/…
Ben Lings

5
Anda dapat mencatat nilai ini dengan% f - NSLog ("executionTime =% f", executTime);
Tony

1
@Tony Anda lupa @,NSLog(@"executionTime = %f", executionTime);
John Riselvato

6
Saya baru saja membandingkan NSDatedan mach_absolute_time()pada level sekitar 30 ms. 27 vs 29, 36 vs 39, 43 vs 45. NSDatelebih mudah digunakan untuk saya dan hasilnya cukup mirip untuk tidak repot mach_absolute_time().
raja nevan

5
Apa pun yang didasarkan pada NSDate tidak aman untuk mengukur waktu yang berlalu karena waktu dapat melompat, bahkan mundur. Cara yang jauh lebih aman adalah menggunakan mach_absolute_time, seperti yang ditunjukkan dalam banyak jawaban lain di sini. Yang ini harus diturunkan karena menjadi contoh yang buruk. Lihat juga jawaban terkait yang menjelaskan semua ini dengan lebih terperinci: stackoverflow.com/a/30363702/43615
Thomas Tempelmann

252

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;

13
Ha ha. Saya suka itu!
bobmoff

5
Apa yang membuat ini sangat baik, adalah tik-tok adalah frase yang mengesankan sehingga penebangan hampir tidak memerlukan pemikiran.
John Riselvato

30
#define TOCK NSLog(@"%s Time: %f", __func__, -[startTime timeIntervalSinceNow])membuat jawaban ini juga mengembalikan fungsi timer digunakan. Saya menemukan ini berguna jika saya menggunakan TICK TOCK untuk mengatur waktu beberapa fungsi.
golmschenk

3
Ide bagus @golmschenk! Anda juga dapat melihat __PRETTY_FUNCTION__dan __LINE__jika Anda menginginkan informasi lebih rinci.
Ron

50

Untuk pengaturan waktu halus pada OS X, Anda harus menggunakan yang mach_absolute_time( )dinyatakan 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 membuat profil aplikasi Anda berjalan menggunakan alat seperti Shark. Ini tidak akan memberi Anda informasi waktu yang tepat, tetapi akan memberi tahu Anda berapa persen waktu aplikasi dihabiskan di mana, yang seringkali lebih bermanfaat (tetapi tidak selalu).


1
Mencoba membuatnya berfungsi di Swift ... ada saran?
zumzum

1
"Seseorang tidak hanya ... pindah ke Swift" - Ned Stark
stonedauwg

@zumzum Lihat jawaban saya untuk contoh melakukan ini di Swift.
jbg

23

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

Tidak seperti NSDateatau CFAbsoluteTimeGetCurrent()offset, mach_absolute_time()dan CACurrentMediaTime()didasarkan pada jam host internal, ukuran monatomik yang tepat, dan tidak mengalami perubahan dalam referensi waktu eksternal, seperti yang disebabkan oleh zona waktu, penghematan siang hari, atau detik kabisat.


ObjC

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

Cepat

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

3
Saya pikir jawaban ini layak mendapat lebih banyak upvotes. Ini jauh lebih baik daripada menggunakan NSDate.
Rata

12

Di Swift, saya menggunakan:

Di Macros.swift 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

Ini seharusnya \(-startTime.timeIntervalSinceNow)(perhatikan yang negatif)
Snowman

9

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 tentang 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 tulisan saya untuk lebih banyak atau unduh di sini: MMStopwatch.zip


7

Saya menggunakan makro berdasarkan solusi Ron .

#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


Jawaban Anda tidak jauh berbeda dari jawaban Ron dan saya juga gagal melihat dengan cara apa lebih baik?
Trilarion

2
Anda tidak dapat menggunakan solusi @ Ron dalam satu konteks dua kali. Ini adalah alasan utama makro ini.
Sergey Teryokhin

4

Saya menggunakan implementasi kelas yang sangat minimal, satu halaman yang 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:

  • telepon saja [DBGStopwatch start:@"slow-operation"];di awal
  • dan kemudian [DBGStopwatch stop:@"slow-operation"];setelah selesai, untuk mendapatkan waktu

3

Anda bisa mendapatkan pengaturan waktu yang sangat 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 stopWatchmetode statis yang mengembalikan objek autoreleased.

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

Contoh Dalam Fungsi ( Pengaturan waktu eksekusi)

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

   ... do stuff

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

"Akurasi hanya detik" Anda salah. Sementara seluruh bagian dari NSTimeInterval adalah detik, itu adalah ganda.
Steven Fisher

3

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

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
CLOCKS_PER_SEC pada iPhone adalah nilai yang sangat tidak akurat.
mxcl

1
Senang mendengarnya. Saya akan menggunakan jawaban Matius jika saya harus melakukan ini sekarang.
David Kanarek

2

Contoh pengaturan waktu berbutir halus mach_absolute_time()dalam 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

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 mengetahui 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 N detik.
Anda mengasumsikan Anda dapat mempercepatnya. Satu-satunya cara Anda dapat melakukannya adalah dengan membuatnya tidak melakukan sesuatu yang dilakukannya pada waktu itu, akuntansi untuk m detik.
Anda awalnya tidak tahu benda apa itu. Anda bisa menebak, seperti yang dilakukan oleh 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 hal 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 persis apa yang harus diperbaiki.
Jika Anda juga ingin tahu persis 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? Itu menemukan, bukan mengukur . Kebanyakan profiling didasarkan pada pengukuran setepat mungkin berapa banyak waktu yang diambil, seolah-olah itu penting, dan menggerakkan tangan masalah mengidentifikasi apa yang perlu diperbaiki. Profil tidak menemukan setiap masalah, tetapi metode ini memang menemukan setiap masalah, dan masalah yang menurut Anda tidak menyakiti Anda.


0

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 dokumen Apple : Pernyataan penundaan digunakan untuk mengeksekusi kode tepat sebelum mentransfer kontrol program di luar ruang lingkup di mana pernyataan penundaan muncul.

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


0

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 mencakup 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.


-1

Karena Anda ingin mengoptimalkan waktu bergerak dari satu halaman ke halaman lain di UIWebView, bukankah itu berarti Anda benar-benar ingin mengoptimalkan Javascript yang digunakan dalam memuat halaman-halaman ini?

Untuk itu, saya akan melihat profiler WebKit seperti yang dibicarakan di sini:

http://www.alertdebugging.com/2009/04/29/building-a-better-javascript-profiler-with-webkit/

Pendekatan lain adalah memulai pada level tinggi, dan pikirkan bagaimana Anda dapat mendesain halaman web yang dimaksud untuk meminimalkan waktu pemuatan menggunakan pemuatan halaman gaya AJAX alih-alih menyegarkan seluruh tampilan web setiap kali.


-1
struct TIME {

    static var ti = mach_timebase_info()
    static var k: Double = 1
    static var mach_stamp: Double {

        if ti.denom == 0 {
            mach_timebase_info(&ti)
            k = Double(ti.numer) / Double(ti.denom) * 1e-6
        }
        return Double(mach_absolute_time()) * k
    }
    static var stamp: Double { return NSDate.timeIntervalSinceReferenceDate() * 1000 }
}

do {
    let mach_start = TIME.mach_stamp
    usleep(200000)
    let mach_diff = TIME.mach_stamp - mach_start

    let start = TIME.stamp
    usleep(200000)
    let diff = TIME.stamp - start

    print(mach_diff, diff)
}

-1

Inilah solusi Swift 3 untuk membagi dua kode di mana saja untuk menemukan proses yang berjalan lama.

var increment: Int = 0

var incrementTime = NSDate()

struct Instrumentation {
    var title: String
    var point: Int
    var elapsedTime: Double

    init(_ title: String, _ point: Int, _ elapsedTime: Double) {
        self.title = title
        self.point = point
        self.elapsedTime = elapsedTime
    }
}

var elapsedTimes = [Instrumentation]()

func instrument(_ title: String) {
    increment += 1
    let incrementedTime = -incrementTime.timeIntervalSinceNow
    let newPoint = Instrumentation(title, increment, incrementedTime)
    elapsedTimes.append(newPoint)
    incrementTime = NSDate()
}

Penggunaan: -

instrument("View Did Appear")

print("ELAPSED TIMES \(elapsedTimes)")

Output sampel: -

WAKTU YANG DIKILANGI [MyApp.SomeViewController.Instrumentation (judul: "Start View Did Load", titik: 1, berlaluTime: 0,040504038333892822), MyApp.SomeViewController.Instrumentation (judul: "Selesai Menambahkan SubViews", poin: 2, elapsedTime: 0,0105955050505050 MyApp.SomeViewController.Instrumentation (judul: "View Did Appear", poin: 3, elapsedTime: 0.56564098596572876)]


-1

banyak jawaban yang aneh dan tidak benar-benar memberikan hasil dalam milidetik (tetapi dalam detik atau apa pun):

di sini apa yang saya gunakan untuk mendapatkan MS (MILLISECONDS):

Cepat:

let startTime = NSDate().timeIntervalSince1970 * 1000

// your Swift code

let endTimeMinusStartTime = NSDate().timeIntervalSince1970 * 1000 - startTime
print("time code execution \(endTimeMinStartTime) ms")

Tujuan-C:

double startTime = [[NSDate date] timeIntervalSince1970] * 1000.0;

// your Objective-C code

double endTimeMinusStartTime = [[NSDate date] timeIntervalSince1970] * 1000.0 - startTime;
printf("time code execution %f ms\n", endTimeMinusStartTime );

-1

Untuk Swift 4, tambahkan sebagai Delegasi ke kelas Anda:

public protocol TimingDelegate: class {
    var _TICK: Date?{ get set }
}

extension TimingDelegate {
    var TICK: Date {
        _TICK = Date()
        return(_TICK)!
     }

    func TOCK(message: String)  {

        if (_TICK == nil){
            print("Call 'TICK' first!")
        }

        if (message == ""){
            print("\(Date().timeIntervalSince(_TICK!))")
        }
        else{
            print("\(message): \(Date().timeIntervalSince(_TICK!))")
        }
    }
}

Tambahkan ke kelas kami:

class MyViewcontroller: UIViewController, TimingDelegate

Kemudian tambahkan ke kelas Anda:

var _TICK: Date?

Ketika Anda ingin mengatur waktu sesuatu, mulailah dengan:

TICK

Dan diakhiri dengan:

TOCK("Timing the XXX routine")

Apakah Anda membaca jawaban dan komentarnya? Jangan gunakan Date untuk ini!
matt
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.