Minor fixes all around

This commit is contained in:
jay-tux 2025-04-21 22:21:57 +02:00
parent 5f91256c31
commit f18351f9f0
Signed by: jay-tux
GPG Key ID: 84302006B056926E
5 changed files with 119 additions and 26 deletions

View File

@ -45,3 +45,14 @@ tasks.test {
kotlin { kotlin {
jvmToolchain(21) jvmToolchain(21)
} }
application {
mainClass.set("com.jaytux.simd.MainKt")
}
tasks.withType<Jar> {
manifest {
attributes["Main-Class"] = application.mainClass
}
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
}

View File

@ -10,26 +10,39 @@ import io.ktor.server.netty.*
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
fun main(args: Array<String>) { fun main(args: Array<String>) {
if(args.size > 3 && args[1] == "-reload") { println("Arguments (${args.size}): [${args.joinToString(", ")}]")
val xmlFile = args[2]
val jsonFile = args[3] if(args.size >= 3 && args[0] == "-reload") {
dbSetup(xmlFile, jsonFile) val xmlFile = args[1]
val jsonFile = args[2]
val force = args.size > 3 && args[3] == "-force"
dbSetup(xmlFile, jsonFile, force)
} }
else if(args.size >= 1 && args[1] == "-h") { else if(args.size >= 1 && args[1] == "-h") {
println("Usage: ${args[0]} -reload <xmlFile> <jsonFile> (to reload the database)") println("Usage: -reload <xmlFile> <jsonFile> (to reload the database)")
println(" ${args[0]} (to start the server)") println(" -reload <xmlFile> <jsonFile> -force (to force reload the database; overwriting data even if the database has newer data)")
println(" -h (to show this help message)")
println(" (no arguments) (to start the server)")
} }
else { else {
EngineMain.main(args) EngineMain.main(args)
} }
} }
fun dbSetup(xmlFile: String, jsonFile: String) { fun dbSetup(xmlFile: String, jsonFile: String, force: Boolean = false) {
runBlocking { runBlocking {
val xml = Loader.loadXml("/home/jay/intrinsics/data.xml") val xml = Loader.loadXml("/home/jay/intrinsics/data.xml")
val perf = Loader.loadJson("/home/jay/intrinsics/perf2.js") val perf = Loader.loadJson("/home/jay/intrinsics/perf2.js")
val current = Loader.DatedVersion.fromPrefs()
if(force || (xml.version.version isNewerThan current.version)) {
Database.reset()
Loader.importToDb(xml, perf) Loader.importToDb(xml, perf)
} }
if(!(xml.version.version isNewerThan current.version)) {
System.err.println("The XML file (${xml.version}) is not more up-to-date than the database ($current). Use -force to force importing.")
}
}
} }
fun Application.module() { fun Application.module() {
@ -38,18 +51,3 @@ fun Application.module() {
configureHTTP() configureHTTP()
configureRouting() configureRouting()
} }
// API: (everything except /details/ is paginated per 100)
// - GET /all (list of SIMD intrinsics (name + ID))
// - GET /cpuid (list of CPUID values)
// - GET /tech (list of techs)
// - GET /category (list of categories)
// - GET /types (list of types)
// - GET /search (search for SIMD intrinsics); query params:
// - name (string, optional, partial matching)
// - return (string, optional, full match)
// - cpuid (string, optional, full match)
// - tech (string, optional, full match)
// - category (string, optional, full match)
// - desc (string, optional, partial matching)
// - GET /details/<id> (details of a SIMD intrinsic)

View File

@ -4,6 +4,7 @@ import com.jaytux.simd.DotEnv
import org.jetbrains.exposed.sql.Database import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.SchemaUtils import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import java.util.prefs.Preferences
object Database { object Database {
val db by lazy { val db by lazy {
@ -22,6 +23,7 @@ object Database {
} }
fun reset() { fun reset() {
db
transaction { transaction {
SchemaUtils.drop(Techs, CppTypes, Categories, CPUIDs, Intrinsics, SchemaUtils.drop(Techs, CppTypes, Categories, CPUIDs, Intrinsics,
IntrinsicArguments, IntrinsicInstructions, Platforms, Performances) IntrinsicArguments, IntrinsicInstructions, Platforms, Performances)

View File

@ -11,11 +11,57 @@ import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import java.io.File import java.io.File
import org.json.JSONObject import org.json.JSONObject
import org.junit.jupiter.api.DisplayNameGenerator.Simple
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.Date
import java.util.prefs.Preferences
import java.time.Instant
object Loader { object Loader {
data class XmlIntrinsic(val name: String, val tech: String, val retType: String, val retVar: String?, val args: List<Pair<String, String>>, val desc: String, val op: String?, val insn: List<Triple<String, String, String?>>, val cpuid: String?, val category: String) private val cache = Preferences.userNodeForPackage(this::class.java)
private val intelDateTimeFormat = SimpleDateFormat("MM/dd/yyyy")
private val dateFormat = SimpleDateFormat("dd-MMMM-yyyy")
data class XmlIntrinsic(val name: String, val tech: String, val retType: String, val retVar: String?,
val args: List<Pair<String, String>>, val desc: String, val op: String?,
val insn: List<Triple<String, String, String?>>, val cpuid: String?, val category: String
)
data class Version(val major: Int, val minor: Int, val patch: Int) {
override fun toString(): String = "$major.$minor.$patch"
infix fun isNewerThan(other: Version): Boolean {
if(major > other.major) return true
if(major == other.major && minor > other.minor) return true
if(major == other.major && minor == other.minor && patch > other.patch) return true
return false
}
companion object {
fun fromString(version: String): Version {
val parts = version.split(".")
return Version(parts[0].toInt(), parts[1].toInt(), parts[2].toInt())
}
}
}
data class DatedVersion(val version: Version, val releaseDate: Date, val updateDate: Date) {
override fun toString(): String = "$version (remote released ${dateFormat.format(releaseDate)}; local updated ${dateFormat.format(updateDate)})"
companion object {
fun fromPrefs(): DatedVersion {
val v = cache.get("version", null)?.let { Version.fromString(it) } ?: Version(0, 0, 0)
val r = cache.get("release", null)?.let { dateFormat.parse(it) } ?: Date.from(Instant.ofEpochMilli(0))
val u = cache.get("update", null)?.let { dateFormat.parse(it) } ?: Date.from(Instant.ofEpochMilli(0))
return DatedVersion(v, r, u)
}
}
}
data class XmlData( data class XmlData(
val version: DatedVersion,
val types: Set<String>, val techs: Set<String>, val cpuids: Set<String>, val categories: Set<String>, val types: Set<String>, val techs: Set<String>, val cpuids: Set<String>, val categories: Set<String>,
val intrinsics: List<XmlIntrinsic> val intrinsics: List<XmlIntrinsic>
) )
@ -24,6 +70,12 @@ object Loader {
data class JsonData(val platforms: Set<String>, val data: Map<String, Map<String, Performance>>) data class JsonData(val platforms: Set<String>, val data: Map<String, Map<String, Performance>>)
private suspend fun updateVersion(version: DatedVersion) = coroutineScope {
cache.put("version", version.version.toString())
cache.put("release", dateFormat.format(version.releaseDate))
cache.put("update", dateFormat.format(version.updateDate))
}
suspend fun loadXml(xmlFile: String): XmlData = coroutineScope { suspend fun loadXml(xmlFile: String): XmlData = coroutineScope {
val xml = Ksoup.parseXml(File(xmlFile).readText(Charsets.UTF_8)) val xml = Ksoup.parseXml(File(xmlFile).readText(Charsets.UTF_8))
@ -35,6 +87,28 @@ object Loader {
val errors = mutableListOf<String>() val errors = mutableListOf<String>()
val (version, release) = xml.getElementsByTag("intrinsics_list").firstOrNull()?.let {
val version = it.attribute("version")?.value?.let { v -> Version.fromString(v) }
if(version == null) {
errors += "Missing version attribute in intrinsics_list element"
return@let null
}
val date = it.attribute("date")?.value?.let { d -> intelDateTimeFormat.parse(d) }
if(date == null) {
errors += "Missing release_date attribute in intrinsics_list element"
return@let null
}
version to date
} ?: Version(0, 0, 0) to Date()
if(errors.isNotEmpty()) {
errors.forEach { System.err.println(it) }
throw Exception("XML file is (partially) invalid")
}
val update = Date()
xml.getElementsByTag("intrinsic").forEachIndexed { i, it -> xml.getElementsByTag("intrinsic").forEachIndexed { i, it ->
val name = it.attribute("name")?.value val name = it.attribute("name")?.value
if(name == null) { if(name == null) {
@ -123,7 +197,10 @@ object Loader {
throw Exception("XML file is (partially) invalid") throw Exception("XML file is (partially) invalid")
} }
XmlData(types = cppTypes, techs = techs, cpuids = cpuids, categories = categories, intrinsics = intrins) XmlData(version = DatedVersion(version, release, update),
types = cppTypes, techs = techs, cpuids = cpuids, categories = categories,
intrinsics = intrins
)
} }
suspend fun loadJson(jsonFile: String): JsonData = coroutineScope { suspend fun loadJson(jsonFile: String): JsonData = coroutineScope {
@ -201,5 +278,6 @@ object Loader {
} }
} }
} }
updateVersion(xml.version)
} }
} }

View File

@ -4,6 +4,10 @@
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> <pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder> </encoder>
</appender> </appender>
<logger name="io.netty" level="warn" />
<logger name="ch.qos.logback" level="warn" />
<root level="trace"> <root level="trace">
<appender-ref ref="APPENDER"/> <appender-ref ref="APPENDER"/>
</root> </root>