This is an automated email from the ASF dual-hosted git repository.

pjfanning pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/pekko.git


The following commit(s) were added to refs/heads/main by this push:
     new bc78cd16d5 ByteStringBuilder.putInt/putLong: eliminate closure 
allocation via SWARUtil VarHandle writes (#2879)
bc78cd16d5 is described below

commit bc78cd16d554e3c3ce6c8fd3345a390ce06049fb
Author: PJ Fanning <[email protected]>
AuthorDate: Fri Apr 24 00:18:55 2026 +0200

    ByteStringBuilder.putInt/putLong: eliminate closure allocation via SWARUtil 
VarHandle writes (#2879)
    
    * Eliminate closure allocation in ByteStringBuilder.putInt/putLong via 
SWARUtil VarHandle writes
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/c0a324ab-b053-4254-8d3b-e472278559b9
    
    Co-authored-by: pjfanning <[email protected]>
    
    * Add tests for SWARUtil.putInt/putLong write methods and 
ByteStringBuilder.putInt/putLong
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/d3bbcf71-0623-473b-b9cc-52a23c034666
    
    Co-authored-by: pjfanning <[email protected]>
    
    * scalafmt
    
    * Create ByteString_putInt_Benchmark.scala
    
    * Add putShort VarHandle support, fix benchmark, add tests for putShort
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/710c7bd8-24f1-4665-b722-dd9020049450
    
    Co-authored-by: pjfanning <[email protected]>
    
    * Refactor SnapshotSerializer: remove writeInt, use SWARUtil.putInt + 
pre-allocated arrays
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/770d8c57-8a12-4f06-b900-1f6271577fdd
    
    Co-authored-by: pjfanning <[email protected]>
    
    * refactor to avoid one array creation on one path
    
    * plan: fix putShort Int param, add all-zero/all-ones layout tests, 
putFloat/putDouble tests, SnapshotSerializer format tests
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/3a10e6a7-4e61-4f22-9ca1-fdbad5891385
    
    Co-authored-by: pjfanning <[email protected]>
    
    * Fix putShort to accept Int; add all-zero/all-ones layout tests; add 
putFloat/putDouble and SnapshotSerializer format tests
    
    Agent-Logs-Url: 
https://github.com/pjfanning/incubator-pekko/sessions/3a10e6a7-4e61-4f22-9ca1-fdbad5891385
    
    Co-authored-by: pjfanning <[email protected]>
    
    ---------
    
    Co-authored-by: copilot-swe-agent[bot] 
<[email protected]>
    Co-authored-by: pjfanning <[email protected]>
---
 .../org/apache/pekko/util/ByteStringSpec.scala     | 373 +++++++++++++++++++++
 .../scala/org/apache/pekko/util/SWARUtilSpec.scala | 222 ++++++++++++
 .../scala/org/apache/pekko/util/ByteString.scala   |  54 +--
 .../scala/org/apache/pekko/util/SWARUtil.scala     | 124 +++++++
 .../pekko/util/ByteString_putInt_Benchmark.scala   | 101 ++++++
 .../serialization/SnapshotSerializer.scala         |  38 +--
 6 files changed, 851 insertions(+), 61 deletions(-)

diff --git 
a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala 
b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
index fcfc4fcca7..1956c556a4 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/util/ByteStringSpec.scala
@@ -2693,6 +2693,379 @@ class ByteStringSpec extends AnyWordSpec with Matchers 
with Checkers {
         }
       }
     }
+
+    "putInt" when {
+      "big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(0x01020304)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x01, 0x02, 0x03, 0x04))
+      }
+      "little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(0x01020304)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x04, 0x03, 0x02, 0x01))
+      }
+      "max value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(Int.MaxValue)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x7F, 0xFF.toByte, 
0xFF.toByte, 0xFF.toByte))
+      }
+      "min value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(Int.MinValue)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x80.toByte, 0x00, 0x00, 
0x00))
+      }
+      "max value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(Int.MaxValue)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0xFF.toByte, 0xFF.toByte, 
0xFF.toByte, 0x7F))
+      }
+      "min value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(Int.MinValue)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x00, 0x00, 0x00, 
0x80.toByte))
+      }
+      "result has length 4" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(42)(BIG_ENDIAN)
+        builder.length should ===(4)
+        builder.result().length should ===(4)
+      }
+      "multiple puts accumulate correctly" in {
+        val builder = ByteString.newBuilder
+        builder.putInt(0x01020304)(BIG_ENDIAN)
+        builder.putInt(0x05060708)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x01, 0x02, 0x03, 0x04, 
0x05, 0x06, 0x07, 0x08))
+      }
+      "round-trips with ByteBuffer big-endian" in {
+        check { (value: Int) =>
+          val builder = ByteString.newBuilder
+          builder.putInt(value)(BIG_ENDIAN)
+          val reference = new Array[Byte](4)
+          ByteBuffer.wrap(reference).order(BIG_ENDIAN).putInt(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+      "round-trips with ByteBuffer little-endian" in {
+        check { (value: Int) =>
+          val builder = ByteString.newBuilder
+          builder.putInt(value)(LITTLE_ENDIAN)
+          val reference = new Array[Byte](4)
+          ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putInt(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+    }
+
+    "putLong" when {
+      "big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(0x0102030405060708L)(BIG_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08))
+      }
+      "little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(0x0102030405060708L)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01))
+      }
+      "max value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(Long.MaxValue)(BIG_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x7F, 0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 
0xFF.toByte, 0xFF.toByte, 0xFF.toByte))
+      }
+      "min value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(Long.MinValue)(BIG_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x80.toByte, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00))
+      }
+      "max value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(Long.MaxValue)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 
0xFF.toByte, 0xFF.toByte, 0xFF.toByte, 0x7F))
+      }
+      "min value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(Long.MinValue)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80.toByte))
+      }
+      "result has length 8" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(42L)(BIG_ENDIAN)
+        builder.length should ===(8)
+        builder.result().length should ===(8)
+      }
+      "multiple puts accumulate correctly" in {
+        val builder = ByteString.newBuilder
+        builder.putLong(0x0102030405060708L)(BIG_ENDIAN)
+        builder.putLong(0x090A0B0C0D0E0F10L)(BIG_ENDIAN)
+        builder.result().toSeq should ===(
+          Seq[Byte](0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+            0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10))
+      }
+      "round-trips with ByteBuffer big-endian" in {
+        check { (value: Long) =>
+          val builder = ByteString.newBuilder
+          builder.putLong(value)(BIG_ENDIAN)
+          val reference = new Array[Byte](8)
+          ByteBuffer.wrap(reference).order(BIG_ENDIAN).putLong(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+      "round-trips with ByteBuffer little-endian" in {
+        check { (value: Long) =>
+          val builder = ByteString.newBuilder
+          builder.putLong(value)(LITTLE_ENDIAN)
+          val reference = new Array[Byte](8)
+          ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putLong(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+    }
+
+    "putFloat" when {
+      "big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(1.0f)(BIG_ENDIAN)
+        val reference = new Array[Byte](4)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putFloat(1.0f)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(1.0f)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](4)
+        ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putFloat(1.0f)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "max value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(Float.MaxValue)(BIG_ENDIAN)
+        val reference = new Array[Byte](4)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putFloat(Float.MaxValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "min value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(Float.MinValue)(BIG_ENDIAN)
+        val reference = new Array[Byte](4)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putFloat(Float.MinValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "max value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(Float.MaxValue)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](4)
+        
ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putFloat(Float.MaxValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "min value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(Float.MinValue)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](4)
+        
ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putFloat(Float.MinValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "NaN big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(Float.NaN)(BIG_ENDIAN)
+        val bits = floatToRawIntBits(Float.NaN)
+        builder.result().toSeq should ===(
+          Seq[Byte]((bits >>> 24).toByte, (bits >>> 16).toByte, (bits >>> 
8).toByte, bits.toByte))
+      }
+      "result has length 4" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(42.0f)(BIG_ENDIAN)
+        builder.length should ===(4)
+        builder.result().length should ===(4)
+      }
+      "multiple puts accumulate correctly" in {
+        val builder = ByteString.newBuilder
+        builder.putFloat(1.0f)(BIG_ENDIAN)
+        builder.putFloat(2.0f)(BIG_ENDIAN)
+        builder.length should ===(8)
+        val reference = new Array[Byte](8)
+        val buf = ByteBuffer.wrap(reference).order(BIG_ENDIAN)
+        buf.putFloat(1.0f)
+        buf.putFloat(2.0f)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "round-trips with ByteBuffer big-endian" in {
+        check { (value: Float) =>
+          val builder = ByteString.newBuilder
+          builder.putFloat(value)(BIG_ENDIAN)
+          val reference = new Array[Byte](4)
+          ByteBuffer.wrap(reference).order(BIG_ENDIAN).putFloat(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+      "round-trips with ByteBuffer little-endian" in {
+        check { (value: Float) =>
+          val builder = ByteString.newBuilder
+          builder.putFloat(value)(LITTLE_ENDIAN)
+          val reference = new Array[Byte](4)
+          ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putFloat(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+    }
+
+    "putDouble" when {
+      "big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(1.0)(BIG_ENDIAN)
+        val reference = new Array[Byte](8)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putDouble(1.0)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(1.0)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](8)
+        ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putDouble(1.0)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "max value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(Double.MaxValue)(BIG_ENDIAN)
+        val reference = new Array[Byte](8)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putDouble(Double.MaxValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "min value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(Double.MinValue)(BIG_ENDIAN)
+        val reference = new Array[Byte](8)
+        ByteBuffer.wrap(reference).order(BIG_ENDIAN).putDouble(Double.MinValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "max value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(Double.MaxValue)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](8)
+        
ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putDouble(Double.MaxValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "min value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(Double.MinValue)(LITTLE_ENDIAN)
+        val reference = new Array[Byte](8)
+        
ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putDouble(Double.MinValue)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "NaN big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(Double.NaN)(BIG_ENDIAN)
+        val bits = doubleToRawLongBits(Double.NaN)
+        builder.result().toSeq should ===(
+          Seq[Byte](
+            (bits >>> 56).toByte, (bits >>> 48).toByte, (bits >>> 40).toByte, 
(bits >>> 32).toByte,
+            (bits >>> 24).toByte, (bits >>> 16).toByte, (bits >>> 8).toByte, 
bits.toByte))
+      }
+      "result has length 8" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(42.0)(BIG_ENDIAN)
+        builder.length should ===(8)
+        builder.result().length should ===(8)
+      }
+      "multiple puts accumulate correctly" in {
+        val builder = ByteString.newBuilder
+        builder.putDouble(1.0)(BIG_ENDIAN)
+        builder.putDouble(2.0)(BIG_ENDIAN)
+        builder.length should ===(16)
+        val reference = new Array[Byte](16)
+        val buf = ByteBuffer.wrap(reference).order(BIG_ENDIAN)
+        buf.putDouble(1.0)
+        buf.putDouble(2.0)
+        builder.result().toSeq should ===(reference.toSeq)
+      }
+      "round-trips with ByteBuffer big-endian" in {
+        check { (value: Double) =>
+          val builder = ByteString.newBuilder
+          builder.putDouble(value)(BIG_ENDIAN)
+          val reference = new Array[Byte](8)
+          ByteBuffer.wrap(reference).order(BIG_ENDIAN).putDouble(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+      "round-trips with ByteBuffer little-endian" in {
+        check { (value: Double) =>
+          val builder = ByteString.newBuilder
+          builder.putDouble(value)(LITTLE_ENDIAN)
+          val reference = new Array[Byte](8)
+          ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putDouble(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+    }
+
+    "putShort" when {
+      "big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(0x0102)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x01, 0x02))
+      }
+      "little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(0x0102)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x02, 0x01))
+      }
+      "max value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(Short.MaxValue.toInt)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x7F, 0xFF.toByte))
+      }
+      "min value big-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(Short.MinValue.toInt)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x80.toByte, 0x00))
+      }
+      "max value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(Short.MaxValue.toInt)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0xFF.toByte, 0x7F))
+      }
+      "min value little-endian" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(Short.MinValue.toInt)(LITTLE_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x00, 0x80.toByte))
+      }
+      "result has length 2" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(42)(BIG_ENDIAN)
+        builder.length should ===(2)
+        builder.result().length should ===(2)
+      }
+      "multiple puts accumulate correctly" in {
+        val builder = ByteString.newBuilder
+        builder.putShort(0x0102)(BIG_ENDIAN)
+        builder.putShort(0x0304)(BIG_ENDIAN)
+        builder.result().toSeq should ===(Seq[Byte](0x01, 0x02, 0x03, 0x04))
+      }
+      "round-trips with ByteBuffer big-endian" in {
+        check { (value: Short) =>
+          val builder = ByteString.newBuilder
+          builder.putShort(value.toInt)(BIG_ENDIAN)
+          val reference = new Array[Byte](2)
+          ByteBuffer.wrap(reference).order(BIG_ENDIAN).putShort(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+      "round-trips with ByteBuffer little-endian" in {
+        check { (value: Short) =>
+          val builder = ByteString.newBuilder
+          builder.putShort(value.toInt)(LITTLE_ENDIAN)
+          val reference = new Array[Byte](2)
+          ByteBuffer.wrap(reference).order(LITTLE_ENDIAN).putShort(value)
+          builder.result().toSeq == reference.toSeq
+        }
+      }
+    }
   }
 
   private def makeMultiByteStringsSample(): ByteString = {
diff --git 
a/actor-tests/src/test/scala/org/apache/pekko/util/SWARUtilSpec.scala 
b/actor-tests/src/test/scala/org/apache/pekko/util/SWARUtilSpec.scala
index 9a9688ded6..a88d6b5e8f 100644
--- a/actor-tests/src/test/scala/org/apache/pekko/util/SWARUtilSpec.scala
+++ b/actor-tests/src/test/scala/org/apache/pekko/util/SWARUtilSpec.scala
@@ -57,6 +57,228 @@ class SWARUtilSpec extends AnyWordSpec with Matchers {
       SWARUtil.getShortBEWithoutMethodHandle(testData, 2) should 
===(0x0203.toShort)
       SWARUtil.getShortLEWithoutMethodHandle(testData, 2) should 
===(0x0302.toShort)
     }
+    "putInt" in {
+      val arr = new Array[Byte](8)
+
+      SWARUtil.putInt(arr, 0, 0x00010203, ByteOrder.BIG_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0x00, 0x01, 0x02, 0x03))
+
+      SWARUtil.putInt(arr, 4, 0x04050607, ByteOrder.BIG_ENDIAN)
+      arr.drop(4).toSeq should ===(Seq[Byte](0x04, 0x05, 0x06, 0x07))
+
+      SWARUtil.putInt(arr, 0, 0x00010203, ByteOrder.LITTLE_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0x03, 0x02, 0x01, 0x00))
+
+      SWARUtil.putInt(arr, 4, 0x04050607, ByteOrder.LITTLE_ENDIAN)
+      arr.drop(4).toSeq should ===(Seq[Byte](0x07, 0x06, 0x05, 0x04))
+
+      // all-zero pattern
+      SWARUtil.putInt(arr, 0, 0, ByteOrder.BIG_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0x00, 0x00, 0x00, 0x00))
+
+      SWARUtil.putInt(arr, 0, 0, ByteOrder.LITTLE_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0x00, 0x00, 0x00, 0x00))
+
+      // all-ones pattern
+      SWARUtil.putInt(arr, 0, -1, ByteOrder.BIG_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0xFF.toByte, 0xFF.toByte, 
0xFF.toByte, 0xFF.toByte))
+
+      SWARUtil.putInt(arr, 0, -1, ByteOrder.LITTLE_ENDIAN)
+      arr.take(4).toSeq should ===(Seq[Byte](0xFF.toByte, 0xFF.toByte, 
0xFF.toByte, 0xFF.toByte))
+    }
+    "putIntBEWithoutMethodHandle" in {
+      val arr = new Array[Byte](8)
+
+      SWARUtil.putIntBEWithoutMethodHandle(arr, 0, 0x00010203)
+      arr.take(4).toSeq should ===(Seq[Byte](0x00, 0x01, 0x02, 0x03))
+
+      SWARUtil.putIntBEWithoutMethodHandle(arr, 4, 0x04050607)
+      arr.drop(4).toSeq should ===(Seq[Byte](0x04, 0x05, 0x06, 0x07))
+
+      // round-trip: putIntBEWithoutMethodHandle and 
getIntBEWithoutMethodHandle are inverses
+      SWARUtil.putIntBEWithoutMethodHandle(arr, 0, Int.MaxValue)
+      SWARUtil.getIntBEWithoutMethodHandle(arr, 0) should ===(Int.MaxValue)
+      SWARUtil.putIntBEWithoutMethodHandle(arr, 0, Int.MinValue)
+      SWARUtil.getIntBEWithoutMethodHandle(arr, 0) should ===(Int.MinValue)
+    }
+    "putIntLEWithoutMethodHandle" in {
+      val arr = new Array[Byte](8)
+
+      SWARUtil.putIntLEWithoutMethodHandle(arr, 0, 0x00010203)
+      arr.take(4).toSeq should ===(Seq[Byte](0x03, 0x02, 0x01, 0x00))
+
+      SWARUtil.putIntLEWithoutMethodHandle(arr, 4, 0x04050607)
+      arr.drop(4).toSeq should ===(Seq[Byte](0x07, 0x06, 0x05, 0x04))
+
+      // round-trip
+      SWARUtil.putIntLEWithoutMethodHandle(arr, 0, Int.MaxValue)
+      SWARUtil.getIntLEWithoutMethodHandle(arr, 0) should ===(Int.MaxValue)
+      SWARUtil.putIntLEWithoutMethodHandle(arr, 0, Int.MinValue)
+      SWARUtil.getIntLEWithoutMethodHandle(arr, 0) should ===(Int.MinValue)
+    }
+    "putLong" in {
+      val arr = new Array[Byte](16)
+
+      SWARUtil.putLong(arr, 0, 0x0001020304050607L, ByteOrder.BIG_ENDIAN)
+      arr.take(8).toSeq should ===(Seq[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 
0x05, 0x06, 0x07))
+
+      SWARUtil.putLong(arr, 8, 0x08090A0B0C0D0E0FL, ByteOrder.BIG_ENDIAN)
+      arr.drop(8).toSeq should ===(Seq[Byte](0x08, 0x09, 0x0A, 0x0B, 0x0C, 
0x0D, 0x0E, 0x0F))
+
+      SWARUtil.putLong(arr, 0, 0x0001020304050607L, ByteOrder.LITTLE_ENDIAN)
+      arr.take(8).toSeq should ===(Seq[Byte](0x07, 0x06, 0x05, 0x04, 0x03, 
0x02, 0x01, 0x00))
+
+      SWARUtil.putLong(arr, 8, 0x08090A0B0C0D0E0FL, ByteOrder.LITTLE_ENDIAN)
+      arr.drop(8).toSeq should ===(Seq[Byte](0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 
0x0A, 0x09, 0x08))
+
+      // all-zero pattern
+      SWARUtil.putLong(arr, 0, 0L, ByteOrder.BIG_ENDIAN)
+      arr.take(8).toSeq should ===(Seq.fill(8)(0x00.toByte))
+
+      SWARUtil.putLong(arr, 0, 0L, ByteOrder.LITTLE_ENDIAN)
+      arr.take(8).toSeq should ===(Seq.fill(8)(0x00.toByte))
+
+      // all-ones pattern
+      SWARUtil.putLong(arr, 0, -1L, ByteOrder.BIG_ENDIAN)
+      arr.take(8).toSeq should ===(Seq.fill(8)(0xFF.toByte))
+
+      SWARUtil.putLong(arr, 0, -1L, ByteOrder.LITTLE_ENDIAN)
+      arr.take(8).toSeq should ===(Seq.fill(8)(0xFF.toByte))
+    }
+    "putLongBEWithoutMethodHandle" in {
+      val arr = new Array[Byte](16)
+
+      SWARUtil.putLongBEWithoutMethodHandle(arr, 0, 0x0001020304050607L)
+      arr.take(8).toSeq should ===(Seq[Byte](0x00, 0x01, 0x02, 0x03, 0x04, 
0x05, 0x06, 0x07))
+
+      SWARUtil.putLongBEWithoutMethodHandle(arr, 8, 0x08090A0B0C0D0E0FL)
+      arr.drop(8).toSeq should ===(Seq[Byte](0x08, 0x09, 0x0A, 0x0B, 0x0C, 
0x0D, 0x0E, 0x0F))
+
+      // round-trip
+      SWARUtil.putLongBEWithoutMethodHandle(arr, 0, Long.MaxValue)
+      SWARUtil.getLongBEWithoutMethodHandle(arr, 0) should ===(Long.MaxValue)
+      SWARUtil.putLongBEWithoutMethodHandle(arr, 0, Long.MinValue)
+      SWARUtil.getLongBEWithoutMethodHandle(arr, 0) should ===(Long.MinValue)
+    }
+    "putLongLEWithoutMethodHandle" in {
+      val arr = new Array[Byte](16)
+
+      SWARUtil.putLongLEWithoutMethodHandle(arr, 0, 0x0001020304050607L)
+      arr.take(8).toSeq should ===(Seq[Byte](0x07, 0x06, 0x05, 0x04, 0x03, 
0x02, 0x01, 0x00))
+
+      SWARUtil.putLongLEWithoutMethodHandle(arr, 8, 0x08090A0B0C0D0E0FL)
+      arr.drop(8).toSeq should ===(Seq[Byte](0x0F, 0x0E, 0x0D, 0x0C, 0x0B, 
0x0A, 0x09, 0x08))
+
+      // round-trip
+      SWARUtil.putLongLEWithoutMethodHandle(arr, 0, Long.MaxValue)
+      SWARUtil.getLongLEWithoutMethodHandle(arr, 0) should ===(Long.MaxValue)
+      SWARUtil.putLongLEWithoutMethodHandle(arr, 0, Long.MinValue)
+      SWARUtil.getLongLEWithoutMethodHandle(arr, 0) should ===(Long.MinValue)
+    }
+    "putInt and getInt are inverses" in {
+      val arr = new Array[Byte](4)
+      for (value <- Seq(0, 1, -1, Int.MaxValue, Int.MinValue, 0x12345678)) {
+        SWARUtil.putInt(arr, 0, value, ByteOrder.BIG_ENDIAN)
+        SWARUtil.getInt(arr, 0, ByteOrder.BIG_ENDIAN) should ===(value)
+        SWARUtil.putInt(arr, 0, value, ByteOrder.LITTLE_ENDIAN)
+        SWARUtil.getInt(arr, 0, ByteOrder.LITTLE_ENDIAN) should ===(value)
+      }
+    }
+    "putLong and getLong are inverses" in {
+      val arr = new Array[Byte](8)
+      for (value <- Seq(0L, 1L, -1L, Long.MaxValue, Long.MinValue, 
0x123456789ABCDEF0L)) {
+        SWARUtil.putLong(arr, 0, value, ByteOrder.BIG_ENDIAN)
+        SWARUtil.getLong(arr, 0, ByteOrder.BIG_ENDIAN) should ===(value)
+        SWARUtil.putLong(arr, 0, value, ByteOrder.LITTLE_ENDIAN)
+        SWARUtil.getLong(arr, 0, ByteOrder.LITTLE_ENDIAN) should ===(value)
+      }
+    }
+    "putInt writes at correct offset" in {
+      val arr = new Array[Byte](6)
+      SWARUtil.putInt(arr, 1, 0x01020304, ByteOrder.BIG_ENDIAN)
+      arr(0) should ===(0.toByte)
+      arr(1) should ===(0x01.toByte)
+      arr(2) should ===(0x02.toByte)
+      arr(3) should ===(0x03.toByte)
+      arr(4) should ===(0x04.toByte)
+      arr(5) should ===(0.toByte)
+    }
+    "putLong writes at correct offset" in {
+      val arr = new Array[Byte](10)
+      SWARUtil.putLong(arr, 1, 0x0102030405060708L, ByteOrder.BIG_ENDIAN)
+      arr(0) should ===(0.toByte)
+      arr(1) should ===(0x01.toByte)
+      arr(2) should ===(0x02.toByte)
+      arr(3) should ===(0x03.toByte)
+      arr(4) should ===(0x04.toByte)
+      arr(5) should ===(0x05.toByte)
+      arr(6) should ===(0x06.toByte)
+      arr(7) should ===(0x07.toByte)
+      arr(8) should ===(0x08.toByte)
+      arr(9) should ===(0.toByte)
+    }
+    "putShort" in {
+      val arr = new Array[Byte](4)
+
+      SWARUtil.putShort(arr, 0, 0x0102, ByteOrder.BIG_ENDIAN)
+      arr.take(2).toSeq should ===(Seq[Byte](0x01, 0x02))
+
+      SWARUtil.putShort(arr, 2, 0x0304, ByteOrder.BIG_ENDIAN)
+      arr.drop(2).toSeq should ===(Seq[Byte](0x03, 0x04))
+
+      SWARUtil.putShort(arr, 0, 0x0102, ByteOrder.LITTLE_ENDIAN)
+      arr.take(2).toSeq should ===(Seq[Byte](0x02, 0x01))
+
+      SWARUtil.putShort(arr, 2, 0x0304, ByteOrder.LITTLE_ENDIAN)
+      arr.drop(2).toSeq should ===(Seq[Byte](0x04, 0x03))
+    }
+    "putShortBEWithoutMethodHandle" in {
+      val arr = new Array[Byte](4)
+
+      SWARUtil.putShortBEWithoutMethodHandle(arr, 0, 0x0102)
+      arr.take(2).toSeq should ===(Seq[Byte](0x01, 0x02))
+
+      SWARUtil.putShortBEWithoutMethodHandle(arr, 2, 0x0304)
+      arr.drop(2).toSeq should ===(Seq[Byte](0x03, 0x04))
+
+      // round-trip
+      SWARUtil.putShortBEWithoutMethodHandle(arr, 0, Short.MaxValue)
+      SWARUtil.getShortBEWithoutMethodHandle(arr, 0) should ===(Short.MaxValue)
+      SWARUtil.putShortBEWithoutMethodHandle(arr, 0, Short.MinValue)
+      SWARUtil.getShortBEWithoutMethodHandle(arr, 0) should ===(Short.MinValue)
+    }
+    "putShortLEWithoutMethodHandle" in {
+      val arr = new Array[Byte](4)
+
+      SWARUtil.putShortLEWithoutMethodHandle(arr, 0, 0x0102)
+      arr.take(2).toSeq should ===(Seq[Byte](0x02, 0x01))
+
+      SWARUtil.putShortLEWithoutMethodHandle(arr, 2, 0x0304)
+      arr.drop(2).toSeq should ===(Seq[Byte](0x04, 0x03))
+
+      // round-trip
+      SWARUtil.putShortLEWithoutMethodHandle(arr, 0, Short.MaxValue)
+      SWARUtil.getShortLEWithoutMethodHandle(arr, 0) should ===(Short.MaxValue)
+      SWARUtil.putShortLEWithoutMethodHandle(arr, 0, Short.MinValue)
+      SWARUtil.getShortLEWithoutMethodHandle(arr, 0) should ===(Short.MinValue)
+    }
+    "putShort and getShort are inverses" in {
+      val arr = new Array[Byte](2)
+      for (value <- Seq(0.toShort, 1.toShort, (-1).toShort, Short.MaxValue, 
Short.MinValue, 0x0102.toShort)) {
+        SWARUtil.putShort(arr, 0, value, ByteOrder.BIG_ENDIAN)
+        SWARUtil.getShort(arr, 0, ByteOrder.BIG_ENDIAN) should ===(value)
+        SWARUtil.putShort(arr, 0, value, ByteOrder.LITTLE_ENDIAN)
+        SWARUtil.getShort(arr, 0, ByteOrder.LITTLE_ENDIAN) should ===(value)
+      }
+    }
+    "putShort writes at correct offset" in {
+      val arr = new Array[Byte](4)
+      SWARUtil.putShort(arr, 1, 0x0102, ByteOrder.BIG_ENDIAN)
+      arr(0) should ===(0.toByte)
+      arr(1) should ===(0x01.toByte)
+      arr(2) should ===(0x02.toByte)
+      arr(3) should ===(0.toByte)
+    }
   }
 
 }
diff --git a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala 
b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
index a46e383334..43735db440 100644
--- a/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/ByteString.scala
@@ -2244,32 +2244,21 @@ final class ByteStringBuilder extends Builder[Byte, 
ByteString] {
    * Add a single Short to this builder.
    */
   def putShort(x: Int)(implicit byteOrder: ByteOrder): this.type = {
-    if (byteOrder == ByteOrder.BIG_ENDIAN) {
-      this += (x >>> 8).toByte
-      this += (x >>> 0).toByte
-    } else if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
-      this += (x >>> 0).toByte
-      this += (x >>> 8).toByte
-    } else throw new IllegalArgumentException("Unknown byte order " + 
byteOrder)
+    ensureTempSize(_tempLength + 2)
+    SWARUtil.putShort(_temp, _tempLength, x, byteOrder)
+    _tempLength += 2
+    _length += 2
+    this
   }
 
   /**
    * Add a single Int to this builder.
    */
   def putInt(x: Int)(implicit byteOrder: ByteOrder): this.type = {
-    fillArray(4) { (target, offset) =>
-      if (byteOrder == ByteOrder.BIG_ENDIAN) {
-        target(offset + 0) = (x >>> 24).toByte
-        target(offset + 1) = (x >>> 16).toByte
-        target(offset + 2) = (x >>> 8).toByte
-        target(offset + 3) = (x >>> 0).toByte
-      } else if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
-        target(offset + 0) = (x >>> 0).toByte
-        target(offset + 1) = (x >>> 8).toByte
-        target(offset + 2) = (x >>> 16).toByte
-        target(offset + 3) = (x >>> 24).toByte
-      } else throw new IllegalArgumentException("Unknown byte order " + 
byteOrder)
-    }
+    ensureTempSize(_tempLength + 4)
+    SWARUtil.putInt(_temp, _tempLength, x, byteOrder)
+    _tempLength += 4
+    _length += 4
     this
   }
 
@@ -2277,27 +2266,10 @@ final class ByteStringBuilder extends Builder[Byte, 
ByteString] {
    * Add a single Long to this builder.
    */
   def putLong(x: Long)(implicit byteOrder: ByteOrder): this.type = {
-    fillArray(8) { (target, offset) =>
-      if (byteOrder == ByteOrder.BIG_ENDIAN) {
-        target(offset + 0) = (x >>> 56).toByte
-        target(offset + 1) = (x >>> 48).toByte
-        target(offset + 2) = (x >>> 40).toByte
-        target(offset + 3) = (x >>> 32).toByte
-        target(offset + 4) = (x >>> 24).toByte
-        target(offset + 5) = (x >>> 16).toByte
-        target(offset + 6) = (x >>> 8).toByte
-        target(offset + 7) = (x >>> 0).toByte
-      } else if (byteOrder == ByteOrder.LITTLE_ENDIAN) {
-        target(offset + 0) = (x >>> 0).toByte
-        target(offset + 1) = (x >>> 8).toByte
-        target(offset + 2) = (x >>> 16).toByte
-        target(offset + 3) = (x >>> 24).toByte
-        target(offset + 4) = (x >>> 32).toByte
-        target(offset + 5) = (x >>> 40).toByte
-        target(offset + 6) = (x >>> 48).toByte
-        target(offset + 7) = (x >>> 56).toByte
-      } else throw new IllegalArgumentException("Unknown byte order " + 
byteOrder)
-    }
+    ensureTempSize(_tempLength + 8)
+    SWARUtil.putLong(_temp, _tempLength, x, byteOrder)
+    _tempLength += 8
+    _length += 8
     this
   }
 
diff --git a/actor/src/main/scala/org/apache/pekko/util/SWARUtil.scala 
b/actor/src/main/scala/org/apache/pekko/util/SWARUtil.scala
index ea65ddd683..7dc9d70d58 100644
--- a/actor/src/main/scala/org/apache/pekko/util/SWARUtil.scala
+++ b/actor/src/main/scala/org/apache/pekko/util/SWARUtil.scala
@@ -235,6 +235,84 @@ private[pekko] object SWARUtil {
     }
   }
 
+  /**
+   * Writes an int value at the specified index in the given byte array.
+   * Uses a VarHandle byte array view if supported, otherwise falls back to 
byte-by-byte writes.
+   * Does not range check - assumes caller has checked bounds.
+   *
+   * @param array     the byte array to write to
+   * @param index     the index to write at
+   * @param value     the int value to write
+   * @param byteOrder the byte order to use (big-endian or little-endian)
+   */
+  def putInt(array: Array[Byte], index: Int, value: Int, byteOrder: 
ByteOrder): Unit = {
+    if (byteOrder == ByteOrder.BIG_ENDIAN) {
+      if (intBeArrayViewSupported) {
+        intBeArrayView.set(array, index, value)
+      } else {
+        putIntBEWithoutMethodHandle(array, index, value)
+      }
+    } else {
+      if (intLeArrayViewSupported) {
+        intLeArrayView.set(array, index, value)
+      } else {
+        putIntLEWithoutMethodHandle(array, index, value)
+      }
+    }
+  }
+
+  /**
+   * Writes the low 16 bits of `value` at the specified index in the given 
byte array.
+   * Uses a VarHandle byte array view if supported, otherwise falls back to 
byte-by-byte writes.
+   * Does not range check - assumes caller has checked bounds.
+   *
+   * @param array     the byte array to write to
+   * @param index     the index to write at
+   * @param value     the value whose low 16 bits are written
+   * @param byteOrder the byte order to use (big-endian or little-endian)
+   */
+  def putShort(array: Array[Byte], index: Int, value: Int, byteOrder: 
ByteOrder): Unit = {
+    if (byteOrder == ByteOrder.BIG_ENDIAN) {
+      if (shortBeArrayViewSupported) {
+        shortBeArrayView.set(array, index, value.toShort)
+      } else {
+        putShortBEWithoutMethodHandle(array, index, value)
+      }
+    } else {
+      if (shortLeArrayViewSupported) {
+        shortLeArrayView.set(array, index, value.toShort)
+      } else {
+        putShortLEWithoutMethodHandle(array, index, value)
+      }
+    }
+  }
+
+  /**
+   * Writes a long value at the specified index in the given byte array.
+   * Uses a VarHandle byte array view if supported, otherwise falls back to 
byte-by-byte writes.
+   * Does not range check - assumes caller has checked bounds.
+   *
+   * @param array     the byte array to write to
+   * @param index     the index to write at
+   * @param value     the long value to write
+   * @param byteOrder the byte order to use (big-endian or little-endian)
+   */
+  def putLong(array: Array[Byte], index: Int, value: Long, byteOrder: 
ByteOrder): Unit = {
+    if (byteOrder == ByteOrder.BIG_ENDIAN) {
+      if (longBeArrayViewSupported) {
+        longBeArrayView.set(array, index, value)
+      } else {
+        putLongBEWithoutMethodHandle(array, index, value)
+      }
+    } else {
+      if (longLeArrayViewSupported) {
+        longLeArrayView.set(array, index, value)
+      } else {
+        putLongLEWithoutMethodHandle(array, index, value)
+      }
+    }
+  }
+
   // Fallback implementations for environments that do not support 
MethodHandles.byteArrayViewVarHandle
 
   private[pekko] def getLongBEWithoutMethodHandle(array: Array[Byte], index: 
Int): Long = {
@@ -279,4 +357,50 @@ private[pekko] object SWARUtil {
   private[pekko] def getShortLEWithoutMethodHandle(array: Array[Byte], index: 
Int): Short =
     ((array(index) & 0xFF) | (array(index + 1) & 0xFF) << 8).toShort
 
+  private[pekko] def putIntBEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Int): Unit = {
+    array(index) = (value >>> 24).toByte
+    array(index + 1) = (value >>> 16).toByte
+    array(index + 2) = (value >>> 8).toByte
+    array(index + 3) = value.toByte
+  }
+
+  private[pekko] def putIntLEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Int): Unit = {
+    array(index) = value.toByte
+    array(index + 1) = (value >>> 8).toByte
+    array(index + 2) = (value >>> 16).toByte
+    array(index + 3) = (value >>> 24).toByte
+  }
+
+  private[pekko] def putShortBEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Int): Unit = {
+    array(index) = (value >>> 8).toByte
+    array(index + 1) = value.toByte
+  }
+
+  private[pekko] def putShortLEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Int): Unit = {
+    array(index) = value.toByte
+    array(index + 1) = (value >>> 8).toByte
+  }
+
+  private[pekko] def putLongBEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Long): Unit = {
+    array(index) = (value >>> 56).toByte
+    array(index + 1) = (value >>> 48).toByte
+    array(index + 2) = (value >>> 40).toByte
+    array(index + 3) = (value >>> 32).toByte
+    array(index + 4) = (value >>> 24).toByte
+    array(index + 5) = (value >>> 16).toByte
+    array(index + 6) = (value >>> 8).toByte
+    array(index + 7) = value.toByte
+  }
+
+  private[pekko] def putLongLEWithoutMethodHandle(array: Array[Byte], index: 
Int, value: Long): Unit = {
+    array(index) = value.toByte
+    array(index + 1) = (value >>> 8).toByte
+    array(index + 2) = (value >>> 16).toByte
+    array(index + 3) = (value >>> 24).toByte
+    array(index + 4) = (value >>> 32).toByte
+    array(index + 5) = (value >>> 40).toByte
+    array(index + 6) = (value >>> 48).toByte
+    array(index + 7) = (value >>> 56).toByte
+  }
+
 }
diff --git 
a/bench-jmh/src/main/scala/org/apache/pekko/util/ByteString_putInt_Benchmark.scala
 
b/bench-jmh/src/main/scala/org/apache/pekko/util/ByteString_putInt_Benchmark.scala
new file mode 100644
index 0000000000..74b0b4d992
--- /dev/null
+++ 
b/bench-jmh/src/main/scala/org/apache/pekko/util/ByteString_putInt_Benchmark.scala
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * license agreements; and to You under the Apache License, version 2.0:
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * This file is part of the Apache Pekko project, which was derived from Akka.
+ */
+
+/*
+ * Copyright (C) 2014-2022 Lightbend Inc. <https://www.lightbend.com>
+ */
+
+package org.apache.pekko.util
+
+import java.util.concurrent.TimeUnit
+
+import org.openjdk.jmh.annotations._
+import org.openjdk.jmh.infra.Blackhole
+
+@State(Scope.Benchmark)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@BenchmarkMode(Array(Mode.Throughput))
+@Fork(2)
+@Warmup(iterations = 5)
+@Measurement(iterations = 10)
+class ByteString_putInt_Benchmark {
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putShortBE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0
+    while (i < 1000) {
+      builder.putShort(i)(java.nio.ByteOrder.BIG_ENDIAN)
+      i += 1
+    }
+    bh.consume(builder.result())
+  }
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putShortLE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0
+    while (i < 1000) {
+      builder.putShort(i)(java.nio.ByteOrder.LITTLE_ENDIAN)
+      i += 1
+    }
+    bh.consume(builder.result())
+  }
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putIntBE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0
+    while (i < 1000) {
+      builder.putInt(i)(java.nio.ByteOrder.BIG_ENDIAN)
+      i += 1
+    }
+    bh.consume(builder.result())
+  }
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putIntLE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0
+    while (i < 1000) {
+      builder.putInt(i)(java.nio.ByteOrder.LITTLE_ENDIAN)
+      i += 1
+    }
+    bh.consume(builder.result())
+  }
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putLongBE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0L
+    while (i < 1000L) {
+      builder.putLong(i)(java.nio.ByteOrder.BIG_ENDIAN)
+      i += 1L
+    }
+    bh.consume(builder.result())
+  }
+
+  @Benchmark
+  @OperationsPerInvocation(1000)
+  def putLongLE(bh: Blackhole): Unit = {
+    val builder = ByteString.newBuilder
+    var i = 0L
+    while (i < 1000L) {
+      builder.putLong(i)(java.nio.ByteOrder.LITTLE_ENDIAN)
+      i += 1L
+    }
+    bh.consume(builder.result())
+  }
+
+}
diff --git 
a/persistence/src/main/scala/org/apache/pekko/persistence/serialization/SnapshotSerializer.scala
 
b/persistence/src/main/scala/org/apache/pekko/persistence/serialization/SnapshotSerializer.scala
index 200c835ff6..3539ce85fb 100644
--- 
a/persistence/src/main/scala/org/apache/pekko/persistence/serialization/SnapshotSerializer.scala
+++ 
b/persistence/src/main/scala/org/apache/pekko/persistence/serialization/SnapshotSerializer.scala
@@ -13,7 +13,7 @@
 
 package org.apache.pekko.persistence.serialization
 
-import java.io._
+import java.io.NotSerializableException
 import java.nio.ByteOrder
 
 import org.apache.pekko
@@ -81,13 +81,18 @@ class SnapshotSerializer(val system: ExtendedActorSystem) 
extends BaseSerializer
     Snapshot(snapshotFromBinary(bytes))
 
   private def headerToBinary(snapshot: AnyRef, snapshotSerializer: 
Serializer): Array[Byte] = {
-    val out = new ByteArrayOutputStream
-    writeInt(out, snapshotSerializer.identifier)
-
     val ms = 
migrateManifestIfNecessary(Serializers.manifestFor(snapshotSerializer, 
snapshot))
-    if (ms.nonEmpty) out.write(ms.getBytes(UTF_8))
-
-    out.toByteArray
+    if (ms.isEmpty) {
+      val result = new Array[Byte](4)
+      SWARUtil.putInt(result, 0, snapshotSerializer.identifier, 
ByteOrder.LITTLE_ENDIAN)
+      result
+    } else {
+      val manifestBytes = ms.getBytes(UTF_8)
+      val result = new Array[Byte](4 + manifestBytes.length)
+      SWARUtil.putInt(result, 0, snapshotSerializer.identifier, 
ByteOrder.LITTLE_ENDIAN)
+      System.arraycopy(manifestBytes, 0, result, 4, manifestBytes.length)
+      result
+    }
   }
 
   private def headerFromBinary(bytes: Array[Byte]): (Int, String) = {
@@ -146,14 +151,13 @@ class SnapshotSerializer(val system: ExtendedActorSystem) 
extends BaseSerializer
       val snapshotSerializer = serialization.findSerializerFor(snapshot)
 
       val headerBytes = headerToBinary(snapshot, snapshotSerializer)
+      val snapshotBytes = snapshotSerializer.toBinary(snapshot)
 
-      val out = new ByteArrayOutputStream
-
-      writeInt(out, headerBytes.length)
-
-      out.write(headerBytes)
-      out.write(snapshotSerializer.toBinary(snapshot))
-      out.toByteArray
+      val result = new Array[Byte](4 + headerBytes.length + 
snapshotBytes.length)
+      SWARUtil.putInt(result, 0, headerBytes.length, ByteOrder.LITTLE_ENDIAN)
+      System.arraycopy(headerBytes, 0, result, 4, headerBytes.length)
+      System.arraycopy(snapshotBytes, 0, result, 4 + headerBytes.length, 
snapshotBytes.length)
+      result
     }
 
     val oldInfo = Serialization.currentTransportInformation.value
@@ -176,10 +180,4 @@ class SnapshotSerializer(val system: ExtendedActorSystem) 
extends BaseSerializer
       .get
   }
 
-  private def writeInt(out: OutputStream, i: Int): Unit = {
-    out.write(i >>> 0)
-    out.write(i >>> 8)
-    out.write(i >>> 16)
-    out.write(i >>> 24)
-  }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to