amplab/shark — pull request #325 by chenghao-intel (2014-04-17 14:37:20+00:00)
Title: Projection & Filter CodeGen for Shark0.9

Shark expression evaluation is based on Hive ObjectInspector/Evaluator framework, however, the "interpret" mode introduces many small objects creation, duplicated sub expression computing, and extra branch predictions etc., when computing the expression. As an in-memory computing framework, Shark need a faster way of expr eval.

Expr Eval codegen is the solution compile the expr once in master, and distributed the expr eval byte code on executor.
The major steps are:
1) Analysis the Expression Tree (ExprNodeDesc in Hive), and transform to internal expr node tree (TypedExprNode), with type info determined and constant folded.
2) Transform the TypedExprNode tree to executing ordered tree(ExecuteExprNode), and the expression node is joint by wedge node (e.g. variable declare and null value checking statement node.)
3) Simplify the ExecuteExprNode tree, by removing the duplicated checking / common sub expression from every executing path.
4) Generate the Java Source Code, compile it on master, and then distribute the classloader across the whole cluster via Spark broadcast API.

### Performance Improvements

HQL | Interpret (Secs) | Codegen (Secs) | Improved
------------- | ----------------- | --------------- | -------------
C1 | 75.706 | 19.851 | 3.81X
C2 |	72.092 | 21.243 | 3.39X
C3 |	88.496 | 40.052 | 2.21X
C4 |	23.677 | 22.251 | 1.06X
C5 |	10.291 | 11.108 | 0.93X

ID | HQL
---- | ----
C1 | select count(1) from test where b+c+d+e+f+g+h+b+c+d+e+f+g+h+e+f+f+d+b+c+d+e+f+g+h+e+e+f+f+f+e+e+e>0;
C2 | select count(1) from (select b+c+d+e+f+g+h+b+c+d+e+f+g+h+e+f+f+d+b+c+d+e+f+g+h+e+e+f+f+f+e+e+e as b from test) t where t.b>0;
C3 | select sum(c1), sum(c2), sum(c3), sum(c4), sum(c5), sum(c6), sum(c7) from (select b+c+d+e as c1, f+g+h+b+c as c2, d+e+f+g as c3, h+e+f+f as c4, d+b+c+d as c5, e+f+g+h+e as c6, e+f+f+f+e+e+e as c7 from test) t where t.c1>0 and t.c2>0 and t.c3>0 and t.c4>0 and t.c5>0 and t.c6>0 and t.c7>0;
C4 | select sum(t.b), sum(t.c), sum(t.d), sum( t.e), sum(t.f ), sum( t.g) from (select a, b, c, d, e,f, g, h, I, j from test) t;
C5 | select count(1) from (select b+c+d from test) t;

The codegen & compiling time is from 50ms ~ 500ms depends on the complexity of the expression.

### Configuration of the Expr Eval CodeGen
In $SHARK/conf/shark-env.sh
##### Output the generated java source code for diagnosing purpose
> SPARK_JAVA_OPTS+="-Dcg_source_code_path=/tmp/cgjava "
##### Increase the permgen memory size
> SPARK_JAVA_OPTS+="-Xms256m -Xmx1024m -XX:PermSize=512m -XX:MaxPermSize=512m "
##### Enable class unloading & Tuning JIT
> SPARK_JAVA_OPTS+="-XX:+CMSClassUnloadingEnabled -XX:+UseCodeCacheFlushing -XX:ReservedCodeCacheSize=256m "

### Enable / Disable the Expr Eval CodeGen
In shark REPL:
Enable / Disable the codegen feature
> set shark.query.cg=true/false; default value: true

Enable / Disable the codegen row/objectinspector in projection output; by default(false), it outputs an array of writable objects. In a real cluster testing, we found the codegen row object has performance defect in bitmask testing(with java.util.BitSet), hence we don't suggest to set the value as true. However codegen row object consists of java primitive objects, not the Writable classes, and more efficient in serialization / deserialization. We will figure out the otherway of bitmask testing soon.
> set shark.query.cg.oi=true/false; default value: false