-
Notifications
You must be signed in to change notification settings - Fork 980
CG Code Cache
Drill implements a code cache. The cache holds generated classes. The cache is indexed by the entire body of the generated code. This means that each operator must generate source code, then check if that body of source has already been compiled.
The reason for this approach is that each code generator has a very wide interface: the resulting code is dependent not just on properties of the template and query; but also on properties for the fragment, the query and globally. Thus, the only reliable, known key is the generated source itself rather than the (large number) of parameters used to generate the source.
The code cache is a mapping from CodeGenerator
to generated class. The code generator, however, holds onto code with a unique class name. To allow the cache to work, during code generation, CodeGenerator
replaces the specific class name with "GenericGenerated
", so that the generic version can be used as a key for the code cache.
CodeGenerator
computes its hash code based on two attributes: the definition and the generic code. Similarly, the equals( )
method compares these same two attributes.
The code cache is stored in a Google Guava LocalCache
.
LocalCache
has three very useful features:
- It is concurrent. If a new object must be added to the cache, it locks that cache entry, builds the item, and unlocks. This ensures that if two threads ask for the same value, the first one builds it and the second one waits for completion.
- It has "build if absent" semantics. (See
CodeCompiler.Loader
.) - It will expire old entries after a period of time or when the cache size goes above some threshold. The code cache holds up to 1000 entries.
Other notes:
-
LocalCache
provides the means to gather statistics for the hit rate, etc. Drill does not currently use this feature. -
LocalCache
provides a callback to remove a class. It would seem that a class must reside in aClassLoader
. Wouldn't we need a removal method to remove an expired class from the class loader? - (Note: this is probably wrong) It turns out the this class does not call the standard
Object.hash()
method, instead callingSystem.identityHashCode()
to get an identity hash code for the object itself. This means that Drill never actually reuses classes and instead generates a new class for each operator. This is because Drill does not set theCacheBuilder.keyEquivalence()
object, so thatLocalCache