=act clean up ByteString#drop(...) (#21440)
* =act clean up ByteString#drop(...) Current implementation has a good algorithm but seems a little bit complicated. Clening-up does not suffer the performance (actually seems to have the better performance when dropping(N-1)) where N is the length, and is easy to understand almost the same algorithm now. * Change private[akka] to priavte * Rename go(...) and some variables They should be easy for us to understand what they are. * Add benchmark of ByteString#drop(...)
This commit is contained in:
parent
cc845c84b0
commit
19dbe9a487
3 changed files with 150 additions and 70 deletions
|
|
@ -485,32 +485,24 @@ object ByteString {
|
|||
else drop0(n)
|
||||
|
||||
private def drop0(n: Int): ByteString = {
|
||||
var continue = true
|
||||
var fullDrops = 0
|
||||
var remainingToDrop = n
|
||||
do {
|
||||
// impl note: could be optimised a bit by using VectorIterator instead,
|
||||
// however then we're forced to call .toVector which halfs performance
|
||||
// We can work around that, as there's a Scala private method "remainingVector" which is fast,
|
||||
// but let's not go into calling private APIs here just yet.
|
||||
val currentLength = bytestrings(fullDrops).length
|
||||
if (remainingToDrop >= currentLength) {
|
||||
fullDrops += 1
|
||||
remainingToDrop -= currentLength
|
||||
} else continue = false
|
||||
} while (remainingToDrop > 0 && continue)
|
||||
// impl note: could be optimised a bit by using VectorIterator instead,
|
||||
// however then we're forced to call .toVector which halfs performance
|
||||
// We can work around that, as there's a Scala private method "remainingVector" which is fast,
|
||||
// but let's not go into calling private APIs here just yet.
|
||||
@tailrec def findSplit(fullDrops: Int, remainingToDrop: Int): (Int, Int) = {
|
||||
val bs = bytestrings(fullDrops)
|
||||
if (bs.length > remainingToDrop) (fullDrops, remainingToDrop)
|
||||
else findSplit(fullDrops + 1, remainingToDrop - bs.length)
|
||||
}
|
||||
|
||||
val remainingByteStrings = bytestrings.drop(fullDrops)
|
||||
if (remainingByteStrings.isEmpty) ByteString.empty
|
||||
else if (remainingToDrop > 0) {
|
||||
val h: ByteString1 = remainingByteStrings.head.drop1(remainingToDrop)
|
||||
val bs = remainingByteStrings.tail
|
||||
val (fullDrops, remainingToDrop) = findSplit(0, n)
|
||||
|
||||
if (h.isEmpty)
|
||||
if (bs.isEmpty) ByteString.empty
|
||||
else new ByteStrings(bs, length - n)
|
||||
else new ByteStrings(h +: bs, length - n)
|
||||
} else ByteStrings(remainingByteStrings, length - n)
|
||||
if (remainingToDrop == 0)
|
||||
new ByteStrings(bytestrings.drop(fullDrops), length - n)
|
||||
else if (fullDrops == bytestrings.length - 1)
|
||||
bytestrings(fullDrops).drop(remainingToDrop)
|
||||
else
|
||||
new ByteStrings(bytestrings(fullDrops).drop1(remainingToDrop) +: bytestrings.drop(fullDrops + 1), length - n)
|
||||
}
|
||||
|
||||
protected def writeReplace(): AnyRef = new SerializationProxy(this)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue