Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear Payload buffer after receiving #32

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

bch36
Copy link

@bch36 bch36 commented Mar 2, 2021

Wrench\Client keeps all received Payload objects in perpetuity. This results in a script eventually running out of memory if it's reading a large stream of data. Instead, after receiving any Payload objects buffered since the last call to receive(), clear the buffer of received Payloads. This is safe because they're never accessed again. Clear the buffer in ChromeDevtoolsProtocol\WebSocket\WebSocketClient to avoid upstream changes to Wrench\Client.

Additional info: Wrench\Client stores all received Payloads in Client::$received. In fact, if Payload::getPayload() is called (as it is in DevtoolsClient), memory usage will double because the received data is copied from the Payload's comprising Frames (Payload::$frames) into Payload::$buffer. The data is then stored a third time in the ReadResponse and returned to the original caller. The caller only has the ability to delete the third copy of the data in the ReadResponse. This results in memory usage growing quickly and perpetually as a long-lasting stream is read until the script eventually runs out of available memory.

For example, if a user generates a large PDF (printToPDF) using a transferMode of ReturnAsStream, they may call $session->io()->read() many times to fetch the generated PDF. As they do so, they'll likely write each block of data to a file. If the buffer of received Payloads is never cleared to free memory, the user is limited to receiving a PDF approximately 1/2 the size of the memory_limit. If the buffer of received Payloads is cleared regularly, then there is theoretically no limit to the size of PDF they can read.

bch36 added 2 commits March 2, 2021 12:07
Wrench\Client keeps all received Payload objects in perpetuity.  This results in a script eventually running out of memory if it's reading a large stream of data.  Instead, after receiving any Payload objects buffered since the last call to receive(), clear the buffer of received Payloads.  This is safe because they're never accessed again.  Clear the buffer in ChromeDevtoolsProtocol\WebSocket\WebSocketClient to avoid upstream changes to Wrench\Client.

Additional info: Wrench\Client stores all received Payloads in Client::$received.  In fact, if Payload::getPayload() is called (as it is in DevtoolsClient), memory usage will double because the received data is copied from the Payload's comprising Frames (Payload::$frames) into Payload::$buffer.  The data is then stored a third time in the ReadResponse and returned to the original caller.  The caller only has the ability to delete the third copy of the data in the ReadResponse.  This results in memory usage growing quickly and perpetually as a long-lasting stream is read until the script eventually runs out of available memory.  

For example, if a user generates a large PDF (printToPDF) using a transferMode of ReturnAsStream, they may call $session->io()->read() many times to fetch the generated PDF.  As they do so, they'll likely write each block of data to a file.  If the buffer of received Payloads is never cleared to free memory, the user is limited to receiving a PDF approximately 1/2 the size of the memory_limit.  If the buffer of received Payloads is cleared regularly, then there is theoretically no limit to the size of PDF they can read.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant