or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

caching.mdcompiled-scripts.mdconfiguration.mddependencies.mdevaluators.mdindex.mdutilities.md

caching.mddocs/

0

# Caching System

1

2

Script compilation caching interface with configurable cache implementations for improved performance in repeated script execution scenarios. The caching system supports both in-memory and persistent storage strategies.

3

4

## Capabilities

5

6

### Compiled Scripts Cache Interface

7

8

Core interface for caching compiled JVM scripts with flexible storage and retrieval mechanisms.

9

10

```kotlin { .api }

11

/**

12

* Cache interface for compiled JVM scripts

13

* Provides storage and retrieval of compiled scripts to improve performance

14

*/

15

interface CompiledJvmScriptsCache {

16

/**

17

* Retrieve cached compiled script

18

* @param script Source code of the script

19

* @param scriptCompilationConfiguration Configuration used for compilation

20

* @return Cached compiled script or null if not found

21

*/

22

fun get(

23

script: SourceCode,

24

scriptCompilationConfiguration: ScriptCompilationConfiguration

25

): CompiledScript?

26

27

/**

28

* Store compiled script in cache

29

* @param compiledScript The compiled script to cache

30

* @param script Original source code

31

* @param scriptCompilationConfiguration Configuration used for compilation

32

*/

33

fun store(

34

compiledScript: CompiledScript,

35

script: SourceCode,

36

scriptCompilationConfiguration: ScriptCompilationConfiguration

37

)

38

39

/**

40

* No-operation cache implementation

41

* Does not store or retrieve any scripts

42

*/

43

object NoCache : CompiledJvmScriptsCache {

44

override fun get(

45

script: SourceCode,

46

scriptCompilationConfiguration: ScriptCompilationConfiguration

47

): CompiledScript? = null

48

49

override fun store(

50

compiledScript: CompiledScript,

51

script: SourceCode,

52

scriptCompilationConfiguration: ScriptCompilationConfiguration

53

) = Unit

54

}

55

}

56

```

57

58

**Usage Examples:**

59

60

```kotlin

61

import kotlin.script.experimental.api.*

62

import kotlin.script.experimental.jvm.*

63

64

// Custom in-memory cache implementation

65

class InMemoryScriptCache : CompiledJvmScriptsCache {

66

private val cache = mutableMapOf<String, CompiledScript>()

67

68

private fun generateCacheKey(

69

script: SourceCode,

70

config: ScriptCompilationConfiguration

71

): String {

72

return "${script.text.hashCode()}-${config.hashCode()}"

73

}

74

75

override fun get(

76

script: SourceCode,

77

scriptCompilationConfiguration: ScriptCompilationConfiguration

78

): CompiledScript? {

79

val key = generateCacheKey(script, scriptCompilationConfiguration)

80

return cache[key]

81

}

82

83

override fun store(

84

compiledScript: CompiledScript,

85

script: SourceCode,

86

scriptCompilationConfiguration: ScriptCompilationConfiguration

87

) {

88

val key = generateCacheKey(script, scriptCompilationConfiguration)

89

cache[key] = compiledScript

90

}

91

}

92

93

// Use cache in compilation configuration

94

val scriptCache = InMemoryScriptCache()

95

96

val compilationConfig = ScriptCompilationConfiguration {

97

jvm {

98

compilationCache = scriptCache

99

}

100

}

101

```

102

103

### Cache Configuration Property

104

105

Configuration property for specifying cache implementation in script compilation settings.

106

107

```kotlin { .api }

108

/**

109

* Property key for compiled scripts cache in compilation configuration

110

*/

111

val ScriptCompilationConfiguration.compilationCache: PropertiesCollection.Key<CompiledJvmScriptsCache>

112

```

113

114

**Usage Example:**

115

116

```kotlin

117

// Configure cache in compilation settings

118

val config = ScriptCompilationConfiguration {

119

compilationCache = InMemoryScriptCache()

120

// ... other configuration

121

}

122

123

// Use NoCache for no caching

124

val noCacheConfig = ScriptCompilationConfiguration {

125

compilationCache = CompiledJvmScriptsCache.NoCache

126

}

127

```

128

129

## Implementation Examples

130

131

### File-Based Persistent Cache

132

133

```kotlin

134

import java.io.File

135

import java.security.MessageDigest

136

137

class FileBasedScriptCache(private val cacheDirectory: File) : CompiledJvmScriptsCache {

138

139

init {

140

cacheDirectory.mkdirs()

141

}

142

143

private fun generateCacheKey(

144

script: SourceCode,

145

config: ScriptCompilationConfiguration

146

): String {

147

val content = "${script.text}-${config.toString()}"

148

val digest = MessageDigest.getInstance("SHA-256")

149

val hash = digest.digest(content.toByteArray())

150

return hash.joinToString("") { "%02x".format(it) }

151

}

152

153

private fun getCacheFile(key: String): File {

154

return File(cacheDirectory, "$key.cached")

155

}

156

157

override fun get(

158

script: SourceCode,

159

scriptCompilationConfiguration: ScriptCompilationConfiguration

160

): CompiledScript? {

161

val key = generateCacheKey(script, scriptCompilationConfiguration)

162

val cacheFile = getCacheFile(key)

163

164

return if (cacheFile.exists()) {

165

try {

166

// Deserialize cached script

167

deserializeCompiledScript(cacheFile.readBytes())

168

} catch (e: Exception) {

169

// Cache corruption, remove file

170

cacheFile.delete()

171

null

172

}

173

} else {

174

null

175

}

176

}

177

178

override fun store(

179

compiledScript: CompiledScript,

180

script: SourceCode,

181

scriptCompilationConfiguration: ScriptCompilationConfiguration

182

) {

183

val key = generateCacheKey(script, scriptCompilationConfiguration)

184

val cacheFile = getCacheFile(key)

185

186

try {

187

val serializedScript = (compiledScript as KJvmCompiledScript).toBytes()

188

cacheFile.writeBytes(serializedScript)

189

} catch (e: Exception) {

190

// Failed to cache, continue without caching

191

println("Warning: Failed to cache script: ${e.message}")

192

}

193

}

194

195

fun clearCache() {

196

cacheDirectory.listFiles()?.forEach { it.delete() }

197

}

198

199

fun getCacheSize(): Long {

200

return cacheDirectory.listFiles()?.sumOf { it.length() } ?: 0L

201

}

202

}

203

```

204

205

### LRU In-Memory Cache

206

207

```kotlin

208

import java.util.LinkedHashMap

209

210

class LRUScriptCache(private val maxSize: Int = 100) : CompiledJvmScriptsCache {

211

212

private val cache = object : LinkedHashMap<String, CompiledScript>(16, 0.75f, true) {

213

override fun removeEldestEntry(eldest: MutableMap.MutableEntry<String, CompiledScript>): Boolean {

214

return size > maxSize

215

}

216

}

217

218

private fun generateCacheKey(

219

script: SourceCode,

220

config: ScriptCompilationConfiguration

221

): String {

222

return "${script.text.hashCode()}-${config.hashCode()}"

223

}

224

225

@Synchronized

226

override fun get(

227

script: SourceCode,

228

scriptCompilationConfiguration: ScriptCompilationConfiguration

229

): CompiledScript? {

230

val key = generateCacheKey(script, scriptCompilationConfiguration)

231

return cache[key]

232

}

233

234

@Synchronized

235

override fun store(

236

compiledScript: CompiledScript,

237

script: SourceCode,

238

scriptCompilationConfiguration: ScriptCompilationConfiguration

239

) {

240

val key = generateCacheKey(script, scriptCompilationConfiguration)

241

cache[key] = compiledScript

242

}

243

244

@Synchronized

245

fun clear() {

246

cache.clear()

247

}

248

249

@Synchronized

250

fun size(): Int = cache.size

251

252

@Synchronized

253

fun getStatistics(): CacheStatistics {

254

return CacheStatistics(

255

size = cache.size,

256

maxSize = maxSize,

257

hitRate = calculateHitRate()

258

)

259

}

260

}

261

262

data class CacheStatistics(

263

val size: Int,

264

val maxSize: Int,

265

val hitRate: Double

266

)

267

```

268

269

### Composite Cache Implementation

270

271

```kotlin

272

class CompositeScriptCache(

273

private val primaryCache: CompiledJvmScriptsCache,

274

private val secondaryCache: CompiledJvmScriptsCache

275

) : CompiledJvmScriptsCache {

276

277

override fun get(

278

script: SourceCode,

279

scriptCompilationConfiguration: ScriptCompilationConfiguration

280

): CompiledScript? {

281

// Try primary cache first

282

primaryCache.get(script, scriptCompilationConfiguration)?.let { return it }

283

284

// Try secondary cache

285

val result = secondaryCache.get(script, scriptCompilationConfiguration)

286

287

// If found in secondary, promote to primary

288

result?.let {

289

primaryCache.store(it, script, scriptCompilationConfiguration)

290

}

291

292

return result

293

}

294

295

override fun store(

296

compiledScript: CompiledScript,

297

script: SourceCode,

298

scriptCompilationConfiguration: ScriptCompilationConfiguration

299

) {

300

// Store in both caches

301

primaryCache.store(compiledScript, script, scriptCompilationConfiguration)

302

secondaryCache.store(compiledScript, script, scriptCompilationConfiguration)

303

}

304

}

305

306

// Usage: Fast in-memory cache with persistent backup

307

val compositeCache = CompositeScriptCache(

308

primaryCache = LRUScriptCache(maxSize = 50),

309

secondaryCache = FileBasedScriptCache(File("script-cache"))

310

)

311

```

312

313

### Time-Based Expiring Cache

314

315

```kotlin

316

import java.time.Instant

317

import java.time.Duration

318

import java.util.concurrent.ConcurrentHashMap

319

320

class ExpiringScriptCache(

321

private val ttl: Duration = Duration.ofHours(1)

322

) : CompiledJvmScriptsCache {

323

324

private data class CacheEntry(

325

val script: CompiledScript,

326

val timestamp: Instant

327

) {

328

fun isExpired(now: Instant): Boolean {

329

return Duration.between(timestamp, now) > ttl

330

}

331

}

332

333

private val cache = ConcurrentHashMap<String, CacheEntry>()

334

335

private fun generateCacheKey(

336

script: SourceCode,

337

config: ScriptCompilationConfiguration

338

): String {

339

return "${script.text.hashCode()}-${config.hashCode()}"

340

}

341

342

override fun get(

343

script: SourceCode,

344

scriptCompilationConfiguration: ScriptCompilationConfiguration

345

): CompiledScript? {

346

val key = generateCacheKey(script, scriptCompilationConfiguration)

347

val entry = cache[key]

348

val now = Instant.now()

349

350

return if (entry != null && !entry.isExpired(now)) {

351

entry.script

352

} else {

353

// Remove expired entry

354

cache.remove(key)

355

null

356

}

357

}

358

359

override fun store(

360

compiledScript: CompiledScript,

361

script: SourceCode,

362

scriptCompilationConfiguration: ScriptCompilationConfiguration

363

) {

364

val key = generateCacheKey(script, scriptCompilationConfiguration)

365

val entry = CacheEntry(compiledScript, Instant.now())

366

cache[key] = entry

367

}

368

369

fun cleanExpiredEntries() {

370

val now = Instant.now()

371

cache.entries.removeIf { (_, entry) -> entry.isExpired(now) }

372

}

373

}

374

```

375

376

### Configuration-Based Cache Factory

377

378

```kotlin

379

enum class CacheType {

380

NONE, IN_MEMORY, FILE_BASED, LRU, EXPIRING, COMPOSITE

381

}

382

383

data class CacheConfiguration(

384

val type: CacheType = CacheType.IN_MEMORY,

385

val maxSize: Int = 100,

386

val ttlHours: Long = 1,

387

val cacheDirectory: File? = null

388

)

389

390

object ScriptCacheFactory {

391

fun createCache(config: CacheConfiguration): CompiledJvmScriptsCache {

392

return when (config.type) {

393

CacheType.NONE -> CompiledJvmScriptsCache.NoCache

394

395

CacheType.IN_MEMORY -> InMemoryScriptCache()

396

397

CacheType.FILE_BASED -> {

398

val dir = config.cacheDirectory ?: File("script-cache")

399

FileBasedScriptCache(dir)

400

}

401

402

CacheType.LRU -> LRUScriptCache(config.maxSize)

403

404

CacheType.EXPIRING -> ExpiringScriptCache(Duration.ofHours(config.ttlHours))

405

406

CacheType.COMPOSITE -> CompositeScriptCache(

407

primaryCache = LRUScriptCache(config.maxSize),

408

secondaryCache = FileBasedScriptCache(

409

config.cacheDirectory ?: File("script-cache")

410

)

411

)

412

}

413

}

414

}

415

416

// Usage

417

val cacheConfig = CacheConfiguration(

418

type = CacheType.COMPOSITE,

419

maxSize = 200,

420

cacheDirectory = File("/tmp/kotlin-script-cache")

421

)

422

423

val cache = ScriptCacheFactory.createCache(cacheConfig)

424

425

val compilationConfig = ScriptCompilationConfiguration {

426

compilationCache = cache

427

}

428

```

429

430

## Best Practices

431

432

### Cache Key Generation

433

434

```kotlin

435

// Good: Include all relevant compilation factors

436

fun generateSecureCacheKey(

437

script: SourceCode,

438

config: ScriptCompilationConfiguration

439

): String {

440

val content = buildString {

441

append(script.text)

442

append(config.jvm.jvmTarget.value ?: "")

443

append(config.dependencies.joinToString { it.toString() })

444

append(config.jvm.jdkHome.value?.absolutePath ?: "")

445

}

446

447

return MessageDigest.getInstance("SHA-256")

448

.digest(content.toByteArray())

449

.joinToString("") { "%02x".format(it) }

450

}

451

```

452

453

### Cache Monitoring

454

455

```kotlin

456

class MonitoredScriptCache(

457

private val delegate: CompiledJvmScriptsCache,

458

private val metrics: CacheMetrics

459

) : CompiledJvmScriptsCache {

460

461

override fun get(

462

script: SourceCode,

463

scriptCompilationConfiguration: ScriptCompilationConfiguration

464

): CompiledScript? {

465

val result = delegate.get(script, scriptCompilationConfiguration)

466

if (result != null) {

467

metrics.recordHit()

468

} else {

469

metrics.recordMiss()

470

}

471

return result

472

}

473

474

override fun store(

475

compiledScript: CompiledScript,

476

script: SourceCode,

477

scriptCompilationConfiguration: ScriptCompilationConfiguration

478

) {

479

delegate.store(compiledScript, script, scriptCompilationConfiguration)

480

metrics.recordStore()

481

}

482

}

483

```