php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80695 Extremely slow PHP file access operations on all Windows OS's
Submitted: 2021-02-01 19:54 UTC Modified: 2021-02-03 15:25 UTC
Votes:1
Avg. Score:5.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:0 (0.0%)
Same OS:1 (100.0%)
From: info at futurion dot si Assigned: cmb (profile)
Status: Not a bug Package: *Directory/Filesystem functions
PHP Version: 7.4.14 OS: Windows (All platforms)
Private report: No CVE-ID: None
 [2021-02-01 19:54 UTC] info at futurion dot si
Description:
------------
I did some extensive tests on various PHP versions on windows and linux platforms. Long story short, it seems windows suffer big time from slow file-access with all PHP file-related functions. I used as a sample a simple PHP script, which is published here:

https://pastebin.com/VfLCgs3K

That script takes about 10x or more time on windows in comparison to linux. I tried all possible combinations (power profiles, opcache, safe mode, windows defender and firewall disable, wincache, etc.), but it doesn't matter, nothing helps. I also tried different windows versions, different web servers, also running that script in CLI is slow as well.

That above being said, would you be maybe kind enough to look into this issue, or maybe try running that same script at your side as well and maybe write something useful back. Is there actually any way to gain some "speed" on windows to be at least close to linux's performance? I really can't believe PHP on windows is so much slower than on linux.

Kind regards and thank you in advance for your answer.

Tomaz Kavcic.

Test script:
---------------
<?php
$microtime = microtime(true);
function displayCounter($txt){
    global $microtime;
echo "<p> {$txt}: ". round((microtime(true) - $microtime) * 1000,0) ."ms</p>";
 
    $microtime = microtime(true);
}
 
$file_prefix = __DIR__ . '/file';
 
for($i= 1; $i < 1000; $i++){
    file_put_contents($file_prefix . $i, '');
}
displayCounter('File Creation');
 
for($i= 1; $i < 1000; $i++){
    file_exists($file_prefix . $i);
}
displayCounter('file_exists');
 
clearstatcache();
 
for($i= 1; $i < 1000; $i++){
    file_exists($file_prefix . $i);
}
displayCounter('file_exists (after cache clear)');
 
 
for($i= 1; $i < 1000; $i++){
    unlink($file_prefix . $i);
}
displayCounter('unlink');

Expected result:
----------------
Tested on Ubuntu Linux 20.04 (Apache 2)
-
File Creation: 33ms
file_exists: 4ms
file_exists (after cache clear): 4ms
unlink: 22ms

Teset on Ubuntu Linux 20.04 (PHP CLI)
-
File Creation: 20ms
file_exists: 2ms
file_exists (after cache clear): 2ms
unlink: 11ms

Actual result:
--------------
Tested on Windows 2019 Server (Also on other Windows OS's - similar results)
-
File Creation: 104ms
file_exists: 21ms
file_exists (after cache clear): 20ms
unlink: 62ms

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-01 19:57 UTC] beberlei@php.net
Just to clarify, the stat cache is only a *single* entry cache, storing the stat information of the last file that was accessed. So that explains why clearstatcache before/after example makes no difference.
 [2021-02-02 12:48 UTC] cmb@php.net
-Status: Open +Status: Not a bug -Assigned To: +Assigned To: cmb
 [2021-02-02 12:48 UTC] cmb@php.net
Generally, such performance comparisons are … difficult.
Obviously, there are huge architectural differences between
Windows and Linux; some of these can be influenced by the system
adminstrator, some cannot[1].  There is nothing to do about that
from the PHP side.  And PHP can't do anything about the rest of
the system (e.g. AV scanners, other background processes, amount
of free memory, etc.)

Then there is the issue that PHP is primarily developed for Linux,
and the Windows implementation tries to match the given POSIX
semantics as closely as possible.  Newer PHP versions have caught
up on that (especially PHP 7.4), and that may well slow down the
performance of file access in favor of improved compatibility with
the Linux implementation.

Then there are relevant differences between thread-safe (ZTS) and
non-thread-safe (NTS) builds, and also regarding some
configuration options (e.g. realpath_cache).

Now I'm a bit irritated that you've mentioned safe mode; this
"feature" is removed as of PHP 5.4.0.  Did you really tests such
old versions?

Then you mentioned that you have tested with different Webservers,
and your test results already acknowledge that performance is
considerable worse for Apache2 than CLI on the same system (Ubuntu
Linux 20.04).  So obviously it makes sense to focus on a certain
SAPI (CLI seems to be most appropriate).

Also, for this bug report to be actionable, at the very least we
would have to check the performance for any of the actively
supported PHP versions[2], and only something that could be
regarded as bug could be addressed for PHP 7.4/8.0; any potential
improvements would have to target the master branch (i.e. 8.1, but
there are no releases yet).

Furthermore, I suggest to use hrtime() instead of microtime() for
any benchmarks.

Anyhow, I have now run the modified script (using hrtime()) with
the official PHP 7.4.14 NTS x64 build[3] on Windows 10 2004, and
with a minimal PHP 7.4.14 NTS x64 build on a Debian 10.2
VirtualBox VM on the same machine.  I can confirm your findings,
but that is comparing apples and oranges.  If I run the test from
a mounted NTFS folder, I see roughly the same performance as with
the Windows builds.  So obviously, we're hitting the differences
mentioned in the first paragraph, which PHP can't solve.

If you notice performance regressions with the same kind of builds
on Windows, compared to earlier PHP versions, please open a new
ticket. For the given test script, the performance of 7.3.26 and
7.4.14 is roughly the same in my environment.

[1] <https://superuser.com/questions/1124472/why-is-linux-30x-faster-than-windows-10-in-copying-files>
[2] <https://www.php.net/supported-versions.php>
[3] <https://bugs.php.net/bug.php?id=80695>
 [2021-02-02 18:19 UTC] info at futurion dot si
Thank you for such informative answer! First of all, the "safe mode" I mentioned in my first question was related indeed to Windows Safe Mode which I tried booting into a few times to see performance differences.

Secondly, I'm actually quite a lousy programmer, so the script I posted was actually a work of someone else (found on serverfault) but it quite good showed the performance difference between two mentioned platforms (windows and linux), therefore I took it as a sample and the functions it uses are probably just a random file-access related functions, but the show the differences.

Also, I'm happy you were able to reproduce the same behaviour as me. I actually do exactly the same thing now, running script inside a VM on the same physical server gives way better results then on windows itself. It's evident there are some differences when using web browsers and running the same script but there's no big difference between the IIS or Apache on Windows, both perform well, but the issue is slow file system nehind that.

Now, my actual question is, is there anything at all that can be done to get similar or same speed of running file-related PHP tasks inside windows OS? You mentioned that you used mounted NTFS folder on linux as well and the performance was worse, so it's evident NTFS is a huge issue in this case. What would need to be done to avoid that issue on windows and get actually same or similar performance as linux? And of course, I also tested many revisions from php 5.6 to 7.4 and 8.x and it seems the performance is always similar or the same.

Lastly, what I actually need/want to do is run a few simpe PHP/mysql CMS apps on windows (I tested roundcube, wordpress, ojs, phpmaestro, etc.). These are all similar apps and they run blazingly fast on linux while on windows I see these huge TTFB times in chrome when clicking/loading a new pages. The times are 5x or more higher then on linux, so using these apps is sadly "slow". Interesting thing maybe is, I have hmailserver running on windows and then I installed roundcube on both windows and linux. On linux it's loading everythng really fast, even though the hmailserver and all mails are inside windows NTFS, while of course roundcube accessing that same hmailserver on windows is as slow as possible. So that makes me thinking that NTFS isn't that slow at all as it behaves ok if it's accessed from linux PHP, so probably the PHP operations on windows NTFS system are the real issue.

However, I probably don't have anything mroe to add, the only thing I'd like to know is if there's anything possible that can be done to make all these fine CMS's run fast on windows NTFS as well.

Kind regards and thank you again!
 [2021-02-03 15:25 UTC] cmb@php.net
> Now, my actual question is, is there anything at all that can be
> done to get similar or same speed of running file-related PHP
> tasks inside windows OS?

Like I said above, I don't think so.

> These are all similar apps and they run blazingly fast on linux
> while on windows I see these huge TTFB times in chrome when
> clicking/loading a new pages.

While file access performance *might* be the main cause of this, I
don't think it necessarily is.  While your test script clearly
shows bad performance on Windows, I don't think it is even
remotely typical to create/write/read many small files for a PHP
Web application.  It is hard to tell where the bottleneck(s)
actually is/are without thorough investigation of the individual
applications, but there are a few known issues on Windows:

1) Slow startup of the PHP process, which is greatly exacerbated
when a lot of extensions are loaded.  Presumably, we cannot do
anything to really improve that, since it is inherent to Windows
(again likely the slower file access, then of course ASLR).  This
is, however, not a real problem, *if* all PHP processes are
started in advance, to serve many Web requests.

2) Failure to attach to OPcache shared memory for individual PHP
processes.  A lot of work-arounds and mitigations have been
applied in the past, but a full solution is not possible (mainly
due to ASLR). So if a PHP process can't attach to OPcache shared
memory, it falls back to the file_cache (if configured), or even
slightly worse falls back to classic loading of PHP files.
Depending on the application at hand, that can greatly slow down
processing of the request.  I've seen differences of factor 10.

3) Persistent connections (to databases etc.)  These are usually
implemented as process globals, but at least for (F)CGI on
Windows, there are usually multiple PHP processes involved, so
reusing such connections is not as effective as one would hope
for.

These three issues are solved on Linux with FPM.  The idea has
been brought up to introduce a new SAPI on Windows, similar to FPM
but having worker threads instead of worker processes.  This would
likely solve the mentioned Windows issues, but would have the
disadvantage of a less stable and secure overall system.  Anyhow,
developing such a new SAPI would be a major effort …
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 13:01:31 2024 UTC