After adding some optimizations to HTML/XML parser I was curious to compare its performance to other implementations.

After adding some optimizations to HTML/XML parser I was curious to compare its performance to other implementations.
As a test sample  I used Golf.xml file (500Kb) from this page
http://www.enetpulse.com/documentation/
As a participants were choosen OXML  http://www.kluug.net/oxml.php (it seems to be a fastest native XML implementation for Delphi)
and standard MSXML (Xml.XMLDoc).

It is not serious test, because results are vary widely from file to file (on some files MS was 9 times slower than HCL) but gives some notion.

Delphi XE2, Win32, Windows 7, Intel Core i5.

1. Reading (string -> DOM, creating and destroying )
HCL: 1.622 ms
  THtXMLNode.Create(s);

OXML: 4.415 ms
   OD:=OXMLPDOM.TXMLDocument.Create;
   OD.LoadFromXML(s);

MSXML: 4.524 ms
  MD:=XMl.XMLDoc.TXMLDocument.Create(nil);
  MD.LoadFromXML(s);

2. Memory (after loading 100 documents)
HCL: 177 Mb
OXML: 206 Mb.
MSXML:  253 Mb.

3. Serialization (DOM -> string )
HCL: 2.65 ms
OXML: 11.07 ms
MSXML: 7.18 ms

4. Simple XPath query:  //results  10000 times (304 nodes selected)
HCL:  671 ms
 (THtXMLNode).XPath('//results');

OXML:  58650 ms
  (OXMLPDOM.TXMLDocument).Node^.SelectNodes('//results');

MSXML: 1295 ms
 (DOMDocument as IDomNodeSelect).selectNodes('//results');

4. XPath query with attribute:  //result[@value="69"] 1000 times
HCL:  390ms
OXML: 5803 ms
MSXML: 609 ms

OXML results are very strange. Considering tests on OXML page it should be significantly faster than MSXML, so maybe I've missed something.
http://www.enetpulse.com/documentation

Comments

  1. Krasimir Ivanov
    Same result:
    HCL: 1528
    OXML: 4306

       XMLDoc := CreateXMLDoc;
       XMLDoc.LoadFromXML(s);
       XMLDoc:=nil;

    ReplyDelete
  2. For those kind of tests is interesting sorurce. Can you post this somewhere?

    ReplyDelete
  3. Krasimir Ivanov Source code is very simple (form with 3 buttons and memo)

    unit Unit10;

    interface

    {$DEFINE HCL}

    uses
      Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
      System.Classes, Vcl.Graphics,
      Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls,
      {$IFDEF HCL} htmlpars, htxml, {$ENDIF}
      Xml.xmldom, Xml.XMLIntf, Xml.Win.msxmldom, Xml.XMLDoc, Xml.adomxmldom, msxml, oxmlpdom;

    const
      TestFile = 'h:\golf.xml';

    type
      TForm10 = class(TForm)
        Memo1: TMemo;
        ReadBtn: TButton;
        WriteBtn: TButton;
        XPathBtn: TButton;
        XPath2Btn: TButton;
        procedure ReadBtnClick(Sender: TObject);
        procedure WriteBtnClick(Sender: TObject);
        procedure XPathBtnClick(Sender: TObject);
        procedure XPath2BtnClick(Sender: TObject);
      public
        {$IFDEF HCL}
        HN: THtXMLNode;
        {$ENDIF}
        OD: oxmlpdom.TXMLDocument;
        MD: Xml.XMLDoc.TXMLDocument;
        XMLDoc: IXMLDocument;
        Sel: IDOMNodeSelect;
        function LoadFile: string;
      end;

    var
      Form10: TForm10;

    implementation

    {$R *.dfm}

    function TForm10.LoadFile: string;
    var
      L: TStringList;
    begin
      L := TStringList.Create;
      try
        L.LoadFromFile(TestFile);
        Result := L.Text;
      finally
        L.Free
      end;
    end;

    procedure TForm10.ReadBtnClick(Sender: TObject);
    var
      s: string;
      i, T: integer;
    begin
      s := LoadFile;
      Memo1.Lines.Add('Read');
      {$IFDEF HCL}
      T := GetTickCount;
      for i := 1 to 100 do begin
        HN := THtXMLNode.Create(s);
        HN.Free;
      end;
      Memo1.Lines.Add('HCL: ' + inttostr(GetTickCount - T));
      {$ENDIF}

      T := GetTickCount;
      for i := 1 to 100 do begin
        XMLDoc := CreateXMLDoc;
        XMLDoc.LoadFromXML(s);
        XMLDoc := nil;
      end;
      Memo1.Lines.Add('OXML: ' + inttostr(GetTickCount - T));

      T := GetTickCount;
      for i := 1 to 100 do begin
        MD := Xml.XMLDoc.TXMLDocument.Create(nil);
        MD.LoadFromXML(s);
        MD.Active := true;
        MD.Free;
      end;
      Memo1.Lines.Add('MSXML: ' + inttostr(GetTickCount - T));

    end;

    procedure TForm10.WriteBtnClick(Sender: TObject);
    var
      s, s1: string;
      i, T: integer;
    begin
      s := LoadFile;
      Memo1.Lines.Add('Write');

      {$IFDEF HCL}
      HN := THtXMLNode.Create(s);
      T := GetTickCount;
      for i := 1 to 100 do begin
        s1 := HN.Code;
      end;
      Memo1.Lines.Add('HCL: ' + inttostr(GetTickCount - T));
      HN.Free;
      {$ENDIF}

      OD := oxmlpdom.TXMLDocument.Create;
      OD.LoadFromXML(s);
      T := GetTickCount;
      for i := 1 to 100 do begin
        s1 := OD.Xml;
      end;
      Memo1.Lines.Add('OXML: ' + inttostr(GetTickCount - T));
      OD.Free;

      MD := Xml.XMLDoc.TXMLDocument.Create(nil);
      MD.LoadFromXML(s);
      T := GetTickCount;
      for i := 1 to 100 do begin
        MD.SaveToXML(s1);
      end;
      Memo1.Lines.Add('MSXML: ' + inttostr(GetTickCount - T));
      MD.Free;
    end;

    procedure TForm10.XPathBtnClick(Sender: TObject);
    var
      s, s1: string;
      i, T: integer;
    begin
      s := LoadFile;
      Memo1.Lines.Add('XPath: //results');
      {$IFDEF HCL}
      HN := THtXMLNode.Create(s);
      T := GetTickCount;
      for i := 1 to 10000 do begin
        HN.XPath('//results');
      end;
      Memo1.Lines.Add('HCL: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' + inttostr(HN.XPath('//results').GetCount));
      HN.Free;
      {$ENDIF}

      OD := oxmlpdom.TXMLDocument.Create;
      OD.LoadFromXML(s);
      T := GetTickCount;

    ReplyDelete

  4.   for i := 1 to 1000 do begin
        OD.Node^.SelectNodes('//results');
      end;
      Memo1.Lines.Add('OXML: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' +
        inttostr(OD.Node^.SelectNodes('//results').Count));
      OD.Free;

      MD := Xml.XMLDoc.TXMLDocument.Create(nil);
      MD.LoadFromXML(s);
      T := GetTickCount;
      for i := 1 to 10000 do begin
        Sel := MD.DOMDocument as IDOMNodeSelect;
        Sel.SelectNodes('//results');
      end;
      Memo1.Lines.Add('MSXML: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' + inttostr(Sel.SelectNodes('//results').length));
      MD.Free;
    end;

    procedure TForm10.XPath2BtnClick(Sender: TObject);
    var
      s, s1: string;
      i, T: integer;
    begin
      s := LoadFile;
      Memo1.Lines.Add('XPath: //result[@value="69"]');
      {$IFDEF HCL}
      HN := THtXMLNode.Create(s);
      T := GetTickCount;
      for i := 1 to 1000 do begin
        HN.XPath('//result[@value="69"]');
      end;
      Memo1.Lines.Add('HCL: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' + inttostr(HN.XPath('//result[@value="69"]')
        .GetCount));
      HN.Free;
      {$ENDIF}
      OD := oxmlpdom.TXMLDocument.Create;
      OD.LoadFromXML(s);
      T := GetTickCount;
      for i := 1 to 1000 do begin
        OD.Node^.SelectNodes('//result[@value="69"]');
      end;
      Memo1.Lines.Add('OXML: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' +
        inttostr(OD.Node^.SelectNodes('//result[@value="69"]').Count));
      OD.Free;

      MD := Xml.XMLDoc.TXMLDocument.Create(nil);
      MD.LoadFromXML(s);
      T := GetTickCount;
      for i := 1 to 1000 do begin
        Sel := MD.DOMDocument as IDOMNodeSelect;
        Sel.SelectNodes('//result[@value="69"]');
      end;
      Memo1.Lines.Add('MSXML: time ' + inttostr(GetTickCount - T));
      Memo1.Lines.Add('Count: ' +
        inttostr(Sel.SelectNodes('//result[@value="69"]').length));
      MD.Free;
    end;

    end.

    ReplyDelete

Post a Comment