首页 > 其他分享 >dremio ClassCompilerSelector 简单说明

dremio ClassCompilerSelector 简单说明

时间:2022-12-31 10:33:58浏览次数:64  
标签:sabot java exec dremio 简单 ClassCompilerSelector StraightPipe com

ClassCompilerSelector 核心是基于配置的策略选择不同的类编译器,然后编译为字节数组
当前包含了基于jdk 的以及janino

ClassCompiler实现类图

dremio ClassCompilerSelector 简单说明_java

 

 

使用到的类

直接使用主要包含CodeCompiler以及QueryClassLoader,间接的包含了不少,主要是对于生成的代码进行编译,具体代码生成利用了codemodel 包
同时从下边的调用关系可以看出dremio 的核心sabot 引擎的操作使用到了不少动态代码生成(包含了dremio 实际任务的执行)

  • 参考调用关系

 

Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 9) cost in 413 ms, listenerId: 29
ts=2022-12-28 05:38:35;thread_name=e1 - 1c5429a4-5f93-2ddc-5df9-a480c18a6500:frag:0:0;id=dd;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
@com.dremio.exec.compile.CodeCompiler.getInstances()
at com.dremio.exec.compile.CodeCompiler.getImplementationClass(CodeCompiler.java:79)
at com.dremio.exec.compile.CodeCompiler.getImplementationClass(CodeCompiler.java:63)
at com.dremio.exec.expr.CodeGenerator.getImplementationClass(CodeGenerator.java:161)
at com.dremio.exec.store.CoercionReader.setupProjector(CoercionReader.java:164)
at com.dremio.exec.store.CoercionReader.newSchema(CoercionReader.java:136)
at com.dremio.exec.store.CoercionReader.setup(CoercionReader.java:119)
at com.dremio.sabot.op.scan.ScanOperator.setupReaderAsCorrectUser(ScanOperator.java:343)
at com.dremio.sabot.op.scan.ScanOperator.setupReader(ScanOperator.java:334)
at com.dremio.sabot.op.scan.ScanOperator.setup(ScanOperator.java:298)
at com.dremio.sabot.driver.SmartOp$SmartProducer.setup(SmartOp.java:592)
at com.dremio.sabot.driver.Pipe$SetupVisitor.visitProducer(Pipe.java:79)
at com.dremio.sabot.driver.Pipe$SetupVisitor.visitProducer(Pipe.java:63)
at com.dremio.sabot.driver.SmartOp$SmartProducer.accept(SmartOp.java:562)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.Pipeline.setup(Pipeline.java:71)
at com.dremio.sabot.exec.fragment.FragmentExecutor.setupExecution(FragmentExecutor.java:598)
at com.dremio.sabot.exec.fragment.FragmentExecutor.run(FragmentExecutor.java:430)
at com.dremio.sabot.exec.fragment.FragmentExecutor.access$1700(FragmentExecutor.java:106)
at com.dremio.sabot.exec.fragment.FragmentExecutor$AsyncTaskImpl.run(FragmentExecutor.java:973)
at com.dremio.sabot.task.AsyncTaskWrapper.run(AsyncTaskWrapper.java:121)
at com.dremio.sabot.task.slicing.SlicingThread.mainExecutionLoop(SlicingThread.java:247)
at com.dremio.sabot.task.slicing.SlicingThread.run(SlicingThread.java:171)

 

ts=2022-12-28 05:38:35;thread_name=e1 - 1c5429a4-5f93-2ddc-5df9-a480c18a6500:frag:0:0;id=dd;is_daemon=false;priority=5;TCCL=sun.misc.Launcher$AppClassLoader@18b4aac2
@com.dremio.exec.compile.CodeCompiler.getImplementationClass()
at com.dremio.exec.compile.CodeCompiler.getImplementationClass(CodeCompiler.java:63)
at com.dremio.exec.expr.CodeGenerator.getImplementationClass(CodeGenerator.java:161)
at com.dremio.exec.store.CoercionReader.setupProjector(CoercionReader.java:164)
at com.dremio.exec.store.CoercionReader.newSchema(CoercionReader.java:136)
at com.dremio.exec.store.CoercionReader.setup(CoercionReader.java:119)
at com.dremio.sabot.op.scan.ScanOperator.setupReaderAsCorrectUser(ScanOperator.java:343)
at com.dremio.sabot.op.scan.ScanOperator.setupReader(ScanOperator.java:334)
at com.dremio.sabot.op.scan.ScanOperator.setup(ScanOperator.java:298)
at com.dremio.sabot.driver.SmartOp$SmartProducer.setup(SmartOp.java:592)
at com.dremio.sabot.driver.Pipe$SetupVisitor.visitProducer(Pipe.java:79)
at com.dremio.sabot.driver.Pipe$SetupVisitor.visitProducer(Pipe.java:63)
at com.dremio.sabot.driver.SmartOp$SmartProducer.accept(SmartOp.java:562)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.StraightPipe.setup(StraightPipe.java:102)
at com.dremio.sabot.driver.Pipeline.setup(Pipeline.java:71)
at com.dremio.sabot.exec.fragment.FragmentExecutor.setupExecution(FragmentExecutor.java:598)
at com.dremio.sabot.exec.fragment.FragmentExecutor.run(FragmentExecutor.java:430)
at com.dremio.sabot.exec.fragment.FragmentExecutor.access$1700(FragmentExecutor.java:106)
at com.dremio.sabot.exec.fragment.FragmentExecutor$AsyncTaskImpl.run(FragmentExecutor.java:973)
at com.dremio.sabot.task.AsyncTaskWrapper.run(AsyncTaskWrapper.java:121)
at com.dremio.sabot.task.slicing.SlicingThread.mainExecutionLoop(SlicingThread.java:247)
at com.dremio.sabot.task.slicing.SlicingThread.run(SlicingThread.java:171)

对于实际代码生成以及代码的编译是基于了模版TemplateClassDefinition
构造函数如下

 

// 需要包含TemplateClassDefinition 定义,目前系统已经包含了不少实现
CodeGenerator(CodeCompiler compiler, MappingSet mappingSet, TemplateClassDefinition<T> definition, FunctionContext functionContext) {
Preconditions.checkNotNull(definition.getSignature(),
"The signature for defintion %s was incorrectly initialized.", definition);
this.definition = definition;
this.compiler = compiler;
this.className = definition.getExternalInterface().getSimpleName() + "Gen" + definition.getNextClassNumber();
this.fqcn = PACKAGE_NAME + "." + className;
try {
// 基于codeModel
this.model = new JCodeModel();
JDefinedClass clazz = model._package(PACKAGE_NAME)._class("GenericGenerated");
clazz = clazz._extends(model.directClass(definition.getTemplateClassName()));
clazz.constructor(JMod.PUBLIC).body().invoke(SignatureHolder.INIT_METHOD);
rootGenerator = new ClassGenerator<>(this, mappingSet, definition.getSignature(), new EvaluationVisitor(functionContext), clazz, model);
this.functionContext = functionContext;
} catch (JClassAlreadyExistsException e) {
throw new IllegalStateException(e);
}
}

实际调用

public T getImplementationClass(){
// 基于CodeCompiler 进行加载
return compiler.getImplementationClass(this);
}

 

public List<T> getImplementationClass(final int instanceCount){
// 基于CodeCompiler 进行加载
return compiler.getImplementationClass(this, instanceCount);
}

实际类编译

//  基于缓存编译,QueryClassLoader 结合ClassCompilerSelector 进行实际类编译的处理
private class GeneratedCodeToCompiledClazzCacheLoader extends CacheLoader<CodeGenerator<?>, GeneratedClassEntry> {
@Override
public GeneratedClassEntry load(final CodeGenerator<?> cg) throws Exception {
logger.debug("In Cache load; Compile code");
final QueryClassLoader loader = new QueryClassLoader(selector);
final Class<?> c = transformer.getImplementationClass(loader, cg.getDefinition(),
cg.getGeneratedCode(), cg.getMaterializedClassName());
logger.debug("Exit Cache load");
return new GeneratedClassEntry(c);
}
}
  • 参考处理
    比如CoercionReader

 

protected void setupProjector(VectorContainer projectorOutput) {
if (DEBUG_PRINT) {
debugPrint(projectorOutput);
}

 

if (incoming.getSchema() == null || incoming.getSchema().getFieldCount() == 0) {
return;
}
// 通过OperatorContext的ClassProducer进行类的创建以及编译,同时不同的处理会包含自己的模版定义
//  Projector 的为: TemplateClassDefinition<Projector> TEMPLATE_DEFINITION = new TemplateClassDefinition<Projector>(Projector.class, ProjectorTemplate.class);
final ClassGenerator<Projector> cg = context.getClassProducer().createGenerator(Projector.TEMPLATE_DEFINITION).getRoot();
final IntHashSet transferFieldIds = new IntHashSet();
final List<TransferPair> transfers = Lists.newArrayList();

 

try {
splitter = ProjectOperator.createSplitterWithExpressions(incoming, exprs, transfers, cg,
transferFieldIds, context, projectorOptions, projectorOutput, targetSchema);
//  此处还会包含支持GANDIVA模式的处理
splitter.setupProjector(projectorOutput, javaCodeGenWatch, gandivaCodeGenWatch);
} catch (Exception e) {
throw Throwables.propagate(e);
}
javaCodeGenWatch.start();
this.projector = cg.getCodeGenerator().getImplementationClass();
this.projector.setup(context.getFunctionContext(), incoming, projectorOutput, transfers, name -> null);
javaCodeGenWatch.stop();
OperatorStats stats = context.getStats();
stats.addLongStat(ScanOperator.Metric.JAVA_BUILD_TIME_NS, javaCodeGenWatch.elapsed(TimeUnit.NANOSECONDS));
stats.addLongStat(ScanOperator.Metric.GANDIVA_BUILD_TIME_NS, gandivaCodeGenWatch.elapsed(TimeUnit.NANOSECONDS));
gandivaCodeGenWatch.reset();
javaCodeGenWatch.reset();

 

// when individual fields of a struct column are projected, currently it results
// in setting schema changed flag. Resetting the flag in iceberg flow, since
// schema learning should not happen in iceberg flow
outputMutator.getAndResetSchemaChanged();
}

说明

dremio 实际的执行计划使用了不少动态代码生成技术,同时如果基于jprofiler 等分析工具也会看到不少的类加载处理

dremio ClassCompilerSelector 简单说明_java_02

 

 

参加资料

sabot/kernel/src/main/java/com/dremio/exec/compile/ClassCompilerSelector.java
sabot/kernel/src/main/java/com/dremio/exec/expr/CodeGenerator.java
sabot/kernel/src/main/java/com/dremio/exec/expr/SingleClassStringWriter.java
sabot/kernel/src/main/java/com/dremio/exec/expr/ClassGenerator.java
sabot/kernel/src/main/java/com/dremio/sabot/exec/context/OperatorContext.java
sabot/kernel/src/main/java/com/dremio/exec/expr/ClassProducer.java
sabot/kernel/src/main/java/com/dremio/exec/compile/TemplateClassDefinition.java

标签:sabot,java,exec,dremio,简单,ClassCompilerSelector,StraightPipe,com
From: https://blog.51cto.com/rongfengliang/5982000

相关文章

  • dremio UserServer 简单说明
    UserServer目的是对于UserRPCServer进行生命周期管理(基于netty开发的)主要是处理非web请求(实际上就是直接链接的服务)从官方源码上UserServer的创建只能在协调节点(当然......
  • 微信聊天记录删除了怎么恢复,简单几步搞定!
    在当下社会,微信已经成为了,我们生活中不可缺少的一部分,更有夸张的说法,你可以一天不吃饭,可是不能一天不打开微信APP进行聊天,而很多用户在使用微信进行聊天的时候会发现,与QQ不......
  • C# WinForm国际化实现的简单方法
    本文是完善:https://www.jb51.net/article/45675.htm文章描述很详细,重要的代码都贴出来了我帮大家懒到家,将窗口代码和资源文件也传上来到手可运行,直观的了解多......
  • 基于WPF实现简单放大镜效果
    原文网址:https://www.jb51.net/article/271074.htmWPF如何实现简单放大镜框架使用.NET40;VisualStudio2019;实现此功能需要用到 VisualBrush ,放大镜展现使用 Can......
  • 使用Python3+PyQT5+Pyserial实现简单的串口工具方法
    练手项目,先上图先实现一个简单的串口工具,为之后的上位机做准备代码如下:github下载地址pyserial_demo.pyimportsysimportserialimportserial.tools......
  • RAM——单口、双口、简单双口、真双口的区别
    单口 RAM(SingleRAM)、双口RAM(DualRAM)、简单双口RAM(Simple-Dual RAM)、真双口RAM(True-DualRAM)有什么不同?对于 分布式RAM,支持简单双口RAM和双口RAM,不能配置成真......
  • MySQL 5.7 版本的安装及简单使用(图文教程)
    MySQL5.7版本的安装使用详细教程写得还是比较详细,甚至有些繁琐,有很多步骤在其他的教程文档里都是省略掉的,但是我还是要写出来,因为我当时走了很多弯路,我希望你们能够避免我......
  • 简单hibernate5.2.10入门配置
    1、官网下载hibernate5相关jar包​​http://hibernate.org/orm/​​2、解压后,在lib目录中找到required目录下的jar包添加至项目。再添加数据库驱动包,博主用MySQLjar包添加......
  • eclipse下简单配置struts2.5.8
    1.下载structs2.5.8jar包。首先去官方下载structs2.5.8的jar包。下载地址:http://struts.apache.org/download.cgi#struts258点击下载完成之后,将该压缩包进行解压。2.在eclip......
  • Hibernate环境部署与注解简单使用
    Hibernate是对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,对对象进行持久化。它可以自动生成SQL语句,自动执行。简单的说就是帮你把XXXDAO的繁琐工作都给自动完成了,要......