Fix poor buffering case for MultipartReader#8665
Conversation
|
@swankjesse any suggestions for the right way to test and fix this? |
|
I'm not sure if this is actually a bug in Okio RealBufferedSource that it assumes that checking segment size is optimal? Also if we do want to scan 8kb at a time, how can we limit the indexOf? Do we need this added to Buffer? |
|
500ms with the fix |
|
@swankjesse requesting post review (as agreed) |
* Demonstrate poor buffering case * Fix for repeated reads of small byteCount from large part (cherry picked from commit 3cc87c3)
* Demonstrate poor buffering case * Fix for repeated reads of small byteCount from large part (cherry picked from commit 3cc87c3)
| -1L -> minOf(maxResult, source.buffer.size - crlfDashDashBoundary.size + 1) | ||
| // Avoid indexOf scanning repeatedly over the entire source by using limit | ||
| // Since maxResult could be midway through the boundary, read further to be safe. | ||
| val limitSource = source.peek().limit(maxResult + crlfDashDashBoundary.size).buffer() |
There was a problem hiding this comment.
Ugh, I regret that BufferedSource doesn’t have an API that does what you want without needing to peek() and limit()
| @JvmOverloads | ||
| internal fun Source.limit( | ||
| byteCount: Long, | ||
| onReadExhausted: (eof: Boolean) -> Unit = {}, |
There was a problem hiding this comment.
Donation of the impl from @JakeWharton
With the idea that we could switch to a future Okio one at some point in the future.
| assertThat(part.headers["header-name"]).isEqualTo("header-value") | ||
| while (true) { | ||
| val readBuff = Buffer() | ||
| val read = part.body.read(readBuff, (1024).toLong()) |
There was a problem hiding this comment.
What a weird way to write 1024L
| } | ||
|
|
||
| @Test | ||
| fun `reading a large part with small byteCount`() { |
100mb Body is fully written, reader wants 1MB chunks, but get 8kb at a time. Unfortunately internally we do indexOf over the full 100mb.