Background

我在业余时间自学数据库,试图通过实现一个入门知识来学习.

您必须实现的第一件事是底层数据格式和存储机制.

在数据库中,有一种称为"Slotted Page"的 struct ,如下所示:

+-----------------------------------------------------------+
| +----------------------+  +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
| | HEADER               |  | | | | | | | | | | | | | | | | |
| |                      |  | | | | | | | | | | | | | | | | |
| +----------------------+  +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ |
|                                     SLOT ARRAY            |
|                                                           |
|                                                           |
|                                                           |
|                 +--------------------+ +----------------+ |
|                 |  TUPLE #4          | |  TUPLE #3      | |
|                 |                    | |                | |
|                 +--------------------+ +----------------+ |
|         +--------------------------+ +------------------+ |
|         |  TUPLE #2                | |  TUPLE #1        | |
|         |                          | |                  | |
|         +--------------------------+ +------------------+ |
+-----------------------------------------------------------+

页面数据通过二进制序列化存储到文件.槽是最简单的部分,其中的定义可能如下所示:

struct Slot {
  uint32_t offset;
  uint32_t length;
}

在C++中,读/写过程可能是std::memcpy

// Ignoring offset of header size in below
void write_to_buffer(char *buffer, Slot& slot, uint32_t slot_idx) {
    memcpy(buffer + sizeof(Slot) * slot_idx, &slot.offset, sizeof(uint32_t));
    memcpy(buffer + sizeof(Slot) * slot_idx + sizeof(uint32_t), &slot.length, sizeof(uint32_t));
}

void read_from_buffer(char *buffer, Slot& slot, uint32_t slot_idx) {
    memcpy(&slot.offset, buffer + sizeof(Slot) * slot_idx, sizeof(uint32_t));
    memcpy(&slot.length, buffer + sizeof(Slot) * slot_idx + sizeof(Slot), sizeof(uint32_t));
}

在Java中,据我所知,您可以做两件事中的任何一件:

  1. 字节缓冲区
record Slot(int offset, int length) {
    void write(字节缓冲区 buffer) {
        buffer.putInt(offset).putInt(length);
    }
    
    static Slot read(字节缓冲区 buffer) {
        return new Slot(buffer.getInt(), buffer.getInt());
    }
}
  1. 新的 foreign 记忆material
record Slot(int offset, int length) {
    public static MemoryLayout LAYOUT = MemoryLayout.structLayout(
            ValueLayout.JAVA_INT.withName("offset"),
            ValueLayout.JAVA_INT.withName("length"));

    public static TupleSlot from(MemorySegment memory) {
        return new TupleSlot(
                memory.get(ValueLayout.JAVA_INT, 0),
                memory.get(ValueLayout.JAVA_INT, Integer.BYTES));
    }

    public void to(MemorySegment memory) {
        memory.set(ValueLayout.JAVA_INT, 0, offset);
        memory.set(ValueLayout.JAVA_INT, Integer.BYTES, length);
    }
}

它们之间的性能差异会是什么?

如果字节缓冲区 API可以忽略不计,我更喜欢它.

推荐答案

保罗·桑多斯在panama-dev封邮件列表上回复道:

嗨,加文.

与ByteBuffer相比,使用内存分段将使您能够更好地控制描述(布局)和管理(释放和池化).此外,如果这是一个问题,您也不会受到ByteBuffer大小限制的限制.使用内存分段的性能应该与ByteBuffer一样好或更好.

在许多方面,内存分段是与本机内存交互的更好的API.ByteBuffer是在带有NIO的Java 1.4中引入的,并且考虑到了其他设计约束,这些约束在今天已经不那么重要了(例如内部可变索引).

保罗

Java相关问答推荐

我可以在regex中的字符类中放置断言吗?

Mat. n_Delete()和Mat. n_release的区别

工件部署期间出错[Tomcat 8.5.45]

使用标记时,场景大纲不在多个线程上运行

Kubernetes的Java客户端检索状态.处于终止状态的Pod的阶段';正在运行';

RESTful框架类字段是安全的还是不安全的

所有 case 一起输入时输出错误,而单独放置时输出正确

在Java中如何从Executors.newFixedThreadPool(MAX_THREAD_COUNT())迁移到虚拟线程

Spring Security不允许加载js

如何从日志(log)行中删除包名称?

二进制数据的未知编码/序列化

具有最大共同前景像素的图像平移优化算法

JavaFX:为什么我的ComboBox添加了一个不必要的单元格的一部分?

";home/runner/work/中没有文件...匹配到[**/pom.xml];Maven项目的构建过程中出现错误

如何使用外部函数从Java中获取C++ struct 的返回值&;内存API

简化每个元素本身都是 map 列表的列表

获取月份';s在java中非UTC时区的开始时间和结束时间

如何在更改分辨率时将鼠标坐标计算为世界坐标

窗口启动后不久,从java.awt.Graphics disapear创建的矩形

如何在 Java 函数式代码中使用泛型