Repository navigation
KCL: Move cache out of static, into owned struct - #14540
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Merging this PR will not alter performance
Comparing Footnotes
|
c081fff to
962161c
Compare
| let mut old_ast = OLD_AST.write().await; | ||
| *old_ast = Some(old_state); | ||
| // Hide the cache's concrete state graph from Send/Sync proofs in callers. | ||
| trait CacheStorage: std::fmt::Debug + Send + Sync { |
There was a problem hiding this comment.
I don't really get why this exists.
There was a problem hiding this comment.
It's just a hack to make rustc do less work. This was originally a concrete type with no trait, but because the type is very deeply nested, it was marking rustc work hard to prove it was Sync + Send. By putting this trait here, we break the deep recursion into two parts: proving that everything that uses this is Send + Sync (easy) and then separately proving that the struct which implements it is Send + Sync (also easier). It does two smaller checks rather than one big check.
There was a problem hiding this comment.
Interesting. I haven't seen this trick before.
There was a problem hiding this comment.
It was Codex's find, but it's the same approach I've used for different problems (like avoiding cyclic dependencies, by changing a nested field struct into a trait)
28b2a55 to
6db189d
Compare
Background
KCL interpreter has a cache, where it stores "execution state", like the results of calculating variables, previous sketch mode executions, etc. This cache is really important for KCL's ux, because it lets the frontend add a new KCL function call to the end of the current KCL program without re-executing everything up to that point. It saves users a lot of time.
Problem
The cache is currently kept in a mutable global static. This works OK for now, but it's not good. Having one shared cache for everything in the process means you can't have two concurrent KCL executions -- even if they're on different engines! Mutable global state is bad even for single-threaded monolithic apps, but it's even worse in something like kcl-lib, where consumers might want to have several different executors.
Solution
Move the cache out of global statics, into a dedicated
Arc<RwMutex<Cache>>which can be shared by different executors if desired, but is probably just being used on its own.Reviewing
First, I suggest you review
cache.rsto see the changed cache structure (globals -> owned structs).Then view
kcl-wasm-lib/src/context.rswhich initializes this new cache, and shares it with every ExecutorContext it creates (so that every execution can use the cache).For x86/arm KCL execution (e.g. in the engine, or CLI, or Synera node), look at how ExecutorContext gets initialized in
kcl-lib/src/execution/mod.rs.Most of the other changes are straightforward changes like this: