mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 09:26:11 -04:00
improve thread pool (performance), improve culling performance
This commit is contained in:
parent
ec7ef10add
commit
7344fdda6c
@ -36,7 +36,7 @@ class ChunkSection(
|
|||||||
var light: IntArray, // packed (skyLight: 0xF0, blockLight: 0x0F)
|
var light: IntArray, // packed (skyLight: 0xF0, blockLight: 0x0F)
|
||||||
) {
|
) {
|
||||||
|
|
||||||
constructor(registries: Registries) : this(RegistrySectionDataProvider<BlockState?>(registries.blockStateRegistry.unsafeCast(), checkSize = true), RegistrySectionDataProvider(registries.biomeRegistry, checkSize = false), SectionDataProvider(checkSize = true), IntArray(ProtocolDefinition.BLOCKS_PER_SECTION))
|
constructor(registries: Registries) : this(RegistrySectionDataProvider<BlockState?>(registries.blockStateRegistry.unsafeCast(), checkSize = true), RegistrySectionDataProvider(registries.biomeRegistry, checkSize = false), SectionDataProvider(checkSize = false), IntArray(ProtocolDefinition.BLOCKS_PER_SECTION))
|
||||||
|
|
||||||
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
fun tick(connection: PlayConnection, chunkPosition: Vec2i, sectionHeight: Int) {
|
||||||
if (blockEntities.isEmpty) {
|
if (blockEntities.isEmpty) {
|
||||||
|
@ -18,7 +18,7 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
|||||||
|
|
||||||
class RegistrySectionDataProvider<T>(
|
class RegistrySectionDataProvider<T>(
|
||||||
val registry: AbstractRegistry<T>,
|
val registry: AbstractRegistry<T>,
|
||||||
data: Array<Any?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION),
|
data: Array<Any?>? = null,
|
||||||
checkSize: Boolean = false,
|
checkSize: Boolean = false,
|
||||||
) : SectionDataProvider<T>(data, checkSize = checkSize) {
|
) : SectionDataProvider<T>(data, checkSize = checkSize) {
|
||||||
|
|
||||||
|
@ -13,15 +13,16 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.world.container
|
package de.bixilon.minosoft.data.world.container
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.util.SemaphoreLock
|
import de.bixilon.minosoft.util.SemaphoreLock
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
|
|
||||||
open class SectionDataProvider<T>(
|
open class SectionDataProvider<T>(
|
||||||
data: Array<Any?> = arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION),
|
data: Array<Any?>? = null,
|
||||||
val checkSize: Boolean = false,
|
val checkSize: Boolean = false,
|
||||||
) : Iterable<T> {
|
) : Iterable<T> {
|
||||||
protected var data = data
|
protected var data = data ?: arrayOfNulls(ProtocolDefinition.BLOCKS_PER_SECTION)
|
||||||
private set
|
private set
|
||||||
protected val lock = SemaphoreLock() // lock while reading (blocks writing)
|
protected val lock = SemaphoreLock() // lock while reading (blocks writing)
|
||||||
var count: Int = 0
|
var count: Int = 0
|
||||||
@ -34,7 +35,12 @@ open class SectionDataProvider<T>(
|
|||||||
private set
|
private set
|
||||||
|
|
||||||
init {
|
init {
|
||||||
recalculate()
|
if (data != null) {
|
||||||
|
recalculate()
|
||||||
|
} else {
|
||||||
|
minPosition = Vec3i.EMPTY
|
||||||
|
maxPosition = Vec3i.EMPTY
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@ -55,9 +61,9 @@ open class SectionDataProvider<T>(
|
|||||||
return data[y shl 8 or (z shl 4) or x] as T
|
return data[y shl 8 or (z shl 4) or x] as T
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun recalculate() {
|
private fun recalculate() {
|
||||||
var count = 0
|
var count = 0
|
||||||
var value: Any?
|
|
||||||
|
|
||||||
var minX = 16
|
var minX = 16
|
||||||
var minY = 16
|
var minY = 16
|
||||||
|
@ -5,12 +5,16 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparenci
|
|||||||
object CullUtil {
|
object CullUtil {
|
||||||
|
|
||||||
fun Array<FaceProperties>.canCull(properties: FaceProperties, sameBlock: Boolean): Boolean {
|
fun Array<FaceProperties>.canCull(properties: FaceProperties, sameBlock: Boolean): Boolean {
|
||||||
|
val sizeStartX = properties.sizeStart.x
|
||||||
|
val sizeStartY = properties.sizeStart.y
|
||||||
|
val sizeEndX = properties.sizeEnd.x
|
||||||
|
val sizeEndY = properties.sizeEnd.y
|
||||||
for (property in this) {
|
for (property in this) {
|
||||||
if (
|
if (
|
||||||
property.sizeStart.x <= properties.sizeStart.x
|
property.sizeStart.x <= sizeStartX
|
||||||
&& property.sizeStart.y <= properties.sizeStart.y
|
&& property.sizeStart.y <= sizeStartY
|
||||||
&& property.sizeEnd.x >= properties.sizeEnd.x
|
&& property.sizeEnd.x >= sizeEndX
|
||||||
&& property.sizeEnd.y >= properties.sizeEnd.y
|
&& property.sizeEnd.y >= sizeEndY
|
||||||
&& !((properties.transparency == TextureTransparencies.OPAQUE && property.transparency != TextureTransparencies.OPAQUE)
|
&& !((properties.transparency == TextureTransparencies.OPAQUE && property.transparency != TextureTransparencies.OPAQUE)
|
||||||
|| (properties.transparency != TextureTransparencies.OPAQUE && property.transparency == properties.transparency && !sameBlock)
|
|| (properties.transparency != TextureTransparencies.OPAQUE && property.transparency == properties.transparency && !sameBlock)
|
||||||
|| (properties.transparency == TextureTransparencies.TRANSPARENT && property.transparency == TextureTransparencies.TRANSLUCENT))
|
|| (properties.transparency == TextureTransparencies.TRANSPARENT && property.transparency == TextureTransparencies.TRANSLUCENT))
|
||||||
|
@ -13,22 +13,17 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.util.task.pool
|
package de.bixilon.minosoft.util.task.pool
|
||||||
|
|
||||||
import de.bixilon.minosoft.util.KUtil.synchronizedSetOf
|
import de.bixilon.minosoft.util.KUtil.synchronizedListOf
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
import de.bixilon.minosoft.util.KUtil.toSynchronizedList
|
||||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedSet
|
import java.util.concurrent.*
|
||||||
import java.util.concurrent.Callable
|
|
||||||
import java.util.concurrent.ExecutorService
|
|
||||||
import java.util.concurrent.Future
|
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
|
|
||||||
open class ThreadPool(
|
open class ThreadPool(
|
||||||
val threadCount: Int = Runtime.getRuntime().availableProcessors(),
|
val threadCount: Int = Runtime.getRuntime().availableProcessors(),
|
||||||
private val name: String = "Worker#%d",
|
private val name: String = "Worker#%d",
|
||||||
) : ExecutorService {
|
) : ExecutorService {
|
||||||
private var state = ThreadPoolStates.STARTING
|
private var state = ThreadPoolStates.STARTING
|
||||||
private val threads: MutableSet<Thread> = synchronizedSetOf()
|
private var threads: MutableList<Thread> = synchronizedListOf()
|
||||||
private val availableThreads: MutableSet<Thread> = synchronizedSetOf()
|
private var queue: PriorityBlockingQueue<ThreadPoolRunnable> = PriorityBlockingQueue()
|
||||||
private var pending: MutableSet<ThreadPoolRunnable> = sortedSetOf<ThreadPoolRunnable>({ a, b -> a.priority - b.priority }).toSynchronizedSet()
|
|
||||||
private var nextThreadId = 0
|
private var nextThreadId = 0
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@ -37,43 +32,24 @@ open class ThreadPool(
|
|||||||
state = ThreadPoolStates.STARTED
|
state = ThreadPoolStates.STARTED
|
||||||
}
|
}
|
||||||
|
|
||||||
val pendingCount: Int
|
val queueSize: Int
|
||||||
get() = pending.size
|
get() = queue.size
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
private fun checkThreads() {
|
private fun checkThreads() {
|
||||||
fun wait() {
|
|
||||||
try {
|
|
||||||
availableThreads += Thread.currentThread()
|
|
||||||
Thread.sleep(Long.MAX_VALUE)
|
|
||||||
} catch (exception: InterruptedException) {
|
|
||||||
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Thread (${Thread.currentThread()} sleeping got interrupted" }
|
|
||||||
}
|
|
||||||
availableThreads -= Thread.currentThread()
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i in 0 until threadCount - threads.size) {
|
for (i in 0 until threadCount - threads.size) {
|
||||||
|
var runnable: ThreadPoolRunnable
|
||||||
val thread = Thread {
|
val thread = Thread {
|
||||||
while (true) {
|
while (true) {
|
||||||
if (state == ThreadPoolStates.STOPPING) {
|
if (state == ThreadPoolStates.STOPPING) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (pending.isEmpty()) {
|
try {
|
||||||
wait()
|
runnable = queue.take()
|
||||||
|
} catch (exception: InterruptedException) {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val runnable: ThreadPoolRunnable?
|
|
||||||
synchronized(pending) {
|
|
||||||
if (pending.isNotEmpty()) {
|
|
||||||
runnable = pending.iterator().next()
|
|
||||||
pending.remove(runnable)
|
|
||||||
} else {
|
|
||||||
runnable = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (runnable == null) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
runnable.thread = Thread.currentThread()
|
runnable.thread = Thread.currentThread()
|
||||||
runnable.runnable.run()
|
runnable.runnable.run()
|
||||||
@ -83,9 +59,7 @@ open class ThreadPool(
|
|||||||
if (exception is InterruptedException) {
|
if (exception is InterruptedException) {
|
||||||
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Thread ${Thread.currentThread()} was interrupted" }
|
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Thread ${Thread.currentThread()} was interrupted" }
|
||||||
runnable.wasInterrupted = true
|
runnable.wasInterrupted = true
|
||||||
if (!runnable.interuptable) {
|
queue += runnable
|
||||||
pending += runnable
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == ThreadPoolStates.STOPPING) {
|
if (state == ThreadPoolStates.STOPPING) {
|
||||||
break
|
break
|
||||||
@ -94,30 +68,18 @@ open class ThreadPool(
|
|||||||
exception.printStackTrace()
|
exception.printStackTrace()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pending.isNotEmpty()) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wait()
|
|
||||||
}
|
}
|
||||||
threads -= Thread.currentThread()
|
threads -= Thread.currentThread()
|
||||||
}
|
}
|
||||||
thread.name = name.format(nextThreadId++)
|
thread.name = name.format(nextThreadId++)
|
||||||
threads += thread
|
|
||||||
thread.start()
|
thread.start()
|
||||||
|
threads += thread
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
fun execute(runnable: ThreadPoolRunnable) {
|
fun execute(runnable: ThreadPoolRunnable) {
|
||||||
pending += runnable
|
queue += runnable
|
||||||
synchronized(availableThreads) {
|
|
||||||
if (availableThreads.isNotEmpty()) {
|
|
||||||
val thread = availableThreads.iterator().next()
|
|
||||||
availableThreads.remove(thread)
|
|
||||||
thread.interrupt()
|
|
||||||
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Interrupting thread $thread" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun execute(runnable: Runnable) {
|
override fun execute(runnable: Runnable) {
|
||||||
@ -138,9 +100,7 @@ open class ThreadPool(
|
|||||||
state = ThreadPoolStates.STOPPING
|
state = ThreadPoolStates.STOPPING
|
||||||
synchronized(threads) {
|
synchronized(threads) {
|
||||||
for (thread in threads.toSynchronizedList()) {
|
for (thread in threads.toSynchronizedList()) {
|
||||||
if (thread.state == Thread.State.TIMED_WAITING) {
|
thread.interrupt()
|
||||||
thread.interrupt()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (threads.isNotEmpty()) {
|
while (threads.isNotEmpty()) {
|
||||||
@ -156,12 +116,8 @@ open class ThreadPool(
|
|||||||
thread.interrupt()
|
thread.interrupt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while (threads.isNotEmpty()) {
|
|
||||||
Thread.sleep(1L)
|
|
||||||
}
|
|
||||||
state = ThreadPoolStates.STOPPED
|
state = ThreadPoolStates.STOPPED
|
||||||
|
return mutableListOf()
|
||||||
return mutableListOf() // ToDo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isShutdown(): Boolean {
|
override fun isShutdown(): Boolean {
|
||||||
|
@ -17,7 +17,7 @@ class ThreadPoolRunnable(
|
|||||||
val priority: Int = ThreadPool.NORMAL,
|
val priority: Int = ThreadPool.NORMAL,
|
||||||
var interuptable: Boolean = false,
|
var interuptable: Boolean = false,
|
||||||
val runnable: Runnable,
|
val runnable: Runnable,
|
||||||
) {
|
) : Comparable<ThreadPoolRunnable> {
|
||||||
var wasInterrupted = false
|
var wasInterrupted = false
|
||||||
var thread: Thread? = null
|
var thread: Thread? = null
|
||||||
|
|
||||||
@ -27,4 +27,8 @@ class ThreadPoolRunnable(
|
|||||||
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE){"Interrupting runnable in thread $thread"}
|
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE){"Interrupting runnable in thread $thread"}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun compareTo(other: ThreadPoolRunnable): Int {
|
||||||
|
return priority - other.priority
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user