Skip to content

Commit

Permalink
DRILL-6763: Codegen optimization of SQL functions with constant values(
Browse files Browse the repository at this point in the history
  • Loading branch information
lushuifeng committed Oct 9, 2018
1 parent 3bc3b66 commit 1b2705e
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 132 deletions.
Expand Up @@ -22,10 +22,13 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import io.netty.buffer.DrillBuf;
import org.apache.commons.lang3.StringUtils;
import org.apache.drill.common.exceptions.DrillRuntimeException;
import org.apache.drill.common.expression.LogicalExpression;
import org.apache.drill.common.types.TypeProtos;
Expand All @@ -39,7 +42,9 @@
import org.apache.drill.exec.compile.sig.SignatureHolder;
import org.apache.drill.exec.exception.SchemaChangeException;
import org.apache.drill.exec.expr.fn.WorkspaceReference;
import org.apache.drill.exec.expr.holders.ValueHolder;
import org.apache.drill.exec.record.TypedFieldId;
import org.apache.drill.shaded.guava.com.google.common.base.Function;
import org.apache.drill.shaded.guava.com.google.common.base.Preconditions;
import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
Expand Down Expand Up @@ -86,6 +91,7 @@ public enum BlockType {SETUP, EVAL, RESET, CLEANUP}
private ClassGenerator<T> innerClassGenerator;
private LinkedList<SizedJBlock>[] blocks;
private LinkedList<SizedJBlock>[] oldBlocks;
private Map<JMethod, Function<DrillBuf, ? extends ValueHolder>> setters;

/**
* Assumed that field has 3 indexes within the constant pull: index of the CONSTANT_Fieldref_info +
Expand Down Expand Up @@ -135,6 +141,7 @@ public static MappingSet getDefaultMapping() {
this.evaluationVisitor = eval;
this.model = model;
this.optionManager = optionManager;
setters = new HashMap<>();

blocks = (LinkedList<SizedJBlock>[]) new LinkedList[sig.size()];
for (int i =0; i < sig.size(); i++) {
Expand Down Expand Up @@ -536,6 +543,26 @@ public JVar declareClassField(String prefix, JType t, JExpression init) {
return clazz.field(JMod.NONE, t, prefix + index++, init);
}

/**
* declare a setter method for the argument {@code var}.
* argument {@code function} holds the constant value which
* returns a value holder must be invoked when the class instance created.
*
* @param var the class member variable
* @param function the function holds the constant value
*/
public void declareSetterMethod(JVar var, Function<DrillBuf, ? extends ValueHolder> function) {
JMethod setter = clazz.method(JMod.PUBLIC, void.class, "set" + StringUtils.capitalize(var.name()));
JVar param = setter.param(var.type(), var.name());
JBlock body = setter.body();
body.assign(JExpr._this().ref(var), param);
setters.put(setter, function);
}

public Map<JMethod, Function<DrillBuf, ? extends ValueHolder>> getSetters() {
return setters;
}

public HoldingContainer declare(MajorType t) {
return declare(t, true);
}
Expand Down
Expand Up @@ -24,6 +24,7 @@
import java.util.Set;
import java.util.Stack;

import io.netty.buffer.DrillBuf;
import org.apache.drill.common.expression.AnyValueExpression;
import org.apache.drill.common.expression.BooleanOperator;
import org.apache.drill.common.expression.CastExpression;
Expand Down Expand Up @@ -56,26 +57,29 @@
import org.apache.drill.common.expression.ValueExpressions.TimeStampExpression;
import org.apache.drill.common.expression.ValueExpressions.VarDecimalExpression;
import org.apache.drill.common.expression.visitors.AbstractExprVisitor;
import org.apache.drill.common.types.TypeProtos;
import org.apache.drill.common.types.TypeProtos.MajorType;
import org.apache.drill.common.types.TypeProtos.MinorType;
import org.apache.drill.common.types.Types;
import org.apache.drill.exec.compile.sig.ConstantExpressionIdentifier;
import org.apache.drill.exec.compile.sig.GeneratorMapping;
import org.apache.drill.exec.compile.sig.MappingSet;
import org.apache.drill.exec.expr.ClassGenerator.BlockType;
import org.apache.drill.exec.expr.ClassGenerator.HoldingContainer;
import org.apache.drill.exec.expr.fn.AbstractFuncHolder;
import org.apache.drill.exec.expr.holders.ValueHolder;
import org.apache.drill.exec.physical.impl.filter.ReturnValueExpression;
import org.apache.drill.exec.vector.ValueHolderHelper;
import org.apache.drill.exec.vector.complex.reader.FieldReader;

import org.apache.drill.shaded.guava.com.google.common.base.Function;
import org.apache.drill.shaded.guava.com.google.common.collect.Lists;
import org.apache.drill.shaded.guava.com.google.common.collect.Maps;
import com.sun.codemodel.JBlock;
import com.sun.codemodel.JClass;
import com.sun.codemodel.JConditional;
import com.sun.codemodel.JExpr;
import com.sun.codemodel.JExpression;
import com.sun.codemodel.JFieldRef;
import com.sun.codemodel.JInvocation;
import com.sun.codemodel.JLabel;
import com.sun.codemodel.JType;
Expand Down Expand Up @@ -265,72 +269,94 @@ public HoldingContainer visitSchemaPath(SchemaPath path, ClassGenerator<?> gener
throw new UnsupportedOperationException("All schema paths should have been replaced with ValueVectorExpressions.");
}

private HoldingContainer getHoldingContainer(ClassGenerator<?> generator,
MajorType majorType,
Function<DrillBuf, ? extends ValueHolder> function) {
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("constant", holderType);
generator.declareSetterMethod(var, function);
JFieldRef outputSet = null;
if (majorType.getMode() == TypeProtos.DataMode.OPTIONAL) {
outputSet = var.ref("isSet");
}
return new HoldingContainer(majorType, var, var.ref("value"), outputSet);
}

@Override
public HoldingContainer visitLongConstant(LongExpression e, ClassGenerator<?> generator) throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getLong()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getBigIntHolder(e.getLong()));
}

@Override
public HoldingContainer visitIntConstant(IntExpression e, ClassGenerator<?> generator) throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getInt()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getIntHolder(e.getInt()));
}

@Override
public HoldingContainer visitDateConstant(DateExpression e, ClassGenerator<?> generator) throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getDate()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getDateHolder(e.getDate()));
}

@Override
public HoldingContainer visitTimeConstant(TimeExpression e, ClassGenerator<?> generator) throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getTime()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getTimeHolder(e.getTime()));
}

@Override
public HoldingContainer visitIntervalYearConstant(IntervalYearExpression e, ClassGenerator<?> generator)
throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getIntervalYear()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getIntervalYearHolder(e.getIntervalYear()));
}

@Override
public HoldingContainer visitTimeStampConstant(TimeStampExpression e, ClassGenerator<?> generator)
throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getTimeStamp()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getTimeStampHolder(e.getTimeStamp()));
}

@Override
public HoldingContainer visitFloatConstant(FloatExpression e, ClassGenerator<?> generator)
throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getFloat()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getFloat4Holder(e.getFloat()));
}

@Override
public HoldingContainer visitDoubleConstant(DoubleExpression e, ClassGenerator<?> generator)
throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getDouble()));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getFloat8Holder(e.getDouble()));
}

@Override
public HoldingContainer visitBooleanConstant(BooleanExpression e, ClassGenerator<?> generator)
throws RuntimeException {
HoldingContainer out = generator.declare(e.getMajorType());
generator.getEvalBlock().assign(out.getValue(), JExpr.lit(e.getBoolean() ? 1 : 0));
return out;
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getBitHolder(e.getBoolean() ? 1 : 0));
}

@Override
Expand Down Expand Up @@ -589,110 +615,64 @@ private HoldingContainer visitReturnValueExpression(ReturnValueExpression e, Cla
@Override
public HoldingContainer visitQuotedStringConstant(QuotedString e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("string", holderType);
JExpression stringLiteral = JExpr.lit(e.value);
JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarCharHolder").arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getVarCharHolder(buffer, e.getString()));
}

@Override
public HoldingContainer visitIntervalDayConstant(IntervalDayExpression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = Types.required(MinorType.INTERVALDAY);
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("intervalday", holderType);
JExpression dayLiteral = JExpr.lit(e.getIntervalDay());
JExpression millisLiteral = JExpr.lit(e.getIntervalMillis());
setup.assign(
var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getIntervalDayHolder").arg(dayLiteral)
.arg(millisLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getIntervalDayHolder(e.getIntervalDay(), e.getIntervalMillis()));
}

@Override
public HoldingContainer visitDecimal9Constant(Decimal9Expression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec9", holderType);
JExpression valueLiteral = JExpr.lit(e.getIntFromDecimal());
JExpression scaleLiteral = JExpr.lit(e.getScale());
JExpression precisionLiteral = JExpr.lit(e.getPrecision());
setup.assign(
var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal9Holder").arg(valueLiteral)
.arg(scaleLiteral).arg(precisionLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getDecimal9Holder(e.getIntFromDecimal(), e.getScale(), e.getPrecision()));
}

@Override
public HoldingContainer visitDecimal18Constant(Decimal18Expression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec18", holderType);
JExpression valueLiteral = JExpr.lit(e.getLongFromDecimal());
JExpression scaleLiteral = JExpr.lit(e.getScale());
JExpression precisionLiteral = JExpr.lit(e.getPrecision());
setup.assign(
var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal18Holder").arg(valueLiteral)
.arg(scaleLiteral).arg(precisionLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getDecimal18Holder(e.getLongFromDecimal(), e.getScale(), e.getPrecision()));
}

@Override
public HoldingContainer visitDecimal28Constant(Decimal28Expression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec28", holderType);
JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal28Holder")
.arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getDecimal28Holder(buffer, e.getBigDecimal()));
}

@Override
public HoldingContainer visitDecimal38Constant(Decimal38Expression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("dec38", holderType);
JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getDecimal38Holder")
.arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getDecimal38Holder(buffer, e.getBigDecimal()));
}

@Override
public HoldingContainer visitVarDecimalConstant(VarDecimalExpression e, ClassGenerator<?> generator)
throws RuntimeException {
MajorType majorType = e.getMajorType();
JBlock setup = generator.getBlock(BlockType.SETUP);
JType holderType = generator.getHolderType(majorType);
JVar var = generator.declareClassField("varDec", holderType);
JExpression stringLiteral = JExpr.lit(e.getBigDecimal().toString());
JExpression buffer = generator.getMappingSet().getIncoming().invoke("getContext").invoke("getManagedBuffer");
setup.assign(var,
generator.getModel().ref(ValueHolderHelper.class).staticInvoke("getVarDecimalHolder")
.arg(buffer).arg(stringLiteral));
return new HoldingContainer(majorType, var, null, null);
return getHoldingContainer(
generator,
e.getMajorType(),
buffer -> ValueHolderHelper.getVarDecimalHolder(buffer, e.getBigDecimal()));
}

@Override
Expand Down
Expand Up @@ -227,7 +227,7 @@ public ValueHolder visitDecimal28Constant(final ValueExpressions.Decimal28Expres
@Nullable
@Override
public ValueHolder apply(DrillBuf buffer) {
return ValueHolderHelper.getDecimal28Holder(buffer, decExpr.getBigDecimal().toString());
return ValueHolderHelper.getDecimal28Holder(buffer, decExpr.getBigDecimal());
}
});
}
Expand All @@ -238,15 +238,15 @@ public ValueHolder visitDecimal38Constant(final ValueExpressions.Decimal38Expres
@Nullable
@Override
public ValueHolder apply(DrillBuf buffer) {
return ValueHolderHelper.getDecimal38Holder(buffer, decExpr.getBigDecimal().toString());
return ValueHolderHelper.getDecimal38Holder(buffer, decExpr.getBigDecimal());
}
});
}

@Override
public ValueHolder visitVarDecimalConstant(final ValueExpressions.VarDecimalExpression decExpr, Integer value) throws RuntimeException {
return getConstantValueHolder(decExpr.getBigDecimal().toString(), decExpr.getMajorType().getMinorType(),
buffer -> ValueHolderHelper.getVarDecimalHolder(Objects.requireNonNull(buffer), decExpr.getBigDecimal().toString()));
buffer -> ValueHolderHelper.getVarDecimalHolder(Objects.requireNonNull(buffer), decExpr.getBigDecimal()));
}

@Override
Expand Down

0 comments on commit 1b2705e

Please sign in to comment.