flink的MemorySegment

本文深入探讨了Flink中MemorySegment的内部实现细节,包括HeapMemorySegment和HybirdMemorySegment的具体工作原理,如何通过Unsafe获取byte数组地址,以及MemorySegment在获取int值和进行比较操作时的高效策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Flink中MemorySegment用来管理内存,其是一个抽象类,具体实现有HeapMemorySegment和HybirdMemorySegment。

protected static final long BYTE_ARRAY_BASE_OFFSET = UNSAFE.arrayBaseOffset(byte[].class);

BYTE_ARRAY_BASE_OFFSET是byte数组的相对偏移量,当存储为堆内内存的时候,在一直当前MemorySegment存在的情况下,通过Unsafe可以根据当前类的地址通过相对偏移量的到byte数组的地址,这个地址也是具体的内存存放的地方。

protected final byte[] heapMemory;

当选择的是堆内内存的时候,这个heapMemory就是存放存储内容的byte数组。

protected long address;

当内存为堆内内存的时候address为byte数组的相对偏移量,而当为堆外内存的时候,address则为一个内存中的绝对地址。

protected final long addressLimit;

这个参数则是内存边界。

protected final int size;

Size自然是这一MemorySegment的内存大小,堆内内存情况下就是byte数组的长度。

private final Object owner;

Owner则为这一MemorySegment内存当前的使用对象。

 

具体的操作以int的获取为例子。

public final int getInt(int index) {
   final long pos = address + index;
   if (index >= 0 && pos <= addressLimit - 4) {
      return UNSAFE.getInt(heapMemory, pos);
   }
   else if (address > addressLimit) {
      throw new IllegalStateException("segment has been freed");
   }
   else {
      // index is in fact invalid
      throw new IndexOutOfBoundsException();
   }
}

在获取制定位置的int的时候,由于int是四个字节,所以所要注意的是代表内存边界的addressLimit需要减4,之后通过unsafe直接获取对应位置上的数据。

public final int getIntLittleEndian(int index) {
   if (LITTLE_ENDIAN) {
      return getInt(index);
   } else {
      return Integer.reverseBytes(getInt(index));
   }
}

对于小端存储的,需要将得到的数据逆转byte位,得到相应的数据。

 

MemorySegment之间进行比较的compare()方法比较有意思。

public final int compare(MemorySegment seg2, int offset1, int offset2, int len) {
   while (len >= 8) {
      long l1 = this.getLongBigEndian(offset1);
      long l2 = seg2.getLongBigEndian(offset2);

      if (l1 != l2) {
         return (l1 < l2) ^ (l1 < 0) ^ (l2 < 0) ? -1 : 1;
      }

      offset1 += 8;
      offset2 += 8;
      len -= 8;
   }
   while (len > 0) {
      int b1 = this.get(offset1) & 0xff;
      int b2 = seg2.get(offset2) & 0xff;
      int cmp = b1 - b2;
      if (cmp != 0) {
         return cmp;
      }
      offset1++;
      offset2++;
      len--;
   }
   return 0;
}

参数len代表与需要进行比较的目标MemorySegment对象比较范围。

为了加快比较的速度,如果比较的长度大于8,首先会一次性取八个byte也就是八字节转化为long进行比较,加快比较的效率。

如果比较到剩余的位数小于8,那么开始逐字节进行比较,直到比较出相应的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值