From f8a47eae3edf853a9e410f810985f96d35ed3d35 Mon Sep 17 00:00:00 2001 From: Desmond Yeung Date: Mon, 24 Jan 2022 14:53:42 -0500 Subject: [PATCH] Optimize apply for fragmented ByteStrings (#31070) (#31075) --- .../scala-2.12/akka/util/ByteString.scala | 8 ++-- .../scala-2.13/akka/util/ByteString.scala | 8 ++-- .../main/scala-3/akka/util/ByteString.scala | 8 ++-- .../util/ByteString_apply_Benchmark.scala | 44 +++++++++++++++++++ 4 files changed, 59 insertions(+), 9 deletions(-) create mode 100644 akka-bench-jmh/src/main/scala/akka/util/ByteString_apply_Benchmark.scala diff --git a/akka-actor/src/main/scala-2.12/akka/util/ByteString.scala b/akka-actor/src/main/scala-2.12/akka/util/ByteString.scala index 8073c0b73b..00a68a316c 100644 --- a/akka-actor/src/main/scala-2.12/akka/util/ByteString.scala +++ b/akka-actor/src/main/scala-2.12/akka/util/ByteString.scala @@ -500,11 +500,13 @@ object ByteString { if (0 <= idx && idx < length) { var pos = 0 var seen = 0 - while (idx >= seen + bytestrings(pos).length) { - seen += bytestrings(pos).length + var frag = bytestrings(pos) + while (idx >= seen + frag.length) { + seen += frag.length pos += 1 + frag = bytestrings(pos) } - bytestrings(pos)(idx - seen) + frag(idx - seen) } else throw new IndexOutOfBoundsException(idx.toString) } diff --git a/akka-actor/src/main/scala-2.13/akka/util/ByteString.scala b/akka-actor/src/main/scala-2.13/akka/util/ByteString.scala index e4e5643df5..2be86938e1 100644 --- a/akka-actor/src/main/scala-2.13/akka/util/ByteString.scala +++ b/akka-actor/src/main/scala-2.13/akka/util/ByteString.scala @@ -517,11 +517,13 @@ object ByteString { if (0 <= idx && idx < length) { var pos = 0 var seen = 0 - while (idx >= seen + bytestrings(pos).length) { - seen += bytestrings(pos).length + var frag = bytestrings(pos) + while (idx >= seen + frag.length) { + seen += frag.length pos += 1 + frag = bytestrings(pos) } - bytestrings(pos)(idx - seen) + frag(idx - seen) } else throw new IndexOutOfBoundsException(idx.toString) } diff --git a/akka-actor/src/main/scala-3/akka/util/ByteString.scala b/akka-actor/src/main/scala-3/akka/util/ByteString.scala index a5413f552d..9cf859b5c6 100644 --- a/akka-actor/src/main/scala-3/akka/util/ByteString.scala +++ b/akka-actor/src/main/scala-3/akka/util/ByteString.scala @@ -518,11 +518,13 @@ object ByteString { if (0 <= idx && idx < length) { var pos = 0 var seen = 0 - while (idx >= seen + bytestrings(pos).length) { - seen += bytestrings(pos).length + var frag = bytestrings(pos) + while (idx >= seen + frag.length) { + seen += frag.length pos += 1 + frag = bytestrings(pos) } - bytestrings(pos)(idx - seen) + frag(idx - seen) } else throw new IndexOutOfBoundsException(idx.toString) } diff --git a/akka-bench-jmh/src/main/scala/akka/util/ByteString_apply_Benchmark.scala b/akka-bench-jmh/src/main/scala/akka/util/ByteString_apply_Benchmark.scala new file mode 100644 index 0000000000..50310cba97 --- /dev/null +++ b/akka-bench-jmh/src/main/scala/akka/util/ByteString_apply_Benchmark.scala @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2014-2021 Lightbend Inc. + */ + +package akka.util + +import java.util.concurrent.TimeUnit + +import org.openjdk.jmh.annotations._ + +import akka.util.ByteString.{ ByteString1, ByteStrings } + +@State(Scope.Benchmark) +@Measurement(timeUnit = TimeUnit.MILLISECONDS) +class ByteString_apply_Benchmark { + + val bss = ByteStrings(Vector.fill(1024)(ByteString1(Array(0.toByte)))) + + /* + akka-bench-jmh/jmh:run -f 1 -wi 3 -i 3 .*ByteString_apply_Benchmark.* + + 2.12 original + ByteString_apply_Benchmark.bss_apply_best_case thrpt 3 204261596.303 ± 94507102.894 ops/s + ByteString_apply_Benchmark.bss_apply_worst_case thrpt 3 170359.149 ± 102901.206 ops/s + + 2.12 optimized + ByteString_apply_Benchmark.bss_apply_best_case thrpt 3 206985005.270 ± 7855543.098 ops/s + ByteString_apply_Benchmark.bss_apply_worst_case thrpt 3 437929.845 ± 27264.190 ops/s + + 2.13 original + ByteString_apply_Benchmark.bss_apply_best_case thrpt 3 206854021.793 ± 81500220.451 ops/s + ByteString_apply_Benchmark.bss_apply_worst_case thrpt 3 237125.194 ± 128394.832 ops/s + + 2.13 optimized + ByteString_apply_Benchmark.bss_apply_best_case thrpt 3 209266780.913 ± 6821134.296 ops/s + ByteString_apply_Benchmark.bss_apply_worst_case thrpt 3 430348.094 ± 24412.915 ops/s + */ + + @Benchmark + def bss_apply_best_case: Byte = bss(0) + + @Benchmark + def bss_apply_worst_case: Byte = bss(1023) +}