|
Online
Registriert seit: 11. Okt 2003 Ort: Elbflorenz 44.332 Beiträge Delphi 12 Athens |
#1
Moin,
in meinem himXML hab ich unter anderem diesen TestCode (in CheckLibs.dpr)
Delphi-Quellcode:
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.
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]); Angeblich (laut Messung) ging das superflott innerhalb von etwa 0 ms , aber nun stellte sich raus, daß die Objekte garnicht freigegeben wurden. ![]() 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:
Statt so:
siRoot := siXML.DocumentElement;
For i := 0 to 9999 do Begin siNode := siRoot.AppendElement(Node_IntToStr[i]); siNode := nil; End; siRoot := nil;
Delphi-Quellcode:
Trotzdem mag Delphi global deklarierte Interfaces irgendwie gar nicht freigeben. Deshalb habe ich alle Tests in entsprechende Proceduren verpackt.
For i := 0 to 9999 do Begin
siXML.DocumentElement.AppendElement(Node_IntToStr[i]); End; bei mir sah/sieht es im Testprojekt so aus
Delphi-Quellcode:
(aber mit dem Hauptproblem der Interfaceverwaltung hat es nichts zu tun)
For i := 0 to 9999 do Begin
siNode := SimpleXML.CreateXmlElement(Node_IntToStr[i]); siXML.DocumentElement.AppendChild(siNode); End; ![]() ![]() 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: ![]() ***** 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 ![]() ***** 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:
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
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; ![]() Im Obrigen Code hab ich nurn also mal alle "temporäten" Variablen entfernt, durch eigene ersetzt und diese manuell freigegeben:
Delphi-Quellcode:
so weit so gut ... nur gibt es jetzt ein "klitzekleines" Problem, denn es läuft nichts mehr
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; ![]() 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. ![]() ![]() ![]() Im Projekt CheckLibs.exe ist eine Exception der Klasse EXMLDocError mit der Meldung 'Kein aktives Dokument' aufgetreten.
Delphi-Quellcode:
aber auch hier wird das Dokument noch nicht dort Freigegeben wo es sollte (<< free) .
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; ![]() 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:
ohne MSXML wird die Prozedur schnell beendet, also wurde irgendwas vom MSXML nicht freigegeben
***** 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] 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.
Ein Therapeut entspricht 1024 Gigapeut.
|
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |