The [`file_scan_directory()`][1] is a recursive function which all files that match for a given directory. It's uses [`is_dir()`][2] and [`opendir()`][3] PHP calls which may be most time expensive in terms of I/O system calls. Simple Drupal bootstrap (e.g. `time drush ev ""`) may call `file_scan_directory` over few thousands times (depending on complexity of your Drupal folder hierarchy, e.g. number of modules and its folders).

In my case I had ~1500 calls to `file_scan_directory` (24 seconds in total consisting 2 calls from [`drupal_system_listing`][4] in `common.inc`, then the other calls were split by recursive calls to `file_scan_directory` it-self.

In order to improve the performance on I/O calls, you need to implement the file caching. This can be achieved by installing and enabling OPCache (`opcache.enable=1`) and tweak its settings (see: [How to use PHP OPCache?][5]). Using memory-based caching such as memcached/redis is also advised.

When using command-line interface (such as `drush`), you should also enable `opcache.enable_cli=1`.

After the change you can check the more consuming syscalls using  some available debuggers.

E.g.

- On Linux using `strace` (hit <kbd>Ctrl</kbd>-<kbd>C</kbd> to finish):

        sudo strace -c -fp $(pgrep -n php)

- On Unix using `dtrace` (using [PHP's DTrace static probes][6]), e.g.

        sudo dtrace -n 'inline string NAME = "php"; syscall:::entry /(NAME == strstr(NAME, execname)) || (execname == strstr(execname, NAME))/ { @num[probefunc] = count(); }'


  [1]: https://api.drupal.org/api/drupal/includes%21file.inc/function/file_scan_directory/7
  [2]: http://php.net/is_dir
  [3]: http://php.net/opendir
  [4]: https://api.drupal.org/api/drupal/includes%21common.inc/function/drupal_system_listing/7
  [5]: http://stackoverflow.com/q/17224798/55075
  [6]: http://php.net/manual/en/features.dtrace.dtrace.php