只有一个可以节省内存的想法。
您可以让数据保留在原始文件中,然后从内存结构中指向它们。
例如,我们几乎可以立即浏览大型日志文件:我们对日志文件内容进行内存映射,然后快速解析它以在内存中创建有用信息的索引,然后动态读取内容。读取期间不创建字符串。只有指向每一行开头的指针,动态数组包含所需的索引。调用TStringList.LoadFromFile肯定会慢得多并且消耗内存。
代码在这里- 查看TSynLogFile课程。诀窍是只读取一次文件,并即时创建所有索引。
例如,下面是我们如何从 UTF-8 文件内容中检索一行文本:
function TMemoryMapText.GetString(aIndex: integer): string;
begin
if (self=nil) or (cardinal(aIndex)>=cardinal(fCount)) then
result := '' else
result := UTF8DecodeToString(fLines[aIndex],GetLineSize(fLines[aIndex],fMapEnd));
end;
我们使用完全相同的技巧来解析 JSON 内容。最快的 XML 访问库使用这种混合方法。
为了处理您的高级数据并快速查询它们,您可以尝试使用动态记录数组以及我们的优化TDynArray和TDynArrayHashed包装器(在同一单元中)。记录数组消耗的内存更少,搜索速度更快,因为数据不会被碎片化(如果使用有序索引或散列会更快),并且您将能够对内容进行高级访问(例如,您可以定义自定义函数以从内存映射文件中检索数据)。动态数组不适合快速删除项目(或者您必须使用查找表) - 但您写道您并没有删除太多数据,因此在您的情况下不会成为问题。
因此,您将不再有任何重复的结构,只有 RAM 中的逻辑和内存映射文件上的数据 - 我在这里添加了一个“s”,因为相同的逻辑可以完美地映射到多个源数据文件(您需要一些“合并”和“实时刷新”AFAIK)。