float list: optimize FragmentedArrayFloatList::add(HeapArrayFloatList)

This commit is contained in:
Moritz Zwerger 2025-03-27 20:04:49 +01:00
parent c0bf5efe7b
commit e753b8e447
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4

View File

@ -14,7 +14,10 @@
package de.bixilon.minosoft.util.collections.floats
import de.bixilon.kutil.collections.primitive.floats.AbstractFloatList
import de.bixilon.kutil.collections.primitive.floats.HeapArrayFloatList
import de.bixilon.kutil.exception.Broken
import de.bixilon.kutil.reflection.ReflectionUtil.field
import de.bixilon.kutil.reflection.ReflectionUtil.getFieldOrNull
import de.bixilon.minosoft.util.collections.floats.FloatListUtil.copy
import org.lwjgl.system.MemoryUtil.memAllocFloat
import org.lwjgl.system.MemoryUtil.memFree
@ -192,39 +195,42 @@ class FragmentedArrayFloatList(
return true
}
override fun add(array: FloatArray) {
if (array.isEmpty()) return
fun add(array: FloatArray, offset: Int, length: Int) {
if (offset + length > array.size) throw IndexOutOfBoundsException("Index ${offset + length} out of bounds!")
if (length == 0) return
checkFinished()
invalidateOutput()
var offset = 0
var indexOffset = 0
for (index in 0 until incomplete.size) {
val fragment = incomplete[index + indexOffset]
val remaining = fragment.limit() - fragment.position()
val copy = minOf(array.size - offset, remaining)
var offset = offset
var left = length
var fragmentOffset = 0 // avoid ConcurrentModificationException when pushing list
for (fragmentIndex in 0 until incomplete.size) {
val fragment = incomplete[fragmentIndex + fragmentOffset]
val capacity = fragment.limit() - fragment.position()
val copy = minOf(left, capacity)
fragment.put(array, offset, copy)
offset += copy
if (tryPush(fragment)) indexOffset--
left -= copy
if (tryPush(fragment)) fragmentOffset-- // fragment not anymore in the list (shifted)
this.size += copy // tryPush needs the current size
if (array.size == offset) {
// everything copied
size += array.size
// verifyPosition()
return
}
if (left == 0) break
}
if (left > 0) {
val next = tryGrow(left)
next.put(array, offset, left)
tryPush(next)
this.size += left
}
size += offset
val length = array.size - offset
val next = tryGrow(length)
next.put(array, offset, length)
size += length
next.position(length)
tryPush(next)
// verifyPosition()
}
override fun add(array: FloatArray) = add(array, 0, array.size)
override fun add(buffer: FloatBuffer) {
if (buffer.position() == 0) return
checkFinished()
@ -266,6 +272,7 @@ class FragmentedArrayFloatList(
}
is DirectArrayFloatList -> add(floatList.toBuffer())
is HeapArrayFloatList -> add(HEAP_DATA[floatList], 0, floatList.size)
else -> add(floatList.toArray())
}
invalidateOutput()
@ -377,4 +384,9 @@ class FragmentedArrayFloatList(
Broken("Buffer size mismatch: expected=$expected, actual=$actual")
}
}
companion object {
private val HEAP_DATA = HeapArrayFloatList::class.java.getFieldOrNull("data")!!.field
}
}