全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1937
推到 Plurk!
推到 Facebook!

產生xmldocument 資料量大 記憶體不足問題

答題得分者是:aftcast
isthatu1999
一般會員


發表:3
回覆:3
積分:1
註冊:2010-06-29

發送簡訊給我
#1 引用回覆 回覆 發表時間:2012-04-10 01:32:24 IP:124.11.xxx.xxx 訂閱
最近user端來份公文 原本轉給他們的資料text 要改傳xml格式

小弟 用了xmldocment元件 來產製 結果程式寫好 實際去run資料 不得了 幾十萬筆資料 居然搞到記憶體不足
感覺節點一直新增時就不斷的耗用記憶體 最後出現out of memory訊息
不知是我寫法有問還是還有其他方法可以解決

程式範例如下 直接迴圈跑2000次 * 20明細 值都隨便塞 (每個月實際的應該高過這個)
結果記憶體不斷的飆高 最後爆了

想說有一個好用的xmldocment 元件 特地使用使用delphi7來用

實在很不想走那種自己塞tag麻煩要命的寫法

不知有各位有更好得解決方法嗎?

範例: 可以順便觀察程式記憶體一直爆衝
procedure TFinsXML.Button2Click(Sender: TObject);
var
i,j,k,m,n:integer;
inpatient:IXMLNode;
tdata:IXMLNode;
ddata:IXMLNode;
dhead:IXMLNode;
dbody:IXMLNode;
pdata:IXMLNode;

t:array[1..32] of IXMLNode; {總表定義節點}
d:array[1..103] of IXMLNode; {主檔}
p:array[1..22] of IXMLNode; {明細}
begin

// 頁面放一顆xmldocment元件了 這段copy下來就應改可以run
// 再放一個memo1 讀產製的xml

XMLDocument1.XML.Clear;
XMLDocument1.Active := True;
XMLDocument1.Version := '1.0';
XMLDocument1.Encoding := 'Big5';

inpatient :=XMLDocument1.AddChild('inpatient');

tdata := _inpatient.AddChild('tdata');
for j:=1 to 32 do // summary
begin
t[j] := tdata.AddChild('t' inttostr(j));
t[j].Text := widestring(inttostr(j));
end;

for i:=1 to 2000 do //給跑2000主檔筆資料
begin
// main_data
ddata := _inpatient.AddChild('ddata');
dhead := ddata.AddChild('dhead');
d[1] := dhead.AddChild('d1');
d[1].Text := widestring('d1');
d[2] := dhead.AddChild('d2');
d[2].Text := widestring('d2');

dbody:= ddata.AddChild('dbody');
for k:=2 to 103 do
begin
d[k] := dbody.AddChild('d' inttostr(k));
d[k].Text := widestring('d' inttostr(k));
end;

for n:=1 to 20 do // 每筆主檔給run 20筆 明細
begin
pdata := dbody.AddChild('dpdata');
for m:=1 to 22 do // sub_data
begin
p[m] := pdata.AddChild('p' inttostr(k));
p[m].Text := widestring('p' inttostr(k));
end;
end;
end;

XMLDocument1.SaveToFile('c:\a.xml');
Memo1.Clear;
Memo1.Lines.LoadFromFile('c:\a.xml');

end;

aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2012-04-10 09:52:31 IP:114.32.xxx.xxx 訂閱
好奇的請問一下a.xml檔案最後是多大? 或者你客戶轉成xml後,那個檔有多大?
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
isthatu1999
一般會員


發表:3
回覆:3
積分:1
註冊:2010-06-29

發送簡訊給我
#3 引用回覆 回覆 發表時間:2012-04-10 23:01:22 IP:124.11.xxx.xxx 訂閱
這範例跑2000次 出來是29M  XML行數1千2百萬行 (自己都 嚇一跳) 
不過USER每個月大概6000案件 應該是這3倍

後來我已經解決了.........

就是這種大量資料要轉成XML時 不能直接以1個xmldocument來一次跑底
光建立節點就會記憶體就爆掉

所以我的作法是拆解 xml 分批建立XMLDocument 再釋放 ..再建立....

例如跑500筆時 就用stringlist 承接起來
aList.Text:= aList.Text XMLDocument.XML.Text;

然後 釋放掉原本的 XMLDocument
XMLDocument.XML.Clear;
XMLDocument.Destroy;
XMLDocument := nil;

迴圈 中再 create
XMLDocument := TXMLDocument.create(self);
XMLDocument.XML.Clear;
XMLDocument.Options:= XMLDocument.Options [doNodeAutoIndent];
XMLDocument.Active := True;
XMLDocument.Version := '1.0';
XMLDocument.Encoding := 'Big5';

xmldocumet 繼續接資料

stringList 再後面繼續接資料

只是注意到接資料時把上層tag去掉
XMLDocument.XML.Delete(XMLDocument.XML.Count-1);
XMLDocument.XML.Delete(1);
XMLDocument.XML.Delete(0);

最後迴圈完成後 stringList再把最外層的ending tag 補上
aList.Lines.add('');

aList.存檔即可!!

這樣觀察記憶體就不會爆衝了 程式之前衝到 記憶體1.6g 程式改了後就在100m-200m間上上下下

以上。









===================引 用 aftcast 文 章===================
好奇的請問一下a.xml檔案最後是多大? 或者你客戶轉成xml後,那個檔有多大?

aftcast
站務副站長


發表:81
回覆:1482
積分:1762
註冊:2002-11-21

發送簡訊給我
#4 引用回覆 回覆 發表時間:2012-04-11 10:42:50 IP:114.32.xxx.xxx 訂閱
 嗯,我想若你的檔案大到這種程度,若是我,可能考慮使用File Mapping的技術(查msdn)。這樣就不用一直放在記憶體裡(包含list)。
一直的往檔案裡寫一段,然後release 物件 (就如你現在做的,差別在不放在list裡)。

我想那樣的寫法就算文件再大,都不會是問題,效能應該也是極好才是!


不過,你目前的做法也很不錯了 :)

參考參考
------



蕭沖
--All ideas are worthless unless implemented--

C++ Builder Delphi Taiwan G+ 社群
http://bit.ly/cbtaiwan
isthatu1999
一般會員


發表:3
回覆:3
積分:1
註冊:2010-06-29

發送簡訊給我
#5 引用回覆 回覆 發表時間:2012-04-12 00:33:27 IP:124.11.xxx.xxx 訂閱
是啊~

結果我用stringlist去接資料 真正去跑資料時 最後還是爆掉

這次爆在stringlist 容量

所以我又把 stringlist裡面資料

分批存入檔案中 再釋放

ex:
AssignFile(myFile, 'Test.xml');
Apend(myFile);
WriteLn(myFile,ts.text);
CloseFile(myFile);

最後才解決問題 而且效能還不錯。




sryang
尊榮會員


發表:38
回覆:741
積分:875
註冊:2002-06-27

發送簡訊給我
#6 引用回覆 回覆 發表時間:2012-04-13 09:48:29 IP:114.35.xxx.xxx 訂閱
難得的大量資料處理經驗,感謝分享!
<embed width="0" hidden="true" height="0" type="application/lingoes-npruntime-capture-word-plugin" id="lingoes_plugin_object"></embed>
------
歡迎參訪 "腦殘賤貓的備忘錄" http://maolaoda.blogspot.com/
系統時間:2017-10-23 19:36:28
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!