Skip to content

Commit e099a72

Browse files
committed
write chunks to a buffer with no re-use
chunks were previously enqueued to a ReadableStream as they were written. We now write them to a view over an ArrayBuffer and enqueue them only when writing has completed or the buffer's size is exceeded. In addition this copy now ensures we don't attempt to re-send buffers that have already been transferred.
1 parent 14c2be8 commit e099a72

File tree

1 file changed

+44
-4
lines changed

1 file changed

+44
-4
lines changed

packages/react-server/src/ReactServerStreamConfigBrowser.js

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,64 @@ export function flushBuffered(destination: Destination) {
2121
// transform streams. https://github.com/whatwg/streams/issues/960
2222
}
2323

24+
let currentView = null;
25+
let writtenBytes = 0;
26+
2427
export function beginWriting(destination: Destination) {}
2528

2629
export function writeChunk(
2730
destination: Destination,
2831
chunk: PrecomputedChunk | Chunk,
2932
): void {
30-
destination.enqueue(chunk);
33+
if (currentView === null) {
34+
currentView = new Uint8Array(512);
35+
writtenBytes = 0;
36+
}
37+
38+
if (chunk.length > currentView.length) {
39+
// this chunk is larger than our view which implies it was not
40+
// one that is cached by the streaming renderer. We will enqueu
41+
// it directly and expect it is not re-used
42+
if (writtenBytes > 0) {
43+
destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
44+
currentView = null;
45+
writtenBytes = 0;
46+
}
47+
destination.enqueue(chunk);
48+
return;
49+
}
50+
51+
let allowableBytes = currentView.length - writtenBytes;
52+
if (allowableBytes < chunk.length) {
53+
// this chunk would overflow the current view. We enqueu a full view
54+
// and start a new view with the remaining chunk
55+
currentView.set(chunk.subarray(0, allowableBytes), writtenBytes);
56+
destination.enqueue(currentView);
57+
currentView = new Uint8Array(512);
58+
currentView.set(chunk.subarray(allowableBytes));
59+
writtenBytes = chunk.length - allowableBytes;
60+
} else {
61+
currentView.set(chunk, writtenBytes);
62+
writtenBytes += chunk.length;
63+
}
3164
}
3265

3366
export function writeChunkAndReturn(
3467
destination: Destination,
3568
chunk: PrecomputedChunk | Chunk,
3669
): boolean {
37-
destination.enqueue(chunk);
38-
return destination.desiredSize > 0;
70+
writeChunk(destination, chunk);
71+
// in web streams there is no backpressure so we can alwas write more
72+
return true;
3973
}
4074

41-
export function completeWriting(destination: Destination) {}
75+
export function completeWriting(destination: Destination) {
76+
if (writtenBytes > 0) {
77+
destination.enqueue(new Uint8Array(currentView.buffer, 0, writtenBytes));
78+
currentView = null;
79+
writtenBytes = 0;
80+
}
81+
}
4282

4383
export function close(destination: Destination) {
4484
destination.close();

0 commit comments

Comments
 (0)