split booting into preBoot, boot and postBoot, booting performance improvements

This commit is contained in:
Moritz Zwerger 2023-10-11 19:26:08 +02:00
parent 84378cbcec
commit 68608934cb
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 68 additions and 28 deletions

View File

@ -18,10 +18,10 @@ import de.bixilon.kutil.concurrent.pool.DefaultThreadPool.async
import de.bixilon.kutil.concurrent.pool.ThreadPool import de.bixilon.kutil.concurrent.pool.ThreadPool
import de.bixilon.kutil.concurrent.worker.task.TaskWorker import de.bixilon.kutil.concurrent.worker.task.TaskWorker
import de.bixilon.kutil.concurrent.worker.task.WorkerTask import de.bixilon.kutil.concurrent.worker.task.WorkerTask
import de.bixilon.kutil.exception.ExceptionUtil.catchAll
import de.bixilon.kutil.file.watcher.FileWatcherService import de.bixilon.kutil.file.watcher.FileWatcherService
import de.bixilon.kutil.latch.AbstractLatch import de.bixilon.kutil.latch.AbstractLatch
import de.bixilon.kutil.latch.CallbackLatch import de.bixilon.kutil.latch.CallbackLatch
import de.bixilon.kutil.latch.SimpleLatch
import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.kutil.observer.DataObserver.Companion.observe
import de.bixilon.kutil.os.OSTypes import de.bixilon.kutil.os.OSTypes
import de.bixilon.kutil.os.PlatformInfo import de.bixilon.kutil.os.PlatformInfo
@ -62,6 +62,7 @@ import de.bixilon.minosoft.terminal.RunConfiguration
import de.bixilon.minosoft.terminal.cli.CLI import de.bixilon.minosoft.terminal.cli.CLI
import de.bixilon.minosoft.util.DesktopUtil import de.bixilon.minosoft.util.DesktopUtil
import de.bixilon.minosoft.util.KUtil import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.json.Jackson
import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
@ -74,27 +75,30 @@ object Minosoft {
val LANGUAGE_MANAGER = MultiLanguageManager() val LANGUAGE_MANAGER = MultiLanguageManager()
val BOOT_LATCH = CallbackLatch(1) val BOOT_LATCH = CallbackLatch(1)
@JvmStatic
fun main(args: Array<String>) { private fun preBoot(args: Array<String>) {
val start = nanos()
Log::class.java.forceInit() Log::class.java.forceInit()
ShutdownManager.addHook { Log.ASYNC_LOGGING = false; catchAll { Log.await() } } async(ThreadPool.Priorities.HIGHEST) { Jackson.init(); MinosoftPropertiesLoader.init() }
CommandLineArguments.parse(args) CommandLineArguments.parse(args)
Log.log(LogMessageType.OTHER, LogLevels.INFO) { "Starting minosoft..." } Log.log(LogMessageType.OTHER, LogLevels.INFO) { "Starting minosoft..." }
val latch = SimpleLatch(2)
DefaultThreadPool += { MINOSOFT_ASSETS_MANAGER.load(); MinosoftPropertiesLoader.load(); latch.dec() }
DefaultThreadPool += { ModLoader.initModLoading(); latch.dec() }
KUtil.initBootClasses() KUtil.initBootClasses()
KUtil.init() KUtil.init()
ModLoader.initModLoading()
latch.await()
ModLoader.load(LoadingPhases.PRE_BOOT) ModLoader.load(LoadingPhases.PRE_BOOT)
ModLoader.await(LoadingPhases.PRE_BOOT) ModLoader.await(LoadingPhases.PRE_BOOT)
MINOSOFT_ASSETS_MANAGER.load()
if (PlatformInfo.OS == OSTypes.MAC) { if (PlatformInfo.OS == OSTypes.MAC) {
checkMacOS() checkMacOS()
} }
MinosoftPropertiesLoader.load() }
private fun boot() {
val taskWorker = TaskWorker(errorHandler = { _, error -> error.printStackTrace(); error.crash() }) val taskWorker = TaskWorker(errorHandler = { _, error -> error.printStackTrace(); error.crash() })
taskWorker += WorkerTask(identifier = BootTasks.VERSIONS, priority = ThreadPool.HIGHER + 2, executor = VersionLoader::load) taskWorker += WorkerTask(identifier = BootTasks.VERSIONS, priority = ThreadPool.HIGHER + 2, executor = VersionLoader::load)
@ -128,13 +132,14 @@ object Minosoft {
taskWorker.work(BOOT_LATCH) taskWorker.work(BOOT_LATCH)
BOOT_LATCH.dec() // initial count
BOOT_LATCH.dec() // remove initial count
BOOT_LATCH.await() BOOT_LATCH.await()
}
private fun postBoot() {
if (ErosCrashReport.alreadyCrashed) return if (ErosCrashReport.alreadyCrashed) return
val end = nanos()
KUtil.initPlayClasses() KUtil.initPlayClasses()
Log.log(LogMessageType.GENERAL, LogLevels.INFO) { "Minosoft boot sequence finished in ${(end - start).formatNanos()}!" }
GlobalEventMaster.fire(FinishBootEvent()) GlobalEventMaster.fire(FinishBootEvent())
DefaultThreadPool += { ModLoader.load(LoadingPhases.POST_BOOT) } DefaultThreadPool += { ModLoader.load(LoadingPhases.POST_BOOT) }
if (RunConfiguration.DISABLE_EROS) { if (RunConfiguration.DISABLE_EROS) {
@ -144,6 +149,23 @@ object Minosoft {
RunConfiguration.AUTO_CONNECT_TO?.let { AutoConnect.autoConnect(it) } RunConfiguration.AUTO_CONNECT_TO?.let { AutoConnect.autoConnect(it) }
} }
@JvmStatic
fun main(args: Array<String>) {
val start = nanos()
Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Pre booting..." }
preBoot(args)
Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Booting..." }
boot()
val delta = nanos() - start
Log.log(LogMessageType.GENERAL, LogLevels.INFO) { "Minosoft boot sequence finished in ${delta.formatNanos()}!" }
Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Post booting..." }
postBoot()
}
private fun startFileWatcherService(latch: AbstractLatch) { private fun startFileWatcherService(latch: AbstractLatch) {
Log.log(LogMessageType.GENERAL, LogLevels.VERBOSE) { "Starting file watcher service..." } Log.log(LogMessageType.GENERAL, LogLevels.VERBOSE) { "Starting file watcher service..." }
FileWatcherService.start() FileWatcherService.start()

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.assets.util package de.bixilon.minosoft.assets.util
import com.fasterxml.jackson.databind.JavaType
import com.fasterxml.jackson.module.kotlin.readValue import com.fasterxml.jackson.module.kotlin.readValue
import de.bixilon.kutil.buffer.BufferDefinition import de.bixilon.kutil.buffer.BufferDefinition
import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.cast.CastUtil.unsafeCast
@ -67,6 +68,16 @@ object InputStreamUtil {
} }
} }
inline fun <reified T> InputStream.readJson(close: Boolean = true, type: JavaType): T {
try {
return Jackson.MAPPER.readValue(this, type)
} finally {
if (close) {
this.close()
}
}
}
fun InputStream.readArchive(): Map<String, ByteArray> { fun InputStream.readArchive(): Map<String, ByteArray> {
val content: MutableMap<String, ByteArray> = mutableMapOf() val content: MutableMap<String, ByteArray> = mutableMapOf()
val stream = TarInputStream(this) val stream = TarInputStream(this)

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.data.language package de.bixilon.minosoft.data.language
import de.bixilon.kutil.exception.ExceptionUtil import de.bixilon.kutil.exception.ExceptionUtil.tryCatch
import de.bixilon.kutil.json.JsonObject import de.bixilon.kutil.json.JsonObject
import de.bixilon.minosoft.assets.AssetsManager import de.bixilon.minosoft.assets.AssetsManager
import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject
@ -109,7 +109,7 @@ object LanguageUtil {
if (name != FALLBACK_LANGUAGE) { if (name != FALLBACK_LANGUAGE) {
ExceptionUtil.tryCatch(FileNotFoundException::class.java, executor = { languages += loadLanguage(name, assetsManager, json, path) ?: return@tryCatch }) tryCatch(FileNotFoundException::class.java, executor = { languages += loadLanguage(name, assetsManager, json, path) ?: return@tryCatch })
} }
loadLanguage(FALLBACK_LANGUAGE, assetsManager, json, path)?.let { languages += it } loadLanguage(FALLBACK_LANGUAGE, assetsManager, json, path)?.let { languages += it }

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.gui.rendering.tint.tints package de.bixilon.minosoft.gui.rendering.tint.tints
import de.bixilon.kutil.exception.ExceptionUtil import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll
import de.bixilon.minosoft.assets.AssetsManager import de.bixilon.minosoft.assets.AssetsManager
import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray
import de.bixilon.minosoft.data.container.stack.ItemStack import de.bixilon.minosoft.data.container.stack.ItemStack
@ -27,7 +27,7 @@ class FoliageTintCalculator : TintProvider {
private lateinit var colorMap: IntArray private lateinit var colorMap: IntArray
fun init(assetsManager: AssetsManager) { fun init(assetsManager: AssetsManager) {
colorMap = ExceptionUtil.ignoreAll { assetsManager["minecraft:colormap/foliage".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256) colorMap = ignoreAll { assetsManager["minecraft:colormap/foliage".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256)
} }
fun getBlockColor(biome: Biome?, y: Int): Int { fun getBlockColor(biome: Biome?, y: Int): Int {

View File

@ -13,7 +13,7 @@
package de.bixilon.minosoft.gui.rendering.tint.tints package de.bixilon.minosoft.gui.rendering.tint.tints
import de.bixilon.kutil.exception.ExceptionUtil import de.bixilon.kutil.exception.ExceptionUtil.ignoreAll
import de.bixilon.minosoft.assets.AssetsManager import de.bixilon.minosoft.assets.AssetsManager
import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray import de.bixilon.minosoft.assets.util.InputStreamUtil.readRGBArray
import de.bixilon.minosoft.data.registries.biomes.Biome import de.bixilon.minosoft.data.registries.biomes.Biome
@ -29,7 +29,7 @@ class GrassTintCalculator : TintProvider {
private lateinit var colorMap: IntArray private lateinit var colorMap: IntArray
fun init(assetsManager: AssetsManager) { fun init(assetsManager: AssetsManager) {
colorMap = ExceptionUtil.ignoreAll { assetsManager["minecraft:colormap/grass".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256) colorMap = ignoreAll { assetsManager["minecraft:colormap/grass".toResourceLocation().texture()].readRGBArray() } ?: IntArray(256)
} }
inline fun getColor(downfall: Int, temperature: Int): Int { inline fun getColor(downfall: Int, temperature: Int): Int {

View File

@ -13,7 +13,6 @@
package de.bixilon.minosoft.modding.loader package de.bixilon.minosoft.modding.loader
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
import de.bixilon.kutil.concurrent.worker.unconditional.UnconditionalWorker import de.bixilon.kutil.concurrent.worker.unconditional.UnconditionalWorker
import de.bixilon.kutil.latch.AbstractLatch import de.bixilon.kutil.latch.AbstractLatch
import de.bixilon.kutil.latch.AbstractLatch.Companion.child import de.bixilon.kutil.latch.AbstractLatch.Companion.child
@ -29,7 +28,6 @@ import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
import java.io.File import java.io.File
import kotlin.reflect.jvm.javaField
object ModLoader { object ModLoader {
@ -58,7 +56,7 @@ object ModLoader {
} }
fun initModLoading() { fun initModLoading() {
DefaultThreadPool += { createDirectories() } createDirectories()
} }
@ -239,6 +237,7 @@ object ModLoader {
} }
private val ASSETS_MANAGER_FIELD = ModMain::assets.javaField!!.apply { isAccessible = true } private val MOD_MAIN = ModMain::class.java
private val LOGGER_FIELD = ModMain::logger.javaField!!.apply { isAccessible = true } private val ASSETS_MANAGER_FIELD = MOD_MAIN.getDeclaredField("assets").apply { isAccessible = true }
private val LOGGER_FIELD = MOD_MAIN.getDeclaredField("logger").apply { isAccessible = true }
} }

View File

@ -18,15 +18,17 @@ import de.bixilon.minosoft.assets.util.InputStreamUtil.readJson
import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft
import de.bixilon.minosoft.properties.general.GeneralP import de.bixilon.minosoft.properties.general.GeneralP
import de.bixilon.minosoft.terminal.RunConfiguration import de.bixilon.minosoft.terminal.RunConfiguration
import de.bixilon.minosoft.util.json.Jackson
import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.Log
import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogLevels
import de.bixilon.minosoft.util.logging.LogMessageType import de.bixilon.minosoft.util.logging.LogMessageType
object MinosoftPropertiesLoader { object MinosoftPropertiesLoader {
val type = Jackson.MAPPER.constructType(MinosoftP::class.java)
fun load() { fun load() {
val properties = Minosoft.MINOSOFT_ASSETS_MANAGER.getOrNull(minosoft("version.json"))?.readJson<MinosoftP>() val properties = Minosoft.MINOSOFT_ASSETS_MANAGER.getOrNull(minosoft("version.json"))?.readJson<MinosoftP>(type = type)
MinosoftProperties = if (properties == null) { MinosoftProperties = if (properties == null) {
Log.log(LogMessageType.OTHER, LogLevels.FATAL) { "Can not load version.json! Did you compile with gradle?" } Log.log(LogMessageType.OTHER, LogLevels.FATAL) { "Can not load version.json! Did you compile with gradle?" }
MinosoftP(GeneralP("unknown", false), null) MinosoftP(GeneralP("unknown", false), null)
@ -37,4 +39,6 @@ object MinosoftPropertiesLoader {
RunConfiguration.APPLICATION_NAME = "Minosoft ${MinosoftProperties.general.name}" RunConfiguration.APPLICATION_NAME = "Minosoft ${MinosoftProperties.general.name}"
Log.log(LogMessageType.OTHER, LogLevels.INFO) { "This is minosoft version ${MinosoftProperties.general.name}${MinosoftProperties.git?.let { ", built on ${it.commitShort}/${it.branch}" } ?: ""}!" } Log.log(LogMessageType.OTHER, LogLevels.INFO) { "This is minosoft version ${MinosoftProperties.general.name}${MinosoftProperties.git?.let { ", built on ${it.commitShort}/${it.branch}" } ?: ""}!" }
} }
fun init() = Unit
} }

View File

@ -279,7 +279,6 @@ object KUtil {
fun initBootClasses() { fun initBootClasses() {
DefaultThreadPool += { GlobalEventMaster::class.java.forceInit() } DefaultThreadPool += { GlobalEventMaster::class.java.forceInit() }
DefaultThreadPool += { ShutdownManager::class.java.forceInit() } DefaultThreadPool += { ShutdownManager::class.java.forceInit() }
DefaultThreadPool += { Jackson::class.java.forceInit() }
DefaultThreadPool += { URLProtocolStreamHandlers::class.java.forceInit() } DefaultThreadPool += { URLProtocolStreamHandlers::class.java.forceInit() }
DefaultThreadPool += { MicrosoftOAuthUtils::class.java.forceInit() } DefaultThreadPool += { MicrosoftOAuthUtils::class.java.forceInit() }
DefaultThreadPool += { TaskScheduler::class.java.forceInit() } DefaultThreadPool += { TaskScheduler::class.java.forceInit() }

View File

@ -14,7 +14,7 @@
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.exception.ExceptionUtil import de.bixilon.kutil.exception.ExceptionUtil.catchAll
import org.lwjgl.system.MemoryUtil.memAllocFloat import org.lwjgl.system.MemoryUtil.memAllocFloat
import org.lwjgl.system.MemoryUtil.memFree import org.lwjgl.system.MemoryUtil.memFree
import java.nio.FloatBuffer import java.nio.FloatBuffer
@ -22,7 +22,7 @@ import java.nio.FloatBuffer
object FloatListUtil { object FloatListUtil {
const val PREFER_FRAGMENTED = true const val PREFER_FRAGMENTED = true
val FLOAT_PUT_METHOD = ExceptionUtil.catchAll { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) } val FLOAT_PUT_METHOD = catchAll { FloatBuffer::class.java.getMethod("put", Int::class.java, FloatBuffer::class.java, Int::class.java, Int::class.java) }
const val DEFAULT_INITIAL_SIZE = 1000 const val DEFAULT_INITIAL_SIZE = 1000
fun direct(initialSize: Int = DEFAULT_INITIAL_SIZE): AbstractFloatList { fun direct(initialSize: Int = DEFAULT_INITIAL_SIZE): AbstractFloatList {

View File

@ -61,4 +61,6 @@ object Jackson {
val JSON_MAP_TYPE: MapType = MAPPER.typeFactory.constructMapType(HashMap::class.java, Any::class.java, Any::class.java) val JSON_MAP_TYPE: MapType = MAPPER.typeFactory.constructMapType(HashMap::class.java, Any::class.java, Any::class.java)
fun init() = Unit
} }

View File

@ -13,6 +13,8 @@
package de.bixilon.minosoft.util.logging package de.bixilon.minosoft.util.logging
import de.bixilon.kutil.ansi.ANSI import de.bixilon.kutil.ansi.ANSI
import de.bixilon.kutil.exception.ExceptionUtil.catchAll
import de.bixilon.kutil.shutdown.ShutdownManager
import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.kutil.time.TimeUtil.millis
import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.config.profile.profiles.other.OtherProfileSelectEvent import de.bixilon.minosoft.config.profile.profiles.other.OtherProfileSelectEvent
@ -62,6 +64,7 @@ object Log {
}, "Log").start() }, "Log").start()
GlobalEventMaster.register(CallbackEventListener.of<OtherProfileSelectEvent> { this.levels = it.profile.log.levels }) GlobalEventMaster.register(CallbackEventListener.of<OtherProfileSelectEvent> { this.levels = it.profile.log.levels })
ShutdownManager.addHook { ASYNC_LOGGING = false; catchAll { await() } }
} }
private fun QueuedMessage.print() { private fun QueuedMessage.print() {