kareman / SwiftShell

A Swift framework for shell scripting.
https://kareman.github.io/SwiftShell
MIT License
1.03k stars 87 forks source link

`waitUntilExit` cause slow execution #101

Open leavez opened 3 years ago

leavez commented 3 years ago

I benchmark the duration of executing a simple process. On other languages (ruby, go, bash), the result is about 1ms, but on Swift, it takes about 60ms.

The test code is

let s = Date()
SwiftShell.run("/bin/cp")
print(Date().IntervalSince(s))

I also test with raw Process and get same result

let s2 = Date()
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/cp")
try process.run()
process.waitUntilExit()
print(Date().IntervalSince(s2))

After digging, I found the it may cause by the Process.waitUntilExit:

 "it polls the current run loop using NSDefaultRunLoopMode until the task completes"

https://developer.apple.com/documentation/foundation/nstask/1415808-waituntilexit

When changing it to terminationHandler, it's back to normal.

let s2 = Date()
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/cp")
process.terminationHandler = { t in
    print(2, Date().timeIntervalSince(s2))
}
try process.run()
process.waitUntilExit()
print(1, Date().timeIntervalSince(s2))

The output:

2 0.007783055305480957
1 0.06369709968566895
kareman commented 3 years ago

Nice finding. Any reimplementation of SwiftShell.run using terminationHandler is welcome :)