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

Fix poor buffering case for MultipartReader #8665

Merged
merged 10 commits into from
Feb 17, 2025
Merged

Conversation

yschimke
Copy link
Collaborator

100mb Body is fully written, reader wants 1MB chunks, but get 8kb at a time. Unfortunately internally we do indexOf over the full 100mb.

outer reading 1048576
indexOf over 104857611 with maxResult 8192
inner 8192
outer read 8192
outer reading 1048576
indexOf over 104849419 with maxResult 8192
inner 8192
outer read 8192

@yschimke yschimke requested a review from squarejesse January 30, 2025 08:37
@yschimke
Copy link
Collaborator Author

@swankjesse any suggestions for the right way to test and fix this?

@yschimke
Copy link
Collaborator Author

yschimke commented Jan 30, 2025

I'm not sure if this is actually a bug in Okio RealBufferedSource that it assumes that checking segment size is optimal?

internal inline fun RealBufferedSource.commonRead(sink: Buffer, byteCount: Long): Long {
  require(byteCount >= 0L) { "byteCount < 0: $byteCount" }
  check(!closed) { "closed" }

  if (buffer.size == 0L) {
    if (byteCount == 0L) return 0L
    val read = source.read(buffer, Segment.SIZE.toLong())
    if (read == -1L) return -1L
  }

  val toRead = minOf(byteCount, buffer.size)
  return buffer.read(sink, toRead)
}

Also if we do want to scan 8kb at a time, how can we limit the indexOf?

    private fun currentPartBytesRemaining(maxResult: Long): Long {
      source.require(crlfDashDashBoundary.size.toLong())

      return when (val delimiterIndex = source.buffer.indexOf(crlfDashDashBoundary)) {
        -1L -> minOf(maxResult, source.buffer.size - crlfDashDashBoundary.size + 1)
        else -> minOf(maxResult, delimiterIndex)
      }
    }

Do we need this added to Buffer?

  override fun indexOf(bytes: ByteString, fromIndex: Long, toIndex: Long): Long

@yschimke yschimke requested a review from JakeWharton February 1, 2025 13:05
@yschimke yschimke marked this pull request as draft February 1, 2025 13:05
@yschimke yschimke changed the title Demonstrate poor buffering case for MultipartReader Fix poor buffering case for MultipartReader Feb 15, 2025
@yschimke yschimke requested review from swankjesse and removed request for squarejesse February 15, 2025 17:15
@yschimke
Copy link
Collaborator Author

500ms with the fix
I stopped after 2 minutes without the fix

@yschimke yschimke marked this pull request as ready for review February 15, 2025 17:17
@yschimke
Copy link
Collaborator Author

@swankjesse requesting post review (as agreed)

@yschimke yschimke merged commit 3cc87c3 into square:master Feb 17, 2025
20 checks passed
yschimke added a commit to yschimke/okhttp that referenced this pull request Feb 17, 2025
* Demonstrate poor buffering case
* Fix for repeated reads of small byteCount from large part

(cherry picked from commit 3cc87c3)
yschimke added a commit that referenced this pull request Feb 17, 2025
* Demonstrate poor buffering case
* Fix for repeated reads of small byteCount from large part

(cherry picked from commit 3cc87c3)
yschimke added a commit that referenced this pull request Feb 17, 2025
* Demonstrate poor buffering case
* Fix for repeated reads of small byteCount from large part

(cherry picked from commit 3cc87c3)
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