是否有一种方法可以确定一个方法需要执行多少时间(以毫秒为单位)?


当前回答

对于OS X上的细粒度计时,您应该使用在<mach/mach_time.h>中声明的mach_absolute_time():

#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;

当然,关于细粒度度量的通常警告也适用;您可能最好多次调用测试中的例程,并求平均值/取最小值/一些其他形式的处理。

此外,请注意,您可能会发现使用Shark等工具对应用程序运行进行概要分析更有用。这不会为您提供确切的时间信息,但它会告诉您应用程序的时间在哪里花费了多少百分比,这通常更有用(但并不总是如此)。

其他回答

许多答案很奇怪,并没有真正以毫秒为单位给出结果(而是以秒或其他单位):

这里是我用来获得MS(毫秒):

迅速:

let startTime = NSDate().timeIntervalSince1970 * 1000

// your Swift code

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

objective - 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 );

我用这个:

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

但我不确定iPhone上的CLOCKS_PER_SEC。你还是别打了吧。

你可以得到很好的时间(秒。部分秒)使用这个StopWatch类。它使用了iPhone的高精度计时器。使用NSDate只能获得秒级精度。这个版本是专门为自动发布和objective-c设计的。如果需要的话,我也有一个c++版本。你可以在这里找到c++版本。

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

该类有一个返回自动释放对象的静态stopWatch方法。

调用start后,使用seconds方法获取运行时间。再次调用start来重新启动它。或者停下来停下来。在调用stop后,您仍然可以随时读取时间(调用秒数)。

函数中的示例(执行的定时调用)

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

   ... do stuff

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

我在我的utils库中使用这个(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.")
    }
}

…然后调用如下方法:

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

…运行后在控制台中看起来是这样的:

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

虽然不像上面的TICK/TOCK那样简洁,但它足以清楚地看到它在做什么,并自动包括正在计时的内容(通过文件、方法开头的行和函数名)。显然,如果我想要更多的细节(例如,如果我不只是计时一个方法调用,因为是通常的情况下,而是在该方法内计时块),我可以在PrintTimer init上添加“name="Foo""参数来命名它除了默认值之外的东西。

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