Skip to content

Instantly share code, notes, and snippets.

@NSEGeorge
Created November 3, 2018 14:21
Show Gist options
  • Save NSEGeorge/688a4a8eaaaec98f0e59507ca91724f5 to your computer and use it in GitHub Desktop.
Save NSEGeorge/688a4a8eaaaec98f0e59507ca91724f5 to your computer and use it in GitHub Desktop.
Swift implementation of function for measuring application launch time. Call it from start or end didFinishLaunchingWithOptions.
import UIKit
class LaunchTimeMeasurer {
private let pid = ProcessInfo().processIdentifier
private var currentTime = timeval(tv_sec: 0, tv_usec: 0)
private var bootTime = timeval()
private var size = MemoryLayout<kinfo_proc>.stride
private var mib: [Int32]
init() {
mib = [CTL_KERN, KERN_PROC, KERN_PROC_PID, pid]
}
func processLaunchTime() -> Double {
sysctl(&mib, u_int(mib.count), &bootTime, &size, nil, 0)
gettimeofday(&currentTime, nil)
return toSeconds(time: currentTime) - toSeconds(time: bootTime)
}
private func toSeconds(time: timeval) -> Double {
let microsecondsInSecond = 1000000.0
return Double(time.tv_sec) + Double(time.tv_usec) / microsecondsInSecond
}
}
@eschos24
Copy link

eschos24 commented May 12, 2020

I was able to figure out what was wrong, and it might help @RagulChandra too. sysctl takes a kinfo_proc, not a timeval. Using a timeval will still return the correct value, but causes memory corruption later on in your app's life cycle.

Here are the modifications that should be made to avoid memory corruption:

...
private var kp = kinfo_proc()  // kp instead of bootTime
...

func processLaunchTime() -> Double {
  sysctl(&mib, u_int(mib.count), &kp, &size, nil, 0)
  gettimeofday(&currentTime, nil)

  let bootTime = kp.kp_proc.p_un.__p_starttime  // this is a timeval struct

  return toSeconds(time: currentTime) - toSeconds(time: bootTime)
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment