做能支付的网站贵吗糖尿病吃什么药降糖效果好
Spark Tungsten
- 数据结构
 - Unsafe Row
 - 内存页管理
 
- 全阶段代码生成
 - 火山迭代模型
 - WSCG
 - 运行时动态生成
 
Tungsten (钨丝计划) : 围绕内核引擎的改进:
- 数据结构设计
 - 全阶段代码生成(WSCG,Whole Stage Code Generation)
 
数据结构
Tungsten 在数据结构的改进 :
- 紧凑的二进制格式 Unsafe Row
 - 内存页管理
 
Unsafe Row
Unsafe Row 是一种字节数组,所有字段按照 Schema 的顺序安放在数组中
- 定长字段值 , 插到字节中
 - 变长字段先在 Schema 对应位置插入偏移地址,再把字段长度和字段值存储后面
 - 节数组的存储能消除存储开销,只用一个数组对象就能封装一条数据,降低 GC 压力
 

用 JVM 传统的对象存储 :
- GenericMutableRow 封装一条数据,Array 用于存储实际的数据值
 - Array 中每个元素都是一个对象,如 : 整型 BoxedInteger、字符串 String
 - 在 JVM 堆内内存中,对象数越多 , 垃圾回收效率越低
 
内存页管理
Tungsten 地址 : 统一 128 位内存地址 , 为了统一管理 Off Heap 和 On Heap 内存空间
- 前 64 位 : Java Object
 - 后 64 位 : 偏移地址 Offset
 - 128 位的 Tungsten 地址,Off Heap/OnHeap 内存在寻址方式上不一样
 
On Heap 的 Tungsten 地址:
- 前 64 位存储 : JVM 堆内对象的引用或指针
 - 后 64 位 Offset 存储 : 数据在该对象内的偏移地址
 
Off Heap 的 Tungsten 地址:
- 前 64 位存储 null 值 : 通过 Java Unsafe API 直接管理操作系统内存,没有内存对象
 - 后 64 位 : 直接寻址操作系统的内存空间
 
堆内外的寻址方式 :
- Tungsten 用页表(Page Table)的数据结构,记录从 Object 引用到 JVM 对象地址的映射
 - 页表中记录的一个个内存页(Memory Page),内存页是一个 JVM 对象
 

Java 中 HashMap :
- HashMap :用数组 + 链表来实现 ,数组元素存储 Hash Code、链表头
 - 链表节点存储 3 个元素:Key 引用、Value 引用、下一个元素的地址
 - 弊端一:存储开销/GC 压力大 ,数据/索引各占一半
 - 弊端一:CPU 缓存命中率低,降低 CPU 利用率,对写入友好,但访问低效
 

Tungsten HashMap :
- Tungsten:用数组 + 内存页来实现。数组中存储元素:Hash code + Tungsten 内存地址,即:Object 引用 + Offset 的 128 位地址
 - 存储单元:内存页 (Java Object),一个内存页能存储多个数据条目。对 GC 友好
 - 内存页 : 用连续空间来存储数据,内存页 + 偏移量定位到每个数据元素。内存的访问方式成了顺序读取(SequentialAccess)。能提升 CPU cache 利用率,减少 CPU 中断
 

全阶段代码生成
迭代器嵌套 :同个 Stage 内部,把多个 RDD 的 compute 函数合成一个函数,再一次性输出数据
 WSCG :基于同一 Stage 内操作符的调用关系,把所有计算进行手写,并合成一个函数
火山迭代模型
迭代器嵌套 (Volcano Iteration Model) 的计算模式有两种操作:
- 内存数据的随机存取
 - 虚函数调用(next)
 

WSCG
Tungsten 引入 WSCG 机制,消除了 VI 模型引入的计算开销
手写代码例子 :

var count = 0for (citizen <- citizens) {if(citizen.city == "Beijing")count += 1
}
 
WSCG 工作过程 : 基于性能较差的代码,在运行时动态地 (On The Fly) 重构出性能更好的代码
运行时动态生成
手写代码的生成过程:
- 从父节点到子节点,递归调用 doProduce,生成代码框架
 - 从子节点到父节点,递归调用 doConsume,向框架填充每一个操作符的运算逻辑
 
1 while (table.hasNext()) {InternalRow row = table.next()2	if (row.getString(2) == "Beijing") {
3    Int user Id = row.getInt(0)rowWriter.write(0, userId)
4    ret = rowWriter.getRow()}
}
 

