I built an Electron application using electron-packager
on macOS. In its simplest form, the app consists of one button which, upon press, opens an external program.
child_process.execFile('open', ['-a', 'Terminal', path])
I am observing a 50x slowdown of the function call above when running the application detached from a terminal (for example started using Spotlight) compared to running it from the terminal
hello.app/Contents/MacOS/hello
Started from Terminal + press button => External app opens in 100 ms
Started from Spotlight + press button => External app opens in 5 seconds
Any hints of what could be the issue?
| Package | Version |
| ----------------- | -------- |
| npm | 6.4.1 |
| node | v10.15.2 |
| electron | 4.1.4 |
| electron-packager | 13.1.1 |
Edit: Issue persists for electron 6.0.9 and electron-packager 14.0.5
You may have better luck using spawn rather than execFile: it may be more appropriate since you're running the open
command, and not directly executing a specific file (to launch an application, for instance).
child_process.spawn('open', ['-a', 'Terminal', path]);
You can use spawn
to warm up a process, run bash or some other terminal in it, and type commands into it.
I wrote a ShellService
you can have a look.
It takes about 300ms to execute a normal open command using exec
on my Mac, but it only takes 1ms in ShellService
. So I think the time is spent on creating a new process.
export default class ShellService {
// Use bash on mac and linux.
// I don't know what to use for windows, temporarily write powershell.
private shell = isWindows() ? spawn('powershell') : spawn('bash');
constructor() {
this.shell.addListener('exit', (code) => {
console.error(`[shell] shell process exit with code:${code}`);
if (!this.shell.stdin.writable) {
this.shell = spawn('bash');
}
});
}
cmdQueue: string[] = [];
isRunning = false;
/**
* run shell cmd in bash
* @param cmd
*/
public exeCmd(cmd: string) {
this.cmdQueue.push(cmd);
this.tryExeCmd();
}
private tryExeCmd() {
if (this.isRunning || this.cmdQueue.length === 0) {
return;
}
this.isRunning = true;
const cmd = this.cmdQueue.shift();
const startTime = new Date().getTime();
// Timeout after one second
const timeoutTimer = setTimeout(() => {
this.isRunning = false;
cubeReport({
e: CubeEventId.ShellServiceTimeout,
f: cmd,
});
console.warn(`Run cmd: ${cmd} timeout.`);
this.shell.kill();
this.shell = spawn('bash');
this.tryExeCmd();
}, 1000);
this.shell.stdin.write(`${cmd}\n`, (err) => {
this.isRunning = false;
clearTimeout(timeoutTimer);
console.log(`Run cmd: ${cmd} cost: ${new Date().getTime() - startTime}`);
if (err) {
console.error(`Run cmd: ${cmd} err: ${err}`);
}
this.tryExeCmd();
});
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With