Doc #61168 [Com]: fwrite() has no buffering

From: Date: Mon, 22 Apr 2013 01:02:52 +0000
Subject: Doc #61168 [Com]: fwrite() has no buffering
References: 1  Groups: php.doc.bugs 
Request: Send a blank email to doc-bugs+get-9754@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=61168&edit=1 ID: 61168 Comment by: tstarling@php.net Reported by: tstarling@php.net Summary: fwrite() has no buffering Status: Open Type: Documentation Problem Package: Streams related Operating System: Linux PHP Version: 5.4.0RC8 Block user comment: N Private report: N New Comment: Still not even a documentation change? It's been more than a year, and I can't imagine it being particularly complex to edit a single sentence in the manual. Previous Comments: ------------------------------------------------------------------------ [2012-02-23 14:49:03] cataphract@php.net Perhaps this change in plain_wrapper.c would be a good idea: @@ -583,7 +583,13 @@ case PHP_STREAM_OPTION_WRITE_BUFFER: if (data->file == NULL) { - return -1; + char fixed_mode[5]; + php_stream_mode_sanitize_fdopen_fopencookie(stream, fixed_mode); + data->file = fdopen(data->fd, fixed_mode); + if (data->file == NULL) { + return -1; + } + data->fd = -1; } if (ptrparam) I'll have to think a bit more about the implications. ------------------------------------------------------------------------ [2012-02-23 10:32:05] cataphract@php.net You're not checking the return value of stream_set_write_buffer. If you were, you'd have noticed it returns -1 indicating failure. PHP does not have buffering for writes as it does for reads. In fact, it has the opposite: it breaks the data to write in chunk_size bits (see the undocumented stream_set_chunk_size in PHP 5.4). Therefore, streams that want to provide write buffering must do so themselves; PHP merely provides a way to configure the write buffering. In the case of plain files, write buffering is supported, but only for stdio files, not plain file descriptors. The stream by default doesn't use stdio (to avoid duplication of read buffers for instance). Extensions can open a FILE* and pass it to php_stream_fopen_from_file(), but it seems that this won't suffice because PHP will still use low-level I/O on the file descriptor returned by fileno(), so you'd have to violate some abstractions and zero the fd field in the php_stdio_stream_data structure (stored in stream->abstract) to force stdio to be used. This should be revisited. In any case, the documentation is wrong. I'm changing this to a documentation problem for the time being. ------------------------------------------------------------------------ [2012-02-23 06:16:09] tstarling@php.net Description: ------------ The stream_set_write_buffer() manual entry indicates that fwrite() buffers its output. This is incorrect. For regular files, no buffering is ever done, each fwrite() call leads to a syscall. This is a performance issue, especially for extensions like the CDB handler in DBA. I have a real-world script that uses almost as much system CPU as user CPU, because each dba_insert() call leads to multiple syscalls. Test script: --------------- $f = fopen( '/tmp/blah', 'w' ); stream_set_write_buffer( $f, 8192 ); for ( $i = 0; $i < 10; $i++ ) { fwrite( $f, 'x' ); } fclose( $f ); Expected result: ---------------- strace php write-tight-loop.php ... write(3, "xxxxxxxxxx", 1) = 10 ... Actual result: -------------- write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 write(3, "x", 1) = 1 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=61168&edit=1

« previous php.doc.bugs (#9754) next »