Skip to content

Commit 5cbe5a5

Browse files
committedOct 30, 2019
Don't use chunking for stream writes
We're currently splitting up large writes into 8K size chunks, which adversely affects I/O performance in some cases. Splitting up writes doesn't make a lot of sense, as we already must have a backing buffer, so there is no memory/performance tradeoff to be made here. This change disables the write chunking at the stream layer, but retains the current retry loop for partial writes. In particular network writes will typically only write part of the data for large writes, so we need to keep the retry loop to preserve backwards compatibility. If issues due to this change turn up, chunking should be reintroduced at lower levels where it is needed to avoid issues for specific streams, rather than unnecessarily enforcing it for all streams.
1 parent f9ab339 commit 5cbe5a5

File tree

4 files changed

+9
-20
lines changed

4 files changed

+9
-20
lines changed
 

‎ext/standard/tests/file/userstreams_006.phpt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,5 @@ bool(true)
3232
option: 3, 2, 50
3333
int(-1)
3434
int(8192)
35-
size: 42
36-
size: 28
35+
size: 70
3736
int(70)

‎ext/standard/tests/streams/set_file_buffer.phpt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,4 @@ option: %d, %d, %d
4343
int(%i)
4444
int(%d)
4545
size: %d
46-
size: %d
4746
int(%d)

‎ext/standard/tests/streams/stream_set_chunk_size.phpt

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ echo "should return previous chunk size (8192)\n";
3434
var_dump(stream_set_chunk_size($f, 1));
3535
echo "should be read without buffer (\$count == 10000)\n";
3636
var_dump(strlen(fread($f, 10000)));
37-
echo "should elicit 3 writes of size 1 and return 3\n";
37+
echo "should have no effect on writes\n";
3838
var_dump(fwrite($f, str_repeat('b', 3)));
3939

4040
echo "should return previous chunk size (1)\n";
@@ -45,7 +45,7 @@ echo "should elicit one read of size 100 (chunk size)\n";
4545
var_dump(strlen(fread($f, 50)));
4646
echo "should elicit no read because there is sufficient cached data\n";
4747
var_dump(strlen(fread($f, 50)));
48-
echo "should elicit 2 writes of size 100 and one of size 50\n";
48+
echo "should have no effect on writes\n";
4949
var_dump(strlen(fwrite($f, str_repeat('b', 250))));
5050

5151
echo "\nerror conditions\n";
@@ -58,10 +58,8 @@ int(8192)
5858
should be read without buffer ($count == 10000)
5959
read with size: 10000
6060
int(10000)
61-
should elicit 3 writes of size 1 and return 3
62-
write with size: 1
63-
write with size: 1
64-
write with size: 1
61+
should have no effect on writes
62+
write with size: 3
6563
int(3)
6664
should return previous chunk size (1)
6765
int(1)
@@ -73,10 +71,8 @@ read with size: 100
7371
int(50)
7472
should elicit no read because there is sufficient cached data
7573
int(50)
76-
should elicit 2 writes of size 100 and one of size 50
77-
write with size: 100
78-
write with size: 100
79-
write with size: 50
74+
should have no effect on writes
75+
write with size: 250
8076
int(3)
8177

8278
error conditions

‎main/streams/streams.c

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1105,7 +1105,7 @@ PHPAPI zend_string *php_stream_get_record(php_stream *stream, size_t maxlen, con
11051105
/* Writes a buffer directly to a stream, using multiple of the chunk size */
11061106
static ssize_t _php_stream_write_buffer(php_stream *stream, const char *buf, size_t count)
11071107
{
1108-
ssize_t didwrite = 0, justwrote;
1108+
ssize_t didwrite = 0;
11091109

11101110
/* if we have a seekable stream we need to ensure that data is written at the
11111111
* current stream->position. This means invalidating the read buffer and then
@@ -1116,13 +1116,8 @@ static ssize_t _php_stream_write_buffer(php_stream *stream, const char *buf, siz
11161116
stream->ops->seek(stream, stream->position, SEEK_SET, &stream->position);
11171117
}
11181118

1119-
11201119
while (count > 0) {
1121-
size_t towrite = count;
1122-
if (towrite > stream->chunk_size)
1123-
towrite = stream->chunk_size;
1124-
1125-
justwrote = stream->ops->write(stream, buf, towrite);
1120+
ssize_t justwrote = stream->ops->write(stream, buf, count);
11261121
if (justwrote <= 0) {
11271122
/* If we already successfully wrote some bytes and a write error occurred
11281123
* later, report the successfully written bytes. */

0 commit comments

Comments
 (0)
Please sign in to comment.