mirror of https://github.com/shadowfacts/ekt.git
Cache compile script data
This commit is contained in:
parent
7df6669bd0
commit
a2c8cd6d4b
|
@ -1,10 +1,9 @@
|
||||||
package net.shadowfacts.ekt
|
package net.shadowfacts.ekt
|
||||||
|
|
||||||
import java.io.File
|
import org.jetbrains.kotlin.cli.common.repl.KotlinJsr223JvmScriptEngineBase
|
||||||
import javax.script.ScriptContext
|
import org.jetbrains.kotlin.cli.common.repl.ReplCompileResult
|
||||||
import javax.script.ScriptEngine
|
import java.io.*
|
||||||
import javax.script.ScriptEngineManager
|
import javax.script.*
|
||||||
import javax.script.SimpleScriptContext
|
|
||||||
import kotlin.concurrent.getOrSet
|
import kotlin.concurrent.getOrSet
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,11 +43,11 @@ fun include(include: String, init: net.shadowfacts.ekt.EKT.DataProvider.() -> Un
|
||||||
_result.toString()
|
_result.toString()
|
||||||
"""
|
"""
|
||||||
|
|
||||||
private val engine = ThreadLocal<ScriptEngine>()
|
private val engine = ThreadLocal<KotlinJsr223JvmScriptEngineBase>()
|
||||||
|
|
||||||
fun render(env: TemplateEnvironment, template: String = env.template): String {
|
fun render(env: TemplateEnvironment, template: String = env.template): String {
|
||||||
if (env.cacheDir != null && env.cacheFile.exists()) {
|
if (env.cacheDir != null && env.cacheScript.exists()) {
|
||||||
return eval(env.cacheFile.readText(Charsets.UTF_8), env)
|
return eval(env.cacheScript.readText(Charsets.UTF_8), env)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
@Suppress("NAME_SHADOWING")
|
||||||
|
@ -79,7 +78,7 @@ _result.toString()
|
||||||
val script = imports + scriptPrefix + template + scriptSuffix
|
val script = imports + scriptPrefix + template + scriptSuffix
|
||||||
|
|
||||||
if (env.cacheDir != null) {
|
if (env.cacheDir != null) {
|
||||||
env.cacheFile.apply {
|
env.cacheScript.apply {
|
||||||
if (!parentFile.exists()) parentFile.mkdirs()
|
if (!parentFile.exists()) parentFile.mkdirs()
|
||||||
if (!exists()) createNewFile()
|
if (!exists()) createNewFile()
|
||||||
writeText(script, Charsets.UTF_8)
|
writeText(script, Charsets.UTF_8)
|
||||||
|
@ -121,21 +120,58 @@ _result.toString()
|
||||||
return renderClasspath(name, path, "$path/includes", cacheDir, init)
|
return renderClasspath(name, path, "$path/includes", cacheDir, init)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun eval(script: String, env: TemplateEnvironment): String {
|
private fun eval(script: String, env: TemplateEnvironment): String {
|
||||||
val engine = engine.getOrSet { ScriptEngineManager().getEngineByExtension("kts") }
|
val engine = engine.getOrSet { ScriptEngineManager().getEngineByExtension("kts") as KotlinJsr223JvmScriptEngineBase }
|
||||||
engine.context = SimpleScriptContext()
|
|
||||||
val bindings = engine.getBindings(ScriptContext.ENGINE_SCOPE)
|
val context = createContext(engine, env)
|
||||||
bindings.putAll(env.data)
|
|
||||||
bindings.put("_env", env)
|
if (env.cacheDir != null) {
|
||||||
|
val cacheCompiled = env.cacheCompiled
|
||||||
|
val compiled = if (cacheCompiled.exists()) {
|
||||||
|
val fis = FileInputStream(cacheCompiled)
|
||||||
|
val ois = ObjectInputStream(fis)
|
||||||
|
val data = ois.readObject() as ReplCompileResult.CompiledClasses
|
||||||
|
ois.close()
|
||||||
|
fis.close()
|
||||||
|
KotlinJsr223JvmScriptEngineBase.CompiledKotlinScript(engine, engine.nextCodeLine(context, env.cacheScript.readText(Charsets.UTF_8)), data)
|
||||||
|
} else {
|
||||||
|
val compiled = engine.compile(script, context) as KotlinJsr223JvmScriptEngineBase.CompiledKotlinScript
|
||||||
|
val data = compiled.compiledData
|
||||||
|
val fos = FileOutputStream(cacheCompiled)
|
||||||
|
val oos = ObjectOutputStream(fos)
|
||||||
|
oos.writeObject(data)
|
||||||
|
oos.close()
|
||||||
|
fos.close()
|
||||||
|
compiled
|
||||||
|
}
|
||||||
|
return engine.eval(compiled, context) as String
|
||||||
|
} else {
|
||||||
|
return engine.eval(script, context) as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun eval(script: KotlinJsr223JvmScriptEngineBase.CompiledKotlinScript, env: TemplateEnvironment): String {
|
||||||
|
return script.engine.eval(script, createContext(script.engine, env)) as String
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createContext(engine: ScriptEngine, env: TemplateEnvironment): ScriptContext {
|
||||||
|
val bindings = engine.createBindings().apply {
|
||||||
|
putAll(env.data)
|
||||||
|
put("_env", env)
|
||||||
|
}
|
||||||
|
|
||||||
|
val context = SimpleScriptContext().apply {
|
||||||
|
setBindings(bindings, ScriptContext.ENGINE_SCOPE)
|
||||||
|
}
|
||||||
|
|
||||||
// Hack to allow data to be accessed by name from template instead of via bindings map
|
// Hack to allow data to be accessed by name from template instead of via bindings map
|
||||||
val unwrapBindings = env.data.keys.map {
|
val unwrapBindings = env.data.keys.joinToString("\n") {
|
||||||
val type = env.data[it]!!.type
|
val type = env.data[it]!!.type
|
||||||
"val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.TypedValue).value as $type"
|
"val $it = (bindings[\"$it\"] as net.shadowfacts.ekt.EKT.TypedValue).value as $type"
|
||||||
}.joinToString("\n")
|
}
|
||||||
engine.eval(unwrapBindings)
|
engine.eval(unwrapBindings, context)
|
||||||
|
|
||||||
return engine.eval(script) as String
|
return context
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TemplateEnvironment {
|
interface TemplateEnvironment {
|
||||||
|
@ -146,8 +182,10 @@ _result.toString()
|
||||||
|
|
||||||
val template: String
|
val template: String
|
||||||
val include: String
|
val include: String
|
||||||
val cacheFile: File
|
val cacheScript: File
|
||||||
get() = File(cacheDir!!, "$name.kts")
|
get() = File(cacheDir!!, "$name.kts")
|
||||||
|
val cacheCompiled: File
|
||||||
|
get() = File(cacheDir!!, "$name.kts.compiled")
|
||||||
|
|
||||||
fun createChild(name: String, data: Map<String, TypedValue>? = null): TemplateEnvironment
|
fun createChild(name: String, data: Map<String, TypedValue>? = null): TemplateEnvironment
|
||||||
|
|
||||||
|
|
|
@ -1,22 +1,46 @@
|
||||||
package net.shadowfacts.ekt
|
package net.shadowfacts.ekt
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author shadowfacts
|
* @author shadowfacts
|
||||||
*/
|
*/
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
for (i in 0..2) {
|
println(ManagementFactory.getRuntimeMXBean().name)
|
||||||
thread {
|
|
||||||
println("Calling from: $i")
|
for (i in 0..99) {
|
||||||
render()
|
println("Rendering $i")
|
||||||
}
|
render()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println("done")
|
||||||
|
|
||||||
|
// thread {
|
||||||
|
// for (i in 0..30) {
|
||||||
|
// println("Thread 1 iteration $i")
|
||||||
|
// render()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// thread {
|
||||||
|
// for (i in 0..30) {
|
||||||
|
// println("Thread 2 iteration $i")
|
||||||
|
// render()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// thread {
|
||||||
|
// for (i in 0..30) {
|
||||||
|
// println("Thread 3 iteration $i")
|
||||||
|
// render()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun render(): String {
|
fun render(): String {
|
||||||
return EKT.renderClasspath("template", "/templates") {
|
return EKT.renderClasspath("template", "/templates", cacheDir = File("cache")) {
|
||||||
"list" to (listOf(1, 2, 3) asType "List<Int>")
|
"list" to (listOf(1, 2, 3) asType "List<Int>")
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue