Implement optimized removeRange for ArrayDeque #KT-64956

Test ArrayDeque with size 15. With the existing sizes the removeRange
implementation couldn't reach the maximum number of iterations - 3.

Benchmark results for ArrayDeque.subList().clear() that uses
removeRange() can be found here:
https://github.com/qurbonzoda/KotlinArrayDequeBenchmarks/tree/master/results
This commit is contained in:
Abduqodiri Qurbonzoda
2024-01-30 16:01:14 +02:00
committed by Space Team
parent 240a423bed
commit b67ebf36a2
5 changed files with 128 additions and 7 deletions
@@ -352,7 +352,7 @@ class ArrayDequeTest {
}
private fun testArrayDeque(test: (bufferSize: Int, dequeSize: Int, head: Int, tail: Int) -> Unit) {
for (bufferSize in listOf(0, 2, 8)) {
for (bufferSize in listOf(0, 2, 8, 15)) {
for (dequeSize in 0..bufferSize) {
for (tail in 0 until bufferSize) {
val head = tail - dequeSize
@@ -609,6 +609,40 @@ class ArrayDequeTest {
}
}
@Test
fun removeRange() = testArrayDeque { bufferSize: Int, dequeSize: Int, head: Int, tail: Int ->
for (fromIndex in 0..dequeSize) {
for (toIndex in fromIndex..dequeSize) {
val deque = generateArrayDeque(head, tail, bufferSize).apply { testRemoveRange(fromIndex, toIndex) }
val length = toIndex - fromIndex
val expectedHead = when {
length == 0 -> head
length == dequeSize -> 0
fromIndex < dequeSize - toIndex -> head + length // shift preceding elements
else -> // shift succeeding elements
if (tail <= length - 1)
head + bufferSize // head becomes positive(head < tail)
else
head
}
val expectedElements = (head until tail).toMutableList().apply {
repeat(length) { removeAt(fromIndex) }
}
deque.internalStructure { actualHead, actualElements ->
assertEquals(
expectedHead,
actualHead,
"bufferSize: $bufferSize, head: $head, tail: $tail, fromIndex: $fromIndex, toIndex: $toIndex"
)
assertEquals(expectedElements, actualElements.toList())
}
}
}
}
@Suppress("INVISIBLE_MEMBER")
@Test
fun toArray() {