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