메서드의 실행 시간을 밀리초 단위로 정확하게 기록하는 방법
메서드를 실행하는 데 필요한 시간(밀리초)을 결정할 수 있는 방법이 있습니까?
NSDate *methodStart = [NSDate date];
/* ... Do whatever you need to do ... */
NSDate *methodFinish = [NSDate date];
NSTimeInterval executionTime = [methodFinish timeIntervalSinceDate:methodStart];
NSLog(@"executionTime = %f", executionTime);
신속:
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)")
사용하기 쉽고, 정밀도가 밀리초 미만입니다.
사용하는 매크로는 다음과 같습니다.
#define TICK NSDate *startTime = [NSDate date]
#define TOCK NSLog(@"Time: %f", -[startTime timeIntervalSinceNow])
다음과 같이 사용합니다.
TICK;
/* ... Do Some Work Here ... */
TOCK;
X 의 하려면 , X 를 사용해 .mach_absolute_time( )
되어 있다<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;
물론 세밀한 측정에 대한 일반적인 주의사항이 적용됩니다. 테스트 대상 루틴을 여러 번 호출하고 최소/기타 형태의 처리를 평균화/수행하는 것이 가장 좋습니다.
또한 Shark와 같은 도구를 사용하여 실행 중인 응용 프로그램을 프로파일링하는 것이 더 유용할 수 있습니다.이것은 정확한 타이밍 정보를 제공하지는 않지만, 애플리케이션 시간의 몇 퍼센트가 어디에 소비되고 있는지를 알려줍니다.이것은 많은 경우(항상 도움이 되는 것은 아닙니다).
.mach_absolute_time()
– 은 – –CACurrentMediaTime()
CoreAnimation
를 참조할 수 있습니다.
★★★★★★★★★★★★★★★와 달리
NSDate
★★★★★★★★★★★★★★★★★」CFAbsoluteTimeGetCurrent()
"오프셋",mach_absolute_time()
★★★★★★★★★★★★★★★★★」CACurrentMediaTime()
는, 내부 호스트 클럭(정밀하고 단원자적인 측정치)에 근거하고 있습니다.시간대, 여름 시간, 윤초 등에 의한 외부 시간 기준의 변경은 없습니다.
ObjC
#import <QuartzCore/QuartzCore.h>
CFTimeInterval startTime = CACurrentMediaTime();
// Do your stuff here
CFTimeInterval endTime = CACurrentMediaTime();
NSLog(@"Total Runtime: %g s", endTime - startTime);
재빠르다
import QuartzCore
let startTime = CACurrentMediaTime()
// Do your stuff here
let endTime = CACurrentMediaTime()
print("Total Runtime: \(endTime - startTime) s")
Swift에서는 다음을 사용하고 있습니다.
방금 추가한 Macros.swift
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)")
}
이제 아무데서나 전화할 수 있게 되었다
TICK()
// your code to be tracked
TOCK()
Swift 5.0
var startTime = NSDate()
func TICK(){ startTime = NSDate() }
func TOCK(function: String = #function, file: String = #file, line: Int = #line){
print("\(function) Time: \(startTime.timeIntervalSinceNow)\nLine:\(line) File: \(file)")
}
- 이 코드는 론이 스위프트로 변환한 코드를 기반으로 하고 있고, 그는 크레딧을 가지고 있습니다.
- 글로벌 레벨의 시작일을 사용하고 있습니다.개선할 수 있는 제안이 있으면 언제든지 환영입니다.
이게 오래된 거라는 건 알지만, 나 자신도 그걸 다시 지나쳐버린 걸 발견했기 때문에, 여기에 나만의 선택지를 제출하려고 했어요.
이에 대한 블로그 투고를 확인하는 것이 가장 좋습니다.Objective-C에서의 타이밍 설정: 스톱워치
기본적으로 매우 기본적인 방법으로 시청을 중지하지만 다음 작업만 수행하면 되도록 캡슐화된 클래스를 작성했습니다.
[MMStopwatchARC start:@"My Timer"];
// your work here ...
[MMStopwatchARC stop:@"My Timer"];
결과적으로 다음과 같은 결과가 됩니다.
MyApp[4090:15203] -> Stopwatch: [My Timer] runtime: [0.029]
로그에서...
다시 한번 제 투고를 확인하시거나 MMStopwatch.zip에서 다운로드 해 주세요.
론의 솔루션을 기반으로 매크로를 사용합니다.
#define TICK(XXX) NSDate *XXX = [NSDate date]
#define TOCK(XXX) NSLog(@"%s: %f", #XXX, -[XXX timeIntervalSinceNow])
코드 행의 경우:
TICK(TIME1);
/// do job here
TOCK(TIME1);
콘솔에는 다음과 같은 내용이 표시됩니다.시간 1: 0.096618
이 블로그 투고의 코드에 착안한, 1 페이지 클래스의 실장을 최소한으로 억제하고 있습니다.
#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
사용법은 매우 간단합니다.
- 해 주세요.
[DBGStopwatch start:@"slow-operation"];
- 다음에 또 한 번.
[DBGStopwatch stop:@"slow-operation"];
후 하기 위해
다음 코드를 사용합니다.
#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;
}
이 StopWatch 클래스를 사용하면 매우 정확한 타이밍(초 단위)을 얻을 수 있습니다.iPhone의 고정밀 타이머를 사용합니다.NSDate를 사용하면 두 번째 정확도만 얻을 수 있습니다.이 버전은 auto-rese 및 objective-c 전용으로 설계되었습니다.필요한 경우 c++ 버전도 있습니다.c++ 버전은 여기서 찾을 수 있습니다.
스톱워치
#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
스톱워치
#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
수 (콜을 해 주세요).seconds
후는 언제든지 사용할 수 있습니다stop
.
함수의 예(실행 콜의 타이밍 설정)
-(void)SomeFunc
{
StopWatch* stopWatch = [StopWatch stopWatch];
[stopWatch Start];
... do stuff
[stopWatch StopWithContext:[NSString stringWithFormat:@"Created %d Records",[records count]]];
}
「」를 사용한 의 예.mach_absolute_time()
4 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")
}
네, 만약 여러분의 목표가 그것을 더 빨리 하기 위해 고칠 수 있는 것을 찾는 것이라면, 그것은 조금 다른 목표입니다.함수에 걸리는 시간을 측정하는 것은 자신이 한 일이 어떤 영향을 미쳤는지 알아내는 좋은 방법이지만, 무엇을 해야 하는지 알아내기 위해서는 다른 기술이 필요합니다.이것이 제가 추천하는 것이며, 아이폰에서도 할 수 있다는 것을 알고 있습니다.
편집: 리뷰어들이 답을 자세히 설명하라고 해서 간략하게 말하려고 합니다.
프로그램 전체에 시간이 걸려 번거롭습니다.그게 N초라고 가정해봐
속도를 높일 수 있을 거라 생각하시는군요이 작업을 수행하려면 m초 동안 수행하던 작업을 수행하지 않도록 하는 방법밖에 없습니다.
수 있지만 수 있습니다.모든 프로그래머가 그렇듯이 추측할 수 있지만, 다른 것일 수도 있습니다.어떤 것이든 찾을 수 있는 방법은 다음과 같습니다.
그것이 무엇이든 시간의 분수 m/N을 설명하기 때문에 랜덤으로 일시정지하면 그 동작에서 포착될 확률이 m/N이 됩니다.물론 다른 일을 하고 있을 수도 있지만, 잠시 멈추고 어떻게 하는지 보세요.
제시하다똑같은 짓을 또 하면 더 의심받을 수 있어요.
10번, 아니 20번.특정 작업을 여러 번 일시정지할 때(어떻게 설명하든 상관없습니다) 제거할 수 있는 경우 두 가지를 알 수 있습니다.시간이 얼마나 걸리는지는 대충 알겠지만, 무엇을 수정해야 하는지 정확히 알고 있습니다.
또한 얼마나 많은 시간을 절약할 수 있는지 정확히 알고 싶다면 간단합니다.그 전에 측정하여 고정하고 그 후에 측정한다.정말 실망스러우면 그 수정은 철회하세요.
이게 측정이랑 뭐가 다른지 알겠니?측정하는 게 아니라 찾는 거야대부분의 프로파일링은 시간이 얼마나 걸리는지를 가능한 한 정확하게 측정하는 것에 기초하고 있습니다.그리고 수정해야 할 것을 특정하는 문제에 손을 흔듭니다.프로파일링은 모든 문제를 찾아내는 것은 아니지만, 이 방법은 모든 문제를 찾아냅니다.그리고 당신에게 상처를 주지 않는 것은 바로 그 문제입니다.
나는 이것을 사용한다.
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);
하지만 아이폰의 CLOCKS_PER_SEC에 대해서는 잘 모르겠습니다.그냥 꺼두는 게 좋을 것 같아
여기 스위프트에서는 delfer 키워드를 사용하여 이를 수행하는 다른 방법이 있습니다.
func methodName() {
let methodStart = Date()
defer {
let executionTime = Date().timeIntervalSince(methodStart)
print("Execution time: \(executionTime)")
}
// do your stuff here
}
Apple 문서에서: defer 문은 defer 문이 나타나는 범위 밖에서 프로그램 제어를 전송하기 직전에 코드를 실행하기 위해 사용됩니다.
이는 try/finally 블록과 유사하며 관련 코드를 그룹화할 수 있다는 장점이 있습니다.
유틸리티 라이브러리(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" 파라미터를 추가하여 기본값 이외의 이름을 붙일 수 있습니다.
UI WebView에서 한 페이지에서 다른 페이지로 이동하는 시간을 최적화하고 싶기 때문에 이러한 페이지를 로드하는 데 사용되는 Javascript를 최적화하려는 것은 아닐까요?
이를 위해 여기서 언급한 것과 같은 WebKit 프로파일러를 살펴보겠습니다.
http://www.alertdebugging.com/2009/04/29/building-a-better-javascript-profiler-with-webkit/
또 다른 접근법은 높은 수준에서 시작하여 매번 전체 웹 뷰를 새로 고치는 대신 AJAX 스타일의 페이지 로딩을 사용하여 해당 웹 페이지를 최소화할 수 있는 방법을 생각해 보십시오.
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)
}
여기 Swift 3 솔루션이 있습니다.어디서나 코드를 이등분하여 장기 실행 프로세스를 찾을 수 있습니다.
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()
}
사용방법: -
instrument("View Did Appear")
print("ELAPSED TIMES \(elapsedTimes)")
출력 예:-
경과시간 [My App]SomeView컨트롤러계측(제목: "시작 보기 로드", 포인트: 1, 경과됨시간: 0.0404038333892822), MyApp.SomeView컨트롤러Instrumentation(제목: "서브뷰 추가 완료", 포인트: 2, 경과됨)시간: 0.010585010051727295), MyApp.SomeView컨트롤러Instrumentation(제목: "View Did Affected시간: 0.56564098596572876)]
많은 답변이 이상하고 밀리초 단위로 결과를 얻을 수 없습니다(단, 초 단위 또는 기타 단위).
MS를 취득하기 위해서 사용하는 것(MILLISEConds):
신속:
let startTime = NSDate().timeIntervalSince1970 * 1000
// your Swift code
let endTimeMinusStartTime = NSDate().timeIntervalSince1970 * 1000 - startTime
print("time code execution \(endTimeMinStartTime) ms")
목표-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 );
Swift 4의 경우 클래스에 대리인으로 추가합니다.
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!))")
}
}
}
클래스에 추가:
class MyViewcontroller: UIViewController, TimingDelegate
그런 다음 클래스에 추가합니다.
var _TICK: Date?
시간을 재려면 다음 항목부터 시작하십시오.
TICK
마지막은 다음과 같습니다.
TOCK("Timing the XXX routine")
언급URL : https://stackoverflow.com/questions/2129794/how-to-log-a-methods-execution-time-exactly-in-milliseconds
'programing' 카테고리의 다른 글
iPhone Simulator에 이미지 또는 비디오 추가 (0) | 2023.04.17 |
---|---|
Code에서 바인딩을 설정하는 방법 (0) | 2023.04.17 |
개발 브랜치를 마스터와 병합 (0) | 2023.04.17 |
WPF에서 라벨 텍스트를 중앙에 배치하려면 어떻게 해야 합니까? (0) | 2023.04.17 |
panda.read_excel에서 헤더마다 행 범위 건너뛰기 (0) | 2023.04.17 |