Description
Reproduce steps:
- create a new table with array type: create table test_code_gen(a array<int>);
- Add log4j.logger.org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator = DEBUG to log4j.properties;
- Enter spark-shell, fire a query: spark.sql("select * from test_code_gen").collect
- Everytime, Dataset.collect is called, SpecificSafeProjection class is generated, but the code for the class cannot be reused because everytime the id for two variables in the generated class is changed: MapObjects_loopValue and MapObjects_loopIsNull. So even the class generated before has been cached, new code cannot match the cache key so that new code need to be compiled again which cost some time. The time cost for compile is increasing with the growth of column number, for wide table, this cost can more than 2s.
object MapObjects { private val curId = new java.util.concurrent.atomic.AtomicInteger() val id = curId.getAndIncrement() val loopValue = s"MapObjects_loopValue$id" val loopIsNull = if (elementNullable) { s"MapObjects_loopIsNull$id" } else { "false" }
First time run:
class SpecificSafeProjection extends org.apache.spark.sql.catalyst.expressions.codegen.BaseProjection { private int MapObjects_loopValue1; private boolean MapObjects_loopIsNull1; private UTF8String MapObjects_loopValue2; private boolean MapObjects_loopIsNull2; }
Second time run:
class SpecificSafeProjection extends org.apache.spark.sql.catalyst.expressions.codegen.BaseProjection { private int MapObjects_loopValue3; private boolean MapObjects_loopIsNull3; private UTF8String MapObjects_loopValue4; private boolean MapObjects_loopIsNull4; }
Expectation:
The code generated by GenerateSafeProjection can be reused if the query is same.
Attachments
Issue Links
- relates to
-
SPARK-27871 LambdaVariable should use per-query unique IDs instead of globally unique IDs
- Resolved