Jump to content

PHP based workflow: first execution after some time is slow

Recommended Posts

Hi All,


I've noticed with my Spotify Mini Player workflow (PHP based) (http://www.alfredforum.com/topic/1892-spotify-mini-player-version-375-now-update-library-and-playlists-from-workflow/) that the first execution after some inactivity time is quite slow compared to next consecutive ones.


So i tried to create a very basic workflow to show you this behavior. Grab it there: http://d.pr/f/2BKC


Launch it with "ctrl+ENTER", it just displays a result with execution time.


The first execution after some time, I get above 0.320 s whereas next ones are around 0.120 s


If I execute it outside of Alfred, I don't get this behavior and I constantly get around 0.120 s


Any idea what could cause this?



Link to comment
  • 7 months later...

I finally had some time to investigate this and I believe this is due to use of exec(). I've read here http://stackoverflow.com/questions/14277910/php-exec-performance: "When you call exec php does not create a thread, It creats a new child process. Creating a new process is big overhead."


So I've done a pull request to David's workflow (https://github.com/jdfwarrior/Workflows/pull/9) to avoid as much as possible the use of exec() in Workflows constructor.

The best improvement is when you set bundleid when creating Workflows:

$w = new Workflows('com.repro.slow.problem');

instead of

$w = new Workflows();

I've created a workflow to show the improvements, get it here https://cloudup.com/cBiUwDy104X



Link to comment

Starting a subprocess is very slow (relatively speaking). It can't be avoided in bash, zsh, etc., but with a "real" language like PHP/Python/Ruby, you should try to use native code and avoid starting subprocesses wherever possible. It's almost always much faster.
However, the reason your workflow runs faster when it's been recently run than when it hasn't been run in a while is probably down to the fact that the libraries loaded by PHP (or any other language/app) are still cached in memory if you've recently run the workflow.
You may have noticed that if your Mac has been running for a while, the RAM more or less always "full". That's because the system doesn't automatically remove everything from RAM that isn't in use any more, but keeps it around in case some other app might use the same library. It only gets removed from memory when that memory is needed by something that is currently running.
So, (most of) the libraries loaded by your workflow are still in RAM if you run the workflow again soon after, but if it's been a while, the libraries have been removed, so other apps can use the RAM, and they need to be loaded back from disk into RAM (and disks are several orders of magnitude slower than RAM).

Edited by deanishe
Link to comment

Thanks for these explanations!


I've removed all calls to exec() in the performance path of my workflow (Spotify Mini Player http://www.alfredforum.com/topic/1892-spotify-mini-player-version-15/) which were in the Workflows.php from David.

I've only one remaining but I think I have no choice because I need to call an applescript to get current playing song from Spotify, and I can't see a way to do that without call to exec().


Anyway even with this, it takes now only between 100 and 250 ms for my workflow to return all results and I'm very happy with that! :)

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Create New...