`
- 浏览:
17666 次
- 性别:
- 来自:
杭州
-
以具体的SQL语句 select a+b fromtable 为例进行说明,下面是它的解析过程:
1.调用虚函数Add.eval(),需确认Add两边数据类型
2.调用虚函数a.eval(),需要确认a的数据类型
3.确认a的数据类型是int,装箱
4.调用虚函数b.eval(),需确认b的数据类型
5.确认b的数据类型是int,装箱
6.调用int类型的add
7.返回装箱后的计算结果
从上面的步骤可以看出,一条SQL语句的解析需要进行多次虚函数的调用。我们知道,虚函数的调用会极大的降低效率。那么,虚函数的调用为什么会影响效率呢?
有人答案是:虚函数调用会进行一次间接寻址过程。事实上这一步间接寻址真的会显著降低运行效率?显然不是。
流水线的打断才是真正降低效率的原因。
我们知道,虚函数的调用时是运行时多态,意思就是在编译期你是无法知道虚函数的具体调用。设想一下,如果说不是虚函数,那么在编译时期,其相对地址是确定的,编译器可以直接生成jmp/invoke指令; 如果是虚函数,多出来的一次查找vtable所带来的开销,倒是次要的,关键在于,这个函数地址是动态的,譬如 取到的地址在eax里,则在call eax之后的那些已经被预取进入流水线的所有指令都将失效。流水线越长,一次分支预测失败的代价也就越大,如下所示:
pf->test
001E146D mov eax,dword ptr[pf]
011E1470 mov edx,dword,ptr[eax]
011E1472 mov esi,esp
011E1474 mov ecx,dword ptr[pf]
011E1477 mov eax,dword ptr[edx]
011E1479 eax <-----------------------分支预测失败
011E147B cmp esi esp
011E147D @ILT+355(__RTC_CheckEsp)(11E1168h)
说到流水线,penalty基本上都是因为气泡(分支指令导致预取失败)。虽然引入流水线极大提高了效率,流水线不是越长越好。
Scala的运行时反射机制很好机制很好解决了这个问题。未完待续,下回分解。
分享到:
Global site tag (gtag.js) - Google Analytics
相关推荐
SparkSQL不仅依赖内存列存储和字节码生成技术,还引入了成本模型进行动态查询优化,能够根据实际数据分布和硬件资源自动选择最优的执行计划。此外,其灵活的架构允许用户自定义SQL解析器、分析器和优化器,以便更好...
字节码生成技术是指将SQL查询转换为高效的字节码执行流的过程。这种技术可以显著提高复杂表达式的执行速度,因为它减少了解释器的开销,并允许进行低级的优化。 **1.2.3 Scala代码优化** Scala作为一种高性能的...
6. Code Generation:SparkSQL使用Java字节码生成技术,将查询计划转化为高效的执行代码,减少运行时的解释开销。 二、SparkSQL调优策略 1. 表分区:合理分区可以减少数据扫描量,提高查询速度。根据查询条件选择...
Catalyst优化器可以生成Java字节码,直接在运行时执行,减少了解释执行的开销,提高了性能。 9. **Columnar Storage and Compression**: Spark SQL支持列式存储和数据压缩,这种存储方式在分析查询中通常比行式...
Catalyst的Tungsten项目引入了基于IR(Intermediate Representation)的代码生成技术,可以生成高效的Java字节码,从而提高Spark SQL的执行性能。 8. **DataFrame操作**: DataFrame提供了丰富的操作接口,如...