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;
,也应该这样做
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现