=act improve ByteString#dropRight(...) (#21439)
#21439: =act improve ByteString#dropRight(...)
This commit is contained in:
parent
8d05592e2e
commit
c38d3850a2
3 changed files with 166 additions and 22 deletions
|
|
@ -309,6 +309,23 @@ class ByteStringSpec extends WordSpec with Matchers with Checkers {
|
|||
ByteString1.fromString("0123456789").drop(1).take(2) should ===(ByteString("12"))
|
||||
ByteString1.fromString("0123456789").drop(5).take(4).drop(1).take(2) should ===(ByteString("67"))
|
||||
}
|
||||
"dropRight" in {
|
||||
ByteString1.empty.dropRight(-1) should ===(ByteString(""))
|
||||
ByteString1.empty.dropRight(0) should ===(ByteString(""))
|
||||
ByteString1.empty.dropRight(1) should ===(ByteString(""))
|
||||
ByteString1.fromString("a").dropRight(-1) should ===(ByteString("a"))
|
||||
ByteString1.fromString("a").dropRight(0) should ===(ByteString("a"))
|
||||
ByteString1.fromString("a").dropRight(1) should ===(ByteString(""))
|
||||
ByteString1.fromString("a").dropRight(2) should ===(ByteString(""))
|
||||
ByteString1.fromString("abc").dropRight(-1) should ===(ByteString("abc"))
|
||||
ByteString1.fromString("abc").dropRight(0) should ===(ByteString("abc"))
|
||||
ByteString1.fromString("abc").dropRight(1) should ===(ByteString("ab"))
|
||||
ByteString1.fromString("abc").dropRight(2) should ===(ByteString("a"))
|
||||
ByteString1.fromString("abc").dropRight(3) should ===(ByteString(""))
|
||||
ByteString1.fromString("abc").dropRight(4) should ===(ByteString(""))
|
||||
ByteString1.fromString("0123456789").dropRight(1).take(2) should ===(ByteString("01"))
|
||||
ByteString1.fromString("0123456789").dropRight(5).take(4).drop(1).take(2) should ===(ByteString("12"))
|
||||
}
|
||||
"take" in {
|
||||
ByteString1.empty.take(-1) should ===(ByteString(""))
|
||||
ByteString1.empty.take(0) should ===(ByteString(""))
|
||||
|
|
@ -341,6 +358,23 @@ class ByteStringSpec extends WordSpec with Matchers with Checkers {
|
|||
ByteString1C.fromString("0123456789").drop(1).take(2) should ===(ByteString("12"))
|
||||
ByteString1C.fromString("0123456789").drop(5).take(4).drop(1).take(2) should ===(ByteString("67"))
|
||||
}
|
||||
"dropRight" in {
|
||||
ByteString1C.fromString("").dropRight(-1) should ===(ByteString(""))
|
||||
ByteString1C.fromString("").dropRight(0) should ===(ByteString(""))
|
||||
ByteString1C.fromString("").dropRight(1) should ===(ByteString(""))
|
||||
ByteString1C.fromString("a").dropRight(-1) should ===(ByteString("a"))
|
||||
ByteString1C.fromString("a").dropRight(0) should ===(ByteString("a"))
|
||||
ByteString1C.fromString("a").dropRight(1) should ===(ByteString(""))
|
||||
ByteString1C.fromString("a").dropRight(2) should ===(ByteString(""))
|
||||
ByteString1C.fromString("abc").dropRight(-1) should ===(ByteString("abc"))
|
||||
ByteString1C.fromString("abc").dropRight(0) should ===(ByteString("abc"))
|
||||
ByteString1C.fromString("abc").dropRight(1) should ===(ByteString("ab"))
|
||||
ByteString1C.fromString("abc").dropRight(2) should ===(ByteString("a"))
|
||||
ByteString1C.fromString("abc").dropRight(3) should ===(ByteString(""))
|
||||
ByteString1C.fromString("abc").dropRight(4) should ===(ByteString(""))
|
||||
ByteString1C.fromString("0123456789").dropRight(1).take(2) should ===(ByteString("01"))
|
||||
ByteString1C.fromString("0123456789").dropRight(5).take(4).drop(1).take(2) should ===(ByteString("12"))
|
||||
}
|
||||
"take" in {
|
||||
ByteString1.fromString("abcdefg").drop(1).take(0) should ===(ByteString(""))
|
||||
ByteString1.fromString("abcdefg").drop(1).take(-1) should ===(ByteString(""))
|
||||
|
|
@ -392,6 +426,48 @@ class ByteStringSpec extends WordSpec with Matchers with Checkers {
|
|||
ByteString("0123456789").drop(5).drop(3).take(1) should ===(ByteString("8"))
|
||||
(ByteString1C.fromString("a") ++ ByteString1.fromString("bc")).drop(2) should ===(ByteString("c"))
|
||||
}
|
||||
"dropRight" in {
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("")).dropRight(Int.MinValue) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("")).dropRight(-1) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("")).dropRight(0) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("")).dropRight(1) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("")).dropRight(Int.MaxValue) should ===(ByteString(""))
|
||||
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(Int.MinValue) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(-1) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(0) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(1) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(2) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(Int.MaxValue) should ===(ByteString(""))
|
||||
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(Int.MinValue) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(-1) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(0) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(1) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(2) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).dropRight(Int.MaxValue) should ===(ByteString(""))
|
||||
|
||||
val bss = ByteStrings(Vector(
|
||||
ByteString1.fromString("a"),
|
||||
ByteString1.fromString("bc"),
|
||||
ByteString1.fromString("def")))
|
||||
|
||||
bss.dropRight(Int.MinValue) should ===(ByteString("abcdef"))
|
||||
bss.dropRight(-1) should ===(ByteString("abcdef"))
|
||||
bss.dropRight(0) should ===(ByteString("abcdef"))
|
||||
bss.dropRight(1) should ===(ByteString("abcde"))
|
||||
bss.dropRight(2) should ===(ByteString("abcd"))
|
||||
bss.dropRight(3) should ===(ByteString("abc"))
|
||||
bss.dropRight(4) should ===(ByteString("ab"))
|
||||
bss.dropRight(5) should ===(ByteString("a"))
|
||||
bss.dropRight(6) should ===(ByteString(""))
|
||||
bss.dropRight(7) should ===(ByteString(""))
|
||||
bss.dropRight(Int.MaxValue) should ===(ByteString(""))
|
||||
|
||||
ByteString("0123456789").dropRight(5).take(2) should ===(ByteString("01"))
|
||||
ByteString("0123456789").dropRight(5).drop(3).take(1) should ===(ByteString("3"))
|
||||
(ByteString1C.fromString("a") ++ ByteString1.fromString("bc")).dropRight(2) should ===(ByteString("a"))
|
||||
}
|
||||
"slice" in {
|
||||
ByteStrings(ByteString1.fromString(""), ByteString1.fromString("a")).slice(1, 1) should ===(ByteString(""))
|
||||
// We explicitly test all edge cases to always test them, refs bug #21237
|
||||
|
|
@ -436,16 +512,6 @@ class ByteStringSpec extends WordSpec with Matchers with Checkers {
|
|||
// Get an empty if `from` is greater than `until`
|
||||
ByteStrings(ByteString1.fromString("ab"), ByteString1.fromString("cd")).slice(4, 0) should ===(ByteString(""))
|
||||
}
|
||||
"dropRight" in {
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(0) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(-1) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(Int.MinValue) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(1) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("")).dropRight(Int.MaxValue) should ===(ByteString(""))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("bc")).dropRight(1) should ===(ByteString("ab"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("bc")).dropRight(2) should ===(ByteString("a"))
|
||||
ByteStrings(ByteString1.fromString("a"), ByteString1.fromString("bc")).dropRight(3) should ===(ByteString(""))
|
||||
}
|
||||
"take" in {
|
||||
ByteString.empty.take(-1) should ===(ByteString(""))
|
||||
ByteString.empty.take(0) should ===(ByteString(""))
|
||||
|
|
|
|||
|
|
@ -487,19 +487,27 @@ object ByteString {
|
|||
}
|
||||
|
||||
override def dropRight(n: Int): ByteString =
|
||||
if (n <= 0) this
|
||||
else {
|
||||
val last = bytestrings.last
|
||||
if (n < last.length) new ByteStrings(bytestrings.init :+ last.dropRight1(n), length - n)
|
||||
else {
|
||||
val remaining = bytestrings.init
|
||||
if (remaining.isEmpty) ByteString.empty
|
||||
else {
|
||||
val s = new ByteStrings(remaining, length - last.length)
|
||||
val remainingToBeDropped = n - last.length
|
||||
s.dropRight(remainingToBeDropped)
|
||||
if (0 < n && n < length) dropRight0(n)
|
||||
else if (n >= length) ByteString.empty
|
||||
else this
|
||||
|
||||
private def dropRight0(n: Int): ByteString = {
|
||||
val byteStringsSize = bytestrings.length
|
||||
@tailrec def dropRightWithFullDropsAndRemainig(fullDrops: Int, remainingToDrop: Int): ByteString = {
|
||||
val bs = bytestrings(byteStringsSize - fullDrops - 1)
|
||||
if (bs.length > remainingToDrop) {
|
||||
if (fullDrops == byteStringsSize - 1)
|
||||
bytestrings(0).dropRight(remainingToDrop)
|
||||
else if (remainingToDrop == 0)
|
||||
new ByteStrings(bytestrings.dropRight(fullDrops), length - n)
|
||||
else
|
||||
new ByteStrings(bytestrings.dropRight(fullDrops + 1) :+ bytestrings(byteStringsSize - fullDrops - 1).dropRight1(remainingToDrop), length - n)
|
||||
} else {
|
||||
dropRightWithFullDropsAndRemainig(fullDrops + 1, remainingToDrop - bs.length)
|
||||
}
|
||||
}
|
||||
|
||||
dropRightWithFullDropsAndRemainig(0, n)
|
||||
}
|
||||
|
||||
override def slice(from: Int, until: Int): ByteString =
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
/**
|
||||
* Copyright (C) 2014-2016 Lightbend Inc. <http://www.lightbend.com>
|
||||
*/
|
||||
package akka.util
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
import akka.util.ByteString.{ ByteString1, ByteStrings }
|
||||
import org.openjdk.jmh.annotations._
|
||||
|
||||
import scala.util.Random
|
||||
|
||||
@State(Scope.Benchmark)
|
||||
@Measurement(timeUnit = TimeUnit.MILLISECONDS)
|
||||
class ByteString_dropRight_Benchmark {
|
||||
|
||||
val str = List.fill[Byte](4)(0).mkString
|
||||
val numVec = 1024
|
||||
val bss = ByteStrings(Vector.fill(numVec)(ByteString1.fromString(str)))
|
||||
|
||||
val rand = new Random()
|
||||
val len = str.size * numVec
|
||||
val n_greater_or_eq_to_len = len + rand.nextInt(Int.MaxValue - len)
|
||||
val n_neg = rand.nextInt(Int.MaxValue) * -1
|
||||
val n_avg = len / 2
|
||||
val n_best = 1
|
||||
val n_worst = len - 1
|
||||
|
||||
/*
|
||||
--------------------------------- BASELINE -----------------------------------------------------------------------
|
||||
commit 0f2da7b26b5c4af35be87d2bd4a1a2392365df15
|
||||
[info] Benchmark Mode Cnt Score Error Units
|
||||
[info] ByteString_dropRight_Benchmark.bss_avg thrpt 40 25626.311 ± 1395.662 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_best thrpt 40 8667558.031 ± 200233.008 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_greater_or_eq_to_len thrpt 40 12658.684 ± 376.730 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_negative thrpt 40 1214680926.895 ± 10661843.507 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_worst thrpt 40 13087.245 ± 246.911 ops/s
|
||||
|
||||
--------------------------------- AFTER --------------------------------------------------------------------------
|
||||
|
||||
------ TODAY –––––––
|
||||
[info] Benchmark Mode Cnt Score Error Units
|
||||
[info] ByteString_dropRight_Benchmark.bss_avg thrpt 40 528969.025 ± 6039.001 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_best thrpt 40 7925951.396 ± 249279.950 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_greater_or_eq_to_len thrpt 40 893475724.604 ± 9836471.105 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_negative thrpt 40 1182275022.613 ± 9710755.955 ops/s
|
||||
[info] ByteString_dropRight_Benchmark.bss_worst thrpt 40 244599.957 ± 3276.140 ops/s
|
||||
|
||||
*/
|
||||
|
||||
@Benchmark
|
||||
def bss_negative(): ByteString =
|
||||
bss.dropRight(n_neg)
|
||||
|
||||
@Benchmark
|
||||
def bss_greater_or_eq_to_len(): ByteString =
|
||||
bss.dropRight(n_greater_or_eq_to_len)
|
||||
|
||||
@Benchmark
|
||||
def bss_avg(): ByteString =
|
||||
bss.dropRight(n_avg)
|
||||
|
||||
@Benchmark
|
||||
def bss_best(): ByteString =
|
||||
bss.dropRight(n_best)
|
||||
|
||||
@Benchmark
|
||||
def bss_worst(): ByteString =
|
||||
bss.dropRight(n_worst)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue