php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #35090 file i/o is not buffered
Submitted: 2005-11-03 19:16 UTC Modified: 2010-08-12 18:32 UTC
From: askalski at gmail dot com Assigned:
Status: Not a bug Package: Filesystem function related
PHP Version: 5.3.3 OS: linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: askalski at gmail dot com
New email:
PHP Version: OS:

 

 [2005-11-03 19:16 UTC] askalski at gmail dot com
Description:
------------
The documentation for stream_set_write_buffer() says that fwrite()s are buffered at 8K by default.  In reality, it does not buffer at all.  Any attempt to call stream_set_write_buffer() on a regular file handle results in failure.


Reproduce code:
---------------
$fh = fopen("asdf", "w");

// write some data using the default buffering
for ($i = 0; $i < 5; $i++)
        fwrite($fh, "test");

// demonstrate that stream_set_write_buffer fails
$n = stream_set_write_buffer($fh, 8192);
if ($n != 0)
        echo "stream_set_write_buffer failed\n";

// write some more data to demonstrate the failure
for ($i = 0; $i < 5; $i++)
        fwrite($fh, "again");

fclose($fh);


Expected result:
----------------
PHP should buffer its I/O, and strace should log a single write().  stream_set_write_buffer() should not fail on regular files.


Actual result:
--------------
Output:

stream_set_write_buffer failed


Abridged strace output:

open("/tmp/php5-200511031730/asdf", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
fstat64(3, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
lseek(3, 0, SEEK_CUR)                   = 0
write(3, "test", 4)                     = 4
write(3, "test", 4)                     = 4
write(3, "test", 4)                     = 4
write(3, "test", 4)                     = 4
write(3, "test", 4)                     = 4
write(1, "stream_set_write_buffer failed\n", 31) = 31
write(3, "again", 5)                    = 5
write(3, "again", 5)                    = 5
write(3, "again", 5)                    = 5
write(3, "again", 5)                    = 5
write(3, "again", 5)                    = 5
close(3)                                = 0


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2005-11-03 21:29 UTC] derick@php.net
Can you please answer why this is not a bug Wez? I forgot the reason :)
 [2005-11-03 21:34 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

PHP does not do any buffering itself, instead it uses the system's file io buffering function to set the buffer. 
There is already a feature request open to enable in-php buffering.
 [2005-11-03 23:40 UTC] askalski at gmail dot com
> instead it uses the system's file io buffering function
> to set the buffer.

Assuming you're talking about setvbuf() and not kernel
level write-behind caching, this statement is false.

The file is opened by _php_stream_fopen():

    fd = open(realpath, open_flags, 0666);

(It is never subsequently wrapped with fdopen())

At this point, the stream is not buffered at all.

When I later call stream_set_write_buffer(), it hits
php_stdiop_set_option():

    case PHP_STREAM_OPTION_WRITE_BUFFER:
        if (data->file == NULL) {
            return -1;
        }
        /* setvbuf happens down here */

Because there is no FILE* handle (data->file), setvbuf()
is never called for the stream.

One of either the documentation (http://us3.php.net/stream_set_write_buffer)
or the PHP source is wrong.
 [2010-08-12 12:59 UTC] surfchen at gmail dot com
So we need to add a note on the documentation say that this function not supported 
with filesystem wrapper, right?
 [2010-08-12 18:32 UTC] askalski at gmail dot com
-PHP Version: 5CVS-2005-11-03 (snap) +PHP Version: 5.3.3
 [2010-08-12 18:32 UTC] askalski at gmail dot com
I guess that's one way to deal with it.  At least then it would be clear to PHP developers that each fwrite() makes a separate system call.

Even better would be for PHP to use the C stdio library for file i/o, and take advantage of the buffering it offers by default.  Even back in the 1970's when C was created, they had already figured out that buffered I/O was a good thing, and consequently built it into stdio...

(I'm surprised to see feedback on a bug ticket that was closed as "Bogus" almost five years ago.  Ultimately, this is pretty low on my list of "reasons PHP execution is so painfully slow"; it's just something I spotted when doing an strace to troubleshoot an unrelated issue.  That's why I never bothered to pursue it further.)
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Thu May 08 11:01:27 2025 UTC