Home / Downloads / XML Designer / Compare parsers
The follow table compares different popular XML parsers supporting XML 1.0 specification.
Company/Parser | xml file size | parsing time | parsing speed | allocated memory | multiplication memory | comments |
Recreate object |
Terimber/Xml Designer 1.7 | 10Kb | 1.2 msec | 8.3Mb/sec | 1Mb | - | Internal buffer allocated |
Microsoft/MSXML4.0 | 10Kb | 2.4 msec | 4.2 Mb/sec | 124 b | - | Internal buffer already was allocated |
Oracle/XML Parser 9.2.0.4.0 C++ | 10Kb | 1.9 msec | 5.3 Mb/sec | 42 Kb | 4.2 | |
Apache/Xerces-C++ Version 2.3.0 | 10Kb | 2.6 msec | 3.8 Mb/sec | 2.8 Mb | - | Internal buffer allocated |
Reuse object |
Terimber/Xml Designer 1.7 | 10Kb | 0.95 msec | 10.5 Mb/sec | 124b | Reusing internal buffer |
Microsoft/MSXML4.0 | 10Kb | 2.5 msec | 4 Mb/sec | 66 b | Reusing internal buffer |
Oracle/XML Parser 9.2.0.4.0 C++ | 10Kb | 1 msec | 10 Mb/sec | 7 Kb | Reusing internal buffer |
Apache/Xerces-C++ Version 2.3.0 | 10Kb | - | - | - | - | Doesn't support reusing object |
Recreate object |
Terimber/Xml Designer 1.7 | 100Kb | 9 msec | 11Mb/sec | 1.2 Mb | - | Internal buffer allocated |
Microsoft/MSXML4.0 | 100Kb | 15 msec | 6.7 Mb/sec | 325 Kb | 3.25 | Internal buffer allocated |
Oracle/XML Parser 9.2.0.4.0 C++ | 100Kb | 11 msec | 9.1 Mb/sec | 242 Kb | 2.4 | |
Apache/Xerces-C++ Version 2.3.0 | 100Kb | 25 msec | 4 Mb/sec | 3 Mb | - | Internal buffer allocated |
Reuse object |
Terimber/Xml Designer 1.7 | 100Kb | 9 msec | 10.5 Mb/sec | 1.4 Kb | Reusing internal buffer |
Microsoft/MSXML4.0 | 100Kb | 17 msec | 4 Mb/sec | 708 b | Reusing internal buffer |
Oracle/XML Parser 9.2.0.4.0 C++ | 100Kb | 9 msec | 10 Mb/sec | 94 Kb | Reusing internal buffer |
Apache/Xerces-C++ Version 2.3.0 | 100Kb | - | - | - | - | Doesn't support reusing object |
Recreate object |
Terimber/Xml Designer 1.7 | 1Mb | 88 msec | 11.4 Mb/sec | 3.8 Mb | 3.8 | |
Microsoft/MSXML4.0 | 1Mb | 146 msec | 6.7 Mb/sec | 6.8 Mb | 6.7 | |
Oracle/XML Parser 9.2.0.4.0 C++ | 1Mb | 106 msec | 9.4 Mb/sec | 14.9 Mb | 14.9 | |
Apache/Xerces-C++ Version 2.3.0 | 1Mb | 260 msec | 3.8 Mb/sec | 11 Mb | 11 | |
Reuse object |
Terimber/Xml Designer 1.7 | 1Mb | 89 msec | 11.2 Mb/sec | 66 Kb | - | Reusing internal buffer |
Microsoft/MSXML4.0 | 1Mb | 175 msec | 5.7 Mb/sec | 708 b | - | Reusing internal buffer |
Oracle/XML Parser 9.2.0.4.0 C++ | 1Mb | 91 msec | 11 Mb/sec | 1.2 Mb | - | Reusing internal buffer |
Apache/Xerces-C++ Version 2.3.0 | 1Mb | - | - | - | - | Doesn't support reusing object |
Recreate object |
Terimber/Xml Designer 1.7 | 10Mb | 846 msec | 11.8 Mb/sec | 32.7 Mb | 3.3 | |
Microsoft/MSXML4.0 | 10Mb | 1.66 sec | 6.2 Mb/sec | 63.4 Mb | 6.3 | |
Oracle/XML Parser 9.2.0.4.0 C++ | 10Mb | 1.0 sec | 10 Mb/sec | 29.5 Mb | 2.9 | |
Apache/Xerces-C++ Version 2.3.0 | 10Mb | 2.5 sec | 4 Mb/sec | 89 Mb | 8.9 | |
Reuse object |
Terimber/Xml Designer 1.7 | 10Mb | 857 msec | 11.7 Mb/sec | 3.3 Mb | - | Reusing internal buffer |
Microsoft/MSXML4.0 | 10Mb | 1.93 sec | 5.2 Mb/sec | 64 Mb | 6.4 | |
Oracle/XML Parser 9.2.0.4.0 C++ | 10Mb | 891 msec | 11.2 Mb/sec | 29.5 Mb | 2.95 | |
Apache/Xerces-C++ Version 2.3.0 | 10Mb | - | - | - | - | Doesn't support reusing object |
Recreate object |
Terimber/Xml Designer 1.7 | 100Mb | 8.45 sec | 11.8 Mb/sec | 317 Mb | 3.2 | |
Microsoft/MSXML4.0 | 100Mb | 42.88 sec | 2.3 Mb/sec | 645 Mb | 6.5 | |
Oracle/XML Parser 9.2.0.4.0 C++ | 100Mb | - | - | >1.2 Gb | - | No enough memory |
Apache/Xerces-C++ Version 2.3.0 | 100Mb | - | - | >900 Mb | - | No enough memory |
Reuse object |
Terimber/Xml Designer 1.7 | 100Mb | 8.63 sec | 11.7 Mb/sec | 317 Mb | 3.2 | |
Microsoft/MSXML4.0 | 100Mb | 43.06 sec | 2.3 Mb/sec | 646 Mb | 6.5 | |
Oracle/XML Parser 9.2.0.4.0 C++ | 100Mb | - | - | >1.2 Gb | - | No enough memory |
Apache/Xerces-C++ Version 2.3.0 | 100Mb | - | - | - | - | Doesn't support reusing object |
For recreation of object the follow test code was used:
PROCESS_MEMORY_COUNTERS p;
p.cb= sizeof(PROCESS_MEMORY_COUNTERS);
HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId());
//Cstring path = "C:\xmltest\build1.xml";
//Cstring path = "C:\xmltest\build10.xml";
//Cstring path = "C:\xmltest\build100.xml";
//Cstring path = "C:\xmltest\build1000.xml";
//Cstring path = "C:\xmltest\build10000.xml";
//__int64 rounds = 1; - 100Mb file
//__int64 rounds = 10; - 10Mb file
//__int64 rounds = 100; - 1Mb file
//__int64 rounds = 1000; - 100Kb file
//__int64 rounds = 10000; - 10 Kb file
__int64 memory_ = 0;
__int64 time_ = 0;
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticks);
VARIANT_BOOL resVar;
VARIANT vpath;
vpath.bstrVal = path.AllocSysString();
vpath.vt = VT_BSTR;
/*
//////////////// terimber
const CLSID clsidt = {0xE9F698B3, 0xB48E, 0x4977, {0xA7, 0x73, 0x48, 0x95, 0xB8, 0x1C, 0x3D, 0x90}};
const IID iidt = {0x3C11D17E, 0x5A2C, 0x446E, {0x9E, 0x9B, 0xF1, 0x28, 0x15, 0xC9, 0xD8, 0xB8}}; // IID_IXmlDesigner
for (__int64 rind = 0; rind < rounds; ++rind)
{
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
IXmlDesigner* p_IXmlDesigner = 0;
HRESULT hr = ::CoCreateInstance(clsidt, 0, CLSCTX_INPROC_SERVER, iidt, (void**)&p_IXmlDesigner);
QueryPerformanceCounter(&tbefore);
hr = p_IXmlDesigner->load(vpath.bstrVal, 0, &resVar);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
p_IXmlDesigner->Release();
memory_ += (mafter - mbefore);
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
}
*/
// microsoft
/*
const CLSID clsid = {0x88d969c0, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5 }};
const IID iid = {0x2933BF95, 0x7B36, 0x11d2, {0xB2,0x0E, 0x00, 0xC0, 0x4F, 0x98, 0x3E, 0x60}}; // IID_IXMLDOMDocument2
for (__int64 rind = 0; rind < rounds; ++rind)
{
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
IXMLDOMDocument2* p_IXMLDOMDocument2 = 0;
HRESULT hr = ::CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, iid, (void**)&p_IXMLDOMDocument2);
QueryPerformanceCounter(&tbefore);
hr = p_IXMLDOMDocument2->load(vpath, &resVar);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
p_IXMLDOMDocument2->Release();
memory_ += (mafter - mbefore);
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
}
*/
// oracle
/*
uword ecode;
XMLParser parser;
ub4 flags = XML_FLAG_DISCARD_WHITESPACE;
for (__int64 rind = 0; rind < rounds; ++rind)
{
parser.xmlinit();
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
QueryPerformanceCounter(&tbefore);
parser.xmlparse((oratext *)(const char*)path, (oratext *) 0, flags);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
parser.xmlclean();
memory_ += (mafter - mbefore);
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
parser.xmlterm();
}
*/
// Xerces
/*
XMLPlatformUtils::Initialize();
for (int index = 0; index < rounds; ++index)
{
XercesDOMParser *parser = new XercesDOMParser();
parser->setValidationScheme(false);
parser->setDoNamespaces(false);
parser->setDoSchema(false);
parser->setValidationSchemaFullChecking(false);
parser->setCreateEntityReferenceNodes(false);
try
{
parser->parse(file);
parser->reset();
}
catch (...)
{
assert(false);
}
delete parser;
}
XMLPlatformUtils::Terminate();
*/
::SysFreeString(vpath.bstrVal);
::CloseHandle(h);
memory_ /= rounds;
time_ /= rounds;
printf("time: %d microsecond, memory: %d bytes", (int)time_, (int)memory_);
For reusing of object the follow test code was used:
PROCESS_MEMORY_COUNTERS p;
p.cb= sizeof(PROCESS_MEMORY_COUNTERS);
HANDLE h = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, ::GetCurrentProcessId());
//Cstring path = "C:\xmltest\build1.xml";
//Cstring path = "C:\xmltest\build10.xml";
//Cstring path = "C:\xmltest\build100.xml";
//Cstring path = "C:\xmltest\build1000.xml";
//Cstring path = "C:\xmltest\build10000.xml";
//__int64 rounds = 1; - 100Mb file
//__int64 rounds = 10; - 10Mb file
//__int64 rounds = 100; - 1Mb file
//__int64 rounds = 1000; - 100Kb file
//__int64 rounds = 10000; - 10 Kb file
__int64 memory_ = 0;
__int64 time_ = 0;
LARGE_INTEGER ticks;
QueryPerformanceFrequency(&ticks);
VARIANT_BOOL resVar;
VARIANT vpath;
vpath.bstrVal = path.AllocSysString();
vpath.vt = VT_BSTR;
/*
//////////////// terimber
const CLSID clsidt = {0xE9F698B3, 0xB48E, 0x4977, {0xA7, 0x73, 0x48, 0x95, 0xB8, 0x1C, 0x3D, 0x90}};
const IID iidt = {0x3C11D17E, 0x5A2C, 0x446E, {0x9E, 0x9B, 0xF1, 0x28, 0x15, 0xC9, 0xD8, 0xB8}}; // IID_IXmlDesigner
IXmlDesigner* p_IXmlDesigner = 0;
HRESULT hr = ::CoCreateInstance(clsidt, 0, CLSCTX_INPROC_SERVER, iidt, (void**)&p_IXmlDesigner);
for (__int64 rind = 0; rind < rounds; ++rind)
{
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
QueryPerformanceCounter(&tbefore);
hr = p_IXmlDesigner->load(vpath.bstrVal, 0, &resVar);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
memory_ += (mafter - mbefore);
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
}
p_IXmlDesigner->Release();
*/
// microsoft
/*
const CLSID clsid = {0x88d969c0, 0xf192, 0x11d4, {0xa6, 0x5f, 0x00, 0x40, 0x96, 0x32, 0x51, 0xe5 }};
const IID iid = {0x2933BF95, 0x7B36, 0x11d2, {0xB2,0x0E, 0x00, 0xC0, 0x4F, 0x98, 0x3E, 0x60}}; // IID_IXMLDOMDocument2
IXMLDOMDocument2* p_IXMLDOMDocument2 = 0;
HRESULT hr = ::CoCreateInstance(clsid, 0, CLSCTX_INPROC_SERVER, iid, (void**)&p_IXMLDOMDocument2);
for (__int64 rind = 0; rind < rounds; ++rind)
{
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
QueryPerformanceCounter(&tbefore);
hr = p_IXMLDOMDocument2->load(vpath, &resVar);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
memory_ += mafter - mbefore;
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
}
p_IXMLDOMDocument2->Release();
*/
// oracle
/*
uword ecode;
XMLParser parser;
ub4 flags = XML_FLAG_DISCARD_WHITESPACE;
parser.xmlinit();
for (__int64 rind = 0; rind < rounds; ++rind)
{
LARGE_INTEGER tbefore, tafter;
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mbefore = p.WorkingSetSize + p.PagefileUsage;
QueryPerformanceCounter(&tbefore);
parser.xmlparse((oratext *)(const char*)path, (oratext *) 0, flags);
QueryPerformanceCounter(&tafter);
::GetProcessMemoryInfo(h, &p, p.cb);
__int64 mafter = p.WorkingSetSize + p.PagefileUsage;
parser.xmlclean();
memory_ += (mafter - mbefore);
time_ += (tafter.QuadPart - tbefore.QuadPart) * 1000000 / ticks.QuadPart;
}
parser.xmlterm();
*/
// Xerces
// this code works, however the memory isn't released or reused
/*
XMLPlatformUtils::Initialize();
XercesDOMParser *parser = new XercesDOMParser();
parser->setValidationScheme(false);
parser->setDoNamespaces(false);
parser->setDoSchema(false);
parser->setValidationSchemaFullChecking(false);
parser->setCreateEntityReferenceNodes(false);
for (int index = 0; index < rounds; ++index)
{
try
{
parser->parse(file);
parser->reset();
}
catch (...)
{
assert(false);
}
}
delete parser;
XMLPlatformUtils::Terminate();
*/
::SysFreeString(vpath.bstrVal);
::CloseHandle(h);
memory_ /= rounds;
time_ /= rounds;
printf("time: %d microsecond, memory: %d bytes", (int)time_, (int)memory_);
|
|