)]}'
{
  "commit": "1091a6d625a56e7aadee60cdd885ece83d7c9a09",
  "tree": "0abd833ce2b6df2fa4aefb10f2c9d65074635d65",
  "parents": [
    "9935c448a143e4f8bf4773044df838b1eb3c4b5d"
  ],
  "author": {
    "name": "Protobuf Team Bot",
    "email": "protobuf-github-bot@google.com",
    "time": "Thu Oct 15 23:09:06 2026 -0700"
  },
  "committer": {
    "name": "Copybara-Service",
    "email": "copybara-worker@google.com",
    "time": "Thu Oct 15 23:15:05 2026 -0700"
  },
  "message": "`ByteString.readFrom(InputStream)` previously allocated a new scratch `byte[]` inside `readChunk` on every iteration in addition to the copy created by `ByteString.copyFrom(byte[], int, int)`, and continued attempting an extra read (with another buffer allocation) even after a partial chunk had already reached end-of-stream. Similarly, `ByteString.copyFrom(Iterable)` always allocated an `Iterator` even for `RandomAccess` lists, and `ByteString.Output` allocated backing list storage when `toByteString()` was called on a single un-flushed buffer or an empty stream.\n\nReuse the scratch buffer in `ByteString.readFrom` once the chunk size reaches `maxChunkSize` and stop reading once a chunk returns fewer bytes than requested (indicating EOF was reached). Add a `RandomAccess` `List` fast path in `ByteString.copyFrom(Iterable)` and `balancedConcat` to index elements directly without allocating an iterator, and avoid unnecessary buffer and list allocations in `ByteString.Output` for empty or single-buffer outputs. These changes reduce per-operation allocations by 40% to 57% and improve throughput by 1.5x to 1.9x in `readFrom`, while reducing single-buffer `ByteString.Output.toByteString()` allocations by 16% and `copyFrom(List)` iterator overhead.\n\n\u003cdetails\u003e\n\n\u003csummary\u003eExpand for JMH benchmark setup and results\u003c/summary\u003e\n\nCommand:\n\n```bash\nblaze run //javatests/com/google/protobuf:ByteStringComparisonJmhBenchmark_bin_deploy.jar -- \\\n  \".*(readFrom|output|copyFrom).*\" -f 1 -wi 3 -i 5 -w 1s -r 1s -prof gc\n```\n\n| Benchmark | Before (ns/op) | After (ns/op) | Speedup | Before Alloc (B/op) | After Alloc (B/op) | Alloc Reduction |\n| :--- | :--- | :--- | :--- | :--- | :--- | :--- |\n| `readFrom100B` | 92.54 | 48.56 | 1.91x (-47.5%) | 1032 | 448 | -584 B/op (-56.6%) |\n| `readFrom4KB` | 1587.21 | 1038.36 | 1.53x (-34.6%) | 20824 | 12584 | -8240 B/op (-39.6%) |\n| `readFrom32KB` | 6867.63 | 4500.33 | 1.53x (-34.5%) | 82648 | 49784 | -32864 B/op (-39.8%) |\n| `outputSingleBuffer` | 33.84 | 29.98 | 1.13x (-11.4%) | 360 | 304 | -56 B/op (-15.6%) |\n| `copyFrom8ElementList` | 99.94 | 93.67 | 1.07x (-6.3%) | 312 | 280 | -32 B/op (-10.3%) |\n| `copyFromSingletonList` | 1.00 | 1.04 | ~1.00x | 0 | 0 | 0 B/op |\n\n\u003c/details\u003e\n\nPiperOrigin-RevId: 1000631317\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "1c444382cade7ba0b4068f2c95e0fdcb02707154",
      "old_mode": 33188,
      "old_path": "java/core/src/main/java/com/google/protobuf/ByteString.java",
      "new_id": "1a872eac5a68d7f0b1de84730ae15c14d20f7ef7",
      "new_mode": 33188,
      "new_path": "java/core/src/main/java/com/google/protobuf/ByteString.java"
    },
    {
      "type": "modify",
      "old_id": "c4e6c6a7bec8f3e443877c3273c6b3af002c6741",
      "old_mode": 33188,
      "old_path": "java/core/src/test/java/com/google/protobuf/ByteStringTest.java",
      "new_id": "ce9fec34ccd6b5eff6a9ab4f40827b9278a92ccc",
      "new_mode": 33188,
      "new_path": "java/core/src/test/java/com/google/protobuf/ByteStringTest.java"
    }
  ]
}
