Moin,
in meinem himXML hab ich unter anderem diesen TestCode (in CheckLibs.dpr)
Delphi-Quellcode:
Var msXML: XMLDoc.TXMLDocument;
msNode: XMLIntf.IXMLNode;
msXML := XMLDoc.TXMLDocument.Create(
nil);
Try
msXML.DOMVendor := XMLDOM_Vendors[i4].Vendor;
msXML.Active := True;
msXML.Version := '
1.0';
msXML.StandAlone := '
yes';
msXML.Encoding := '
UTF-8';
msXML.Options := [doNodeAutoIndent];
msXML.AddChild('
xml');
For i := 0
to 9999
do msXML.DocumentElement.AddChild(Node_IntToStr[i]);
nu hat jemand (
samso) rausgefunden, daß dort die Interfaceverwaltung beim SimpleXML schlecht ist ... wodurch einige Objekte (vorallem SimpleXML und auch
MSXML) nicht korrekt freigegeben wurden.
Angeblich (laut Messung) ging das superflott innerhalb von etwa 0 ms , aber nun stellte sich raus, daß die Objekte garnicht freigegeben wurden.
Zitat von
samso:
Hallo,
ich habe CheckLibs ein wenig überarbeitet. Dabei ging es mir überwiegend um das Testen von SimpleXML. Bei SimpleXML ist es ausgesprochen suboptimal den Knoten sozusagen "offline" zu erzeugen und ihn dann im nächsten Schritt in den
XML-Baum einzuklinken. Besser ist die Verwendung von "AppendElement".
Dann bereitet leider das Freigeben der Interfaces ausgesprochenen Ärger. Delphi mag temporäre Interfaces freiwillig erst beim Verlassen der Procedure freigeben. D.h. temporäre Interfaces müssen manuell freigeben werden.
Also so:
Delphi-Quellcode:
siRoot := siXML.DocumentElement;
For i := 0 to 9999 do Begin
siNode := siRoot.AppendElement(Node_IntToStr[i]);
siNode := nil;
End;
siRoot := nil;
Statt so:
Delphi-Quellcode:
For i := 0 to 9999 do Begin
siXML.DocumentElement.AppendElement(Node_IntToStr[i]);
End;
Trotzdem mag Delphi global deklarierte Interfaces irgendwie gar nicht freigeben. Deshalb habe ich alle Tests in entsprechende Proceduren verpackt.
OK, das AppendElement statt meinem CreateXmlElement+AppendChild machte jetzt im Test erstmal keinen großen Unterschied, da AppendElement ebenfalls intern sowas wie CreateXmlElement+InsertChild ausführt.
bei mir sah/sieht es im Testprojekt so aus
Delphi-Quellcode:
For i := 0 to 9999 do Begin
siNode := SimpleXML.CreateXmlElement(Node_IntToStr[i]);
siXML.DocumentElement.AppendChild(siNode);
End;
(aber mit dem Hauptproblem der Interfaceverwaltung hat es nichts zu tun)
Zitat von
samso:
Jau, schon klar!
Mein Problem war Test 6. Dort wird der Speicher zwischen erzeugen der 3Mio Knoten und dem Lesen der Datei leider nicht freigegeben. Dies führt dann dazu das der Test wegen Speichermangel abgebrochen wird. Deshalb habe ich beide Tests getrennt. Das Verhalten kann man auch bei den anderen Tests erkennen, weil hier das Freigeben üblicherweise in 0ms erfolgt - ergo - es wird nichts freigeben.
D.h. bei globaler Variable:
Zitat:
***** Test 4 ************************************************** ****************
fill TXMLFile with 100.000 nodes, save into and load this from a file
create:0 fill:191 save:109 free:36
create:0 load:409 free:41
fill SimpleXML with 100.000 nodes, save into and load this from a file
create:0 fill:99 save:123 free:0
create:0 load:312 free:0
Bei lokaler Variable
Zitat:
***** Test 4 ************************************************** ****************
fill TXMLFile with 100.000 nodes, save into and load this from a file
create:0 fill:193 save:107 free:37
create:0 load:414 free:36
fill SimpleXML with 100.000 nodes, save into and load this from a file
create:0 fill:109 save:123 free:45
create:0 load:311 free:41
Delphi-Quellcode:
Var msXML: XMLDoc.TXMLDocument;
msNode: XMLIntf.IXMLNode;
msXML := XMLDoc.TXMLDocument.Create(
nil);
Try
msXML.DOMVendor := XMLDOM_Vendors[i4].Vendor;
msXML.Active := True;
msXML.Version := '
1.0';
msXML.StandAlone := '
yes';
msXML.Encoding := '
UTF-8';
msXML.Options := [doNodeAutoIndent];
msNode :=
msXML.AddChild('
xml');
msNode :=
nil;
For i := 0
to 9999
do msNode :=
msXML.DocumentElement.AddChild(Node_IntToStr[i]);
msNode :=
nil;
Nachdem ich nun selber nochmal alles umgestellt und auch mal die Zeit für das Ende ( end. ) der einzelnen Prozeduren mitgemessen hatte, stellte sich der Selbe Effekt auch beim
MSXML raus, aber leider komme ich hier nicht weiter
Im Obrigen Code hab ich nurn also mal alle "temporäten" Variablen entfernt, durch eigene ersetzt und diese manuell freigegeben:
Delphi-Quellcode:
Var msXML: XMLDoc.TXMLDocument;
msNode: XMLIntf.IXMLNode;
msXML := XMLDoc.TXMLDocument.Create(
nil);
Try
msXML.DOMVendor := XMLDOM_Vendors[i4].Vendor;
msXML.Active := True;
msXML.Version := '
1.0';
msXML.StandAlone := '
yes';
msXML.Encoding := '
UTF-8';
msXML.Options := [doNodeAutoIndent];
msNode :=
msXML.AddChild('
xml');
msNode :=
nil;
For i := 0
to 9999
do
msNode :=
msXML.DocumentElement.AddChild(Node_IntToStr[i]);
msNode :=
nil;
so weit so gut ... nur gibt es jetzt ein "klitzekleines" Problem, denn es läuft nichts mehr
msXML läßt sich so nicht als IXMLDokument (Interface) nutzen, da ich noch keine andere Möglichkeit fand dort den DOMVendor anders zu nutzen.
Probem ist jetzt, sobald der Rootnode, welcher von
msXML.AddChild('
xml') zurückgegeben wird, freigegeben wurde, wird auch das ganze Dokument freigegeben und es kommmt beim Erstellen des ersten Nodes innerhalb der Schleife zu einer
Exception.
Zitat:
Im Projekt CheckLibs.exe ist eine
Exception der Klasse EXMLDocError mit der Meldung 'Kein aktives Dokument' aufgetreten.
OK, nach etwas Rumprobieren hab ich es nun so
Delphi-Quellcode:
Var msXMLc: XMLDoc.TXMLDocument;
msXML: XMLIntf.IXMLDocument;
msNode: XMLIntf.IXMLNode;
msXMLc := XMLDoc.TXMLDocument.Create(
nil);
Try
Try
msXMLc.DOMVendor := XMLDOM_Vendors[i4].Vendor;
msXMLc.Active := True;
msXMLc.Version := '
1.0';
msXMLc.StandAlone := '
yes';
msXMLc.Encoding := '
UTF-8';
msXMLc.Options := [doNodeAutoIndent];
Finally
msXML := msXMLc;
End;
msNode :=
msXML.AddChild('
xml');
msNode :=
nil;
For i := 0
to 9999
do msNode :=
msXML.DocumentElement.AddChild(Node_IntToStr[i]);
msNode :=
nil;
msXML.SaveToFile(ChangeFileExt(ParamStr(0), '
.Test1_MSXML.xml'));
msXML :=
nil;
// << free
Except
On E:
Exception do Begin
WriteLn(E.Classname, '
: ', E.
Message);
msXML :=
nil;
End;
End;
aber auch hier wird das Dokument noch nicht dort Freigegeben wo es sollte (<< free) .
so geht es ebenfalls nicht
Delphi-Quellcode:
msNode :=
msXML.AddChild('
xml');
msNode :=
nil;
For i := 0
to 9999
do Begin
msNode :=
msXML.DocumentElement.AddChild(Node_IntToStr[i]);
msNode :=
nil;
End;
msXML.SaveToFile(ChangeFileExt(ParamStr(0), '
.Test1_MSXML.xml'));
Code:
***** Test 1 ******************************************************************
fill TXMLFile with 10.000 nodes and save this into a file
create:8 fill:7 save:4 free:3
fill MS-
XML-
DOM with 10.000 nodes and save this into a file
create:21 fill:13006 save:110 [color=#ff0000]free:0[/color]
[color=#ff0000]local free:456[/color]
Code:
***** Test 1 ******************************************************************
fill TXMLFile with 10.000 nodes and save this into a file
create:0 fill:7 save:6 free:3
[color=#ff0000]local free:0[/color]
ohne
MSXML wird die Prozedur schnell beendet, also wurde irgendwas vom
MSXML nicht freigegeben
und ich finde einfach nichts mehr ... keine weitere Prozedur hat noch einen Rückgabewert mit 'nem Interface, welche von Delphi als "temporäre" Variable gepsichert und somit erst bei Prozedurende, wo dann auch alle temporären Variablen freigeben werden, welche wie lokale Variablen behandelt werden ... zumindestens finde ich Keine.