d固定大小输出缓冲

原文

enum PAGE_SIZE = 4096;
enum HEADER_SIZE = (uint.sizeof) * 6;
enum TUPLE_SLOT_SIZE = (uint.sizeof) * 2;

struct TupleSlot
{
    uint offset;
    uint size;
}

struct Tuple
{
    uint size;
    ubyte[] data;
}

struct PageHeader
{
    uint logStorageNumber = 0;
    uint pageId = 0;
    uint prevPageId = 0;
    uint nextPageId = 0;
    uint freeSpacePointer = PAGE_SIZE;
    uint tupleCount = 0;
    TupleSlot[] slots;
}

struct SlottedPage
{
    PageHeader header;
    Tuple[] tuples;
    ubyte[PAGE_SIZE] buffer;

    void insertTuple(Tuple tuple)
    {
        tuples ~= tuple;
        header.slots ~= TupleSlot(header.freeSpacePointer, cast(uint) tuple.sizeof);
        header.tupleCount++;
        header.freeSpacePointer -= tuple.sizeof;
    }

    void serialize(OutBuffer buf)
    {
        with (header)
        {
            buf.write(pageId);
            buf.write(logStorageNumber);
            buf.write(prevPageId);
            buf.write(nextPageId);
            buf.write(freeSpacePointer);
            buf.write(tupleCount);
        }

        foreach (TupleSlot slot; header.slots)
        {
            buf.write(slot.offset);
            buf.write(slot.size);
        }

        buf.fill0(header.freeSpacePointer);

        foreach (Tuple tuple; tuples)
        {
            buf.write(tuple.size);
            buf.write(tuple.data);
        }
    }
}

void main()
{
    OutBuffer buffer = new OutBuffer();
    buffer.reserve(4096);

    auto page = new SlottedPage(PageHeader());
    foreach (i; 0 .. 10)
    {
        OutBuffer buf = new OutBuffer();
        buf.write(i);
        page.insertTuple(Tuple(cast(uint) buf.data.length, buf.data));
    }

    page.serialize(buffer);
    // Writes 8206
    writeln("Buffer size is: ", buffer.data.length);
}

OutBuffer上调用toBytes()丢弃传递过来保存和使用的分配的额外字节.但我猜这仍然会首先分配内存(编译器会优化它吗?)
复制OutBuffer类到新的FixedSizeOutBuffer(T)类中,并改变它的行为
ubyte[PAGE_SIZE]并手写如下:

ubyte[] toBytes(uint value)
{
    static ubyte[4] bytes = new ubyte[4];
    bytes[0] = cast(ubyte)(value >> 24);
    bytes[1] = cast(ubyte)(value >> 16);
    bytes[2] = cast(ubyte)(value >> 8);
    bytes[3] = cast(ubyte)(value);
    return bytes;
}

void serialize(out ubyte[PAGE_SIZE] outbuf)
{
    ubyte[] buf;
    reserve(buf, PAGE_SIZE);

    buf ~= toBytes(header.pageId);
    buf ~= toBytes(header.logStorageNumber);
    buf ~= toBytes(header.prevPageId);
    buf ~= toBytes(header.nextPageId);
    buf ~= toBytes(header.freeSpacePointer);
    buf ~= toBytes(header.tupleCount);

    foreach (idx, ref slot; header.slots)
    {
        buf ~= toBytes(slot.offset);
        buf ~= toBytes(slot.size);
    }

    // Skip over free space
    ubyte[] padding = new ubyte[header.freeSpacePointer];
    padding[] = 0;
    buf ~= padding;

    foreach (idx, ref tuple; tuples)
    {
        buf ~= toBytes(tuple.size);
        buf ~= tuple.data;
    }

    move(buf.ptr, outbuf.ptr);
}

它会在需要时分配.它会增长,但不会再缩小

static ubyte[4] bytes = new ubyte[4];

不必,你正在分配线本内存.只需使用静态数组.

foreach (idx, ref slot; header.slots)

此处无需引用slot.会阻止编译器优化.

ubyte[] padding = new ubyte[header.freeSpacePointer];
padding[] = 0;
buf ~= padding;

不必,ubyte初值为0,自动分配.只需设置切片长度:

buf.length += header.freeSpacePointer;

这,

foreach (idx, ref tuple; tuples)

再次,无需引用

move(buf.ptr, outbuf.ptr);

不确定那是什么.简单

outbuf[0 .. buf.length] = buf;

,也应该这样做

posted @   zjh6  阅读(11)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示