我正在使用Delphi从关系数据库中的数据创建XML文档。它使用小型数据集进行测试,但是当我尝试将数据集的大小扩展到生产级别时,它最终会在节点创建期间因EOutOfMemory异常而爆炸。
我正在使用表单上的TXMLDocument(MSXML作为供应商),我的代码通常如下所示:
DS := GetDS(Conn, 'SELECT Fields. . . FROM Table WHERE InsuredID = ' +IntToStr(AInsuredID));
try
while not DS.Eof do
with ANode.AddChild('LE') do
begin
AddChild('LEProvider').Text := DS.FieldByName('LEProvider').AsString;
// Need to handle "other" here
AddChild('Date').Text := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
AddChild('Pct50').Text := DS.FieldByName('50Percent').AsString;
AddChild('Pct80').Text := DS.FieldByName('80Percent').AsString;
AddChild('Actuarial').Text := DS.FieldByName('CompleteActuarial').AsString;
AddChild('Multiplier').Text := DS.FieldByName('MortalityMultiplier').AsString;
DS.Next;
end;
finally
DS.Free;
end;
使用此部分,以及应用于不同数据库表的许多其他类似构造的部分,执行多次。在此示例中,ANode是传递给函数的IXMLNode,用作容器。
我不希望磁盘上生成的XML文件超过10兆字节。我假设我在创建和处理XMLNodes时泄漏了内存,但我不熟悉Interfaces以了解如何追踪我的问题。
答案 0 :(得分:3)
TXMDocument是一个DOM样式的界面,可以将整个文档保存在内存中。内存会以相当快的速度消耗掉。即使生成的文件不是那么大。你真的不需要TXMLDocument来写出一个简单的XML。为什么不直接写入xml格式的文件?
话虽如此:由于堆碎片或真正的内存泄漏,它也可能是一个错误。您可能想尝试这里提到的工具:Profiler and Memory Analysis Tools for Delphi
答案 1 :(得分:0)
每个AddChild
调用都将其结果存储到编译器隐式声明的临时IXmlNode
变量中。当前子程序返回时(无论是正常还是异常),它们应该自动清理。您可以通过声明自己的变量来使其生命周期更加明确。
var
le, child: IXmlNode;
begin
DS := GetDS(Conn, Format(Query, [AInsuredID]));
try
while not DS.Eof do begin
le := ANode.AddChild('LE');
child := le.AddChild('LEProvider');
child.Text := DS.FieldByName('LEProvider').AsString;
// Need to handle "other" here
child := le.AddChild('Date');
child.Text := DateToXMLDate(DS.FieldByName('LEDate').AsDateTime);
child := le.AddChild('Pct50');
child.Text := DS.FieldByName('50Percent').AsString;
child := le.AddChild('Pct80');
child.Text := DS.FieldByName('80Percent').AsString;
child := le.AddChild('Actuarial');
child.Text := DS.FieldByName('CompleteActuarial').AsString;
child := le.AddChild('Multiplier');
child.Text := DS.FieldByName('MortalityMultiplier').AsString;
DS.Next;
end;
finally
DS.Free;
end;
end;
在上面的代码中,没有隐式接口变量。编译器会为每个AddNode
调用声明一个新的隐式变量,但上面的代码表明只有两个是必需的,因为child
可以为每个新的子节点重用。
但是,仅使用该代码不应导致极大的内存使用量。您似乎更有可能保留对您不再需要的对象的引用,或者您正在为某些接口对象创建循环引用。 MSXML库不应该创建自己的任何循环引用,但是您没有显示可能在此处运行的所有代码。
答案 2 :(得分:0)
尝试使用SAX解析器而不是DOM。 DOM将整个XML文件的表示保存在内存中。
尝试here