Implement script level cache#403
Conversation
14b2ed5 to
52514bf
Compare
| } | ||
|
|
||
|
|
||
| def runScriptLevelCache(path: Path, args: Seq[String] = Vector.empty, |
There was a problem hiding this comment.
starting point for running scripts
Tries to load from cache else calls runscript
|
Great that you got tests passing! Some high level feedback:
That's the high-level review; your code looks great. Leaving some other feedback in-line. Now that you've got this working and tests passing, let's iterate on this diff until it's great! |
| |@ | ||
| |println(wd relativeTo x)""".stripMargin | ||
| ) | ||
| ) |
There was a problem hiding this comment.
Try not to re-format irrelevant things as part of this diff.
Things like this, and this (adding indentation to the whole for-comprehension) may or may not be the "right" formatting, but they have no place in an already-very-large diff like this one. Given that this diff is already large and hard to review for correctness, you should aim to avoid all this sort of minor/irrelevant changes so we can focus on the script-level-caching. If we care enough, we can put these changes into a separate diff later.
| pkgName: Seq[Name] | ||
| ): Res[Imports] = if(scriptCaching) { | ||
| val cacheTag = "cache" + Util.md5Hash(Iterator(code.getBytes)).map("%02x".format(_)).mkString | ||
| storage.asInstanceOf[Storage.Folder].classFilesListLoad(pkgName.map(_.backticked).mkString("."), wrapperName.backticked, cacheTag) match { |
There was a problem hiding this comment.
We should need to asInstanceOf to check if something is a Storage.Folder; instead, Storage should has classfilesListLoad and classfilesListLoad as part of it's interface, and Storage.InMemory should just keep things in an in-memory Map or something when saved and read from that Map on load
|
The unit tests aren't testing the right thing. Our goal isn't to get the Realistically, what you should do is:
|
| // blockNumber keeps track of blockIndex | ||
| cachedData.foreach { d => | ||
| for { | ||
| cls <- eval.loadClass(pkg + "." + wrapper + getBlockNumber, d._1) |
There was a problem hiding this comment.
What happens if loadClass or evalMain fail? You should probably use Res.map on this to propagate the Res[_] from each individual loadClass into a big Res[List[...]], and make evalCachedClassFiles return a Res[_] to represent the possibility of failure
Program flow is like:
Speed improvement is achieved by making processModule cache anything( scripts, predefs, imports including $ivy and $file,etc.) it processes at script level( at block level it already gets) and tries to retrieve from cache next time it is asked to process same code.
Process Module checks if the script is available in cacheFolder i.e.
scriptCaches. If it is not found, processModule0 is called which keeps the rest of program flow same as before this diff but passes back importHooks and other imports accumulated inprocessCorrectScriptfunction. This data is stored byclassFilesListSavewhich takes list ofpkgNameconcatenated withwrapperNameand hash values of blocks along with imports and stores them.If script is found in cache,
classFilesListLoadreads the list of names and hash values of blocks and loads those blocks from their cache folders made bycompileCacheLoadfunction. Loaded import hooks are resolved byresolveSingleImportHook. Along with retrieved imports this data is passed toeval.evalCacheClassFileswhich loads each classFile and evals the main function thus executing the code.The final imports are returned by processModule function whether evaled or loaded from cache, thus processModule is opaque from outside whether cache HIT or MISS, it behaves in exactly same way in return as well as side effects except cache save.