Presto的核心就是纯内存计算,因此内存对于Presto来说至关重要
org.airlift是工具类,跟Presto是同一个开发者
一、Slice
- ClassLayout和Unsafe
 
在Java中一般是无法取得类的大小的,需要通过一些特殊的手段,例如Unsafe包中的方法
org.openjdk.jol包封装了很多Unsafe的方法
我们可以通过jol中的ClassLayout类来或者我们创建的Java对象在内存中的大小
① 常规方法
public static void common() {int []nums = new int[20];for (int i=0 ; i< nums.length; i++) {nums[i] = i;}for (int i: nums) {System.out.println(i);}}
② Unsafe方式
public static void unSafeMethod() throws Exception{Field field = Unsafe.class.getDeclaredField("theUnsafe");field.setAccessible(true);Unsafe unsafe = (Unsafe) field.get(null);int []nums = new int[20];for (int i=0 ; i<nums.length; i++) {unsafe.putInt(nums, (long) i * Unsafe.ARRAY_INT_INDEX_SCALE + Unsafe.ARRAY_INT_BASE_OFFSET, i);}System.out.println("BASE_OFFSET:" + Unsafe.ARRAY_INT_BASE_OFFSET);System.out.println("INDEX_SCALE:" + Unsafe.ARRAY_LONG_INDEX_SCALE);for (int i: nums) {System.out.println(i);}}
③ Unsafe创建大对象的方式(Slice的原理)
public static void unSafeObjectMethod() throws Exception {Person person = new Person();ClassLayout personClassLayout = ClassLayout.parseClass(Person.class);long size = personClassLayout.instanceSize();System.out.println("size: " + size);System.out.println("header size: " + personClassLayout.headerSize());Field field = Unsafe.class.getDeclaredField("theUnsafe");field.setAccessible(true);Unsafe unsafe = (Unsafe) field.get(null);// 得到所有的field信息SortedSet<FieldLayout> fieldLayouts = personClassLayout.fields();for (FieldLayout layout: fieldLayouts) {switch (layout.name()) {case "name":unsafe.putObject(person, ((long) layout.offset()), "zhu");break;case "age":unsafe.putInt(person, ((long) layout.offset()), 20);break;default:break;}}System.out.println(person);}static class Person {private String name;private int age;}
2、类详解
我们无法直接创建Slice类,可以通过Slices类提供的很多的静态方法来进行创建
//利用这个方法我们可以直接创建一个容量为capacity的Slice,底层就是创建了一个byte[capacity]的数组,不过这个对象是在堆内的Slice allocate(int capacity);//利用这个方法我们可以在堆外创建一块内存,底层是使用的nio的ByteBuffer.allocateDirectSlice allocateDirect(int capacity);
创建了Slice之后,就可以往里面添加元素了
在Presto中最重要的两个用法就是FixedWidthBlock和VariableWidthBlock
创建者两种Block运用他的Builder类FixedWidthBlockBuilder和VariableWidthBlockBuilder类
① FixedWidthBlock
定长的Block,所以会固定一个FixedSize,然后底层就是一个byte数组。不管我们往里面写什么,只要一个entry的长度是FixedSize就行。同时这个不提供自动扩展内存的功能,当超出大小时,会抛出异常
② VariableWidthBlock
变长的Block,没有固定的大小,所以需要一个额外的数组记录指定entry的位置同时在每次增加之前会确保内存空间足够,如果不够会进行自动扩容
二、Block
三、Page
小结
- 本篇文章主要介绍Slice的实现原理(通过Unsafe的方式),同时介绍Slice的主要应用场景
 - 由于时间缘故,Block和Page留到下次补充
 
参考文献
