TurboXml is a .NET library that provides a lightweight and fast SAX - Simple API XML parser by using callbacks.
$ dotnet add package TurboXml
TurboXml is a .NET library that provides a lightweight and fast SAX - Simple API XML parser by using callbacks.
This is the equivalent of
System.Xml.XmlReaderbut faster with no allocations. 🚀
System.Xml.XmlReaderReadOnlySpan<char> for the parsed elements.net8.0+TurboXML is in the family of the SAX parsers and so you need to implement the callbacks defined by IXmlReadHandler.
By default this handler implements empty interface methods that you can easily override:
var xml = "<?xml version=\"1.0\"?><root enabled=\"true\">Hello World!</root>";
var handler = new MyXmlHandler();
XmlParser.Parse(xml, ref handler);
// Will print:
//
// BeginTag(1:23): root
// Attribute(1:28)-(1:36): enabled="true"
// Content(1:43): Hello World!
// EndTag(1:57): root
struct MyXmlHandler : IXmlReadHandler
{
public void OnBeginTag(ReadOnlySpan<char> name, int line, int column)
=> Console.WriteLine($"BeginTag({line + 1}:{column + 1}): {name}");
public void OnEndTagEmpty()
=> Console.WriteLine($"EndTagEmpty");
public void OnEndTag(ReadOnlySpan<char> name, int line, int column)
=> Console.WriteLine($"EndTag({line + 1}:{column + 1}): {name}");
public void OnAttribute(ReadOnlySpan<char> name, ReadOnlySpan<char> value, int nameLine, int nameColumn, int valueLine, int valueColumn)
=> Console.WriteLine($"Attribute({nameLine + 1}:{nameColumn + 1})-({valueLine + 1}:{valueColumn + 1}): {name}=\"{value}\"");
public void OnText(ReadOnlySpan<char> text, int line, int column)
=> Console.WriteLine($"Content({line + 1}:{column + 1}): {text}");
}
The solution contains 2 benchmarks:
BenchStream that parses 240+ MSBuild xml files (targets and props) from the .NET 8 (or latest SDK) installedBenchString that parses the Tiger.svg in memory from a string.In general, the advantages of TurboXml over System.Xml.XmlReader:
ReadOnlySpan<char> back the the XML Handler.BenchmarkDotNet v0.13.12, Windows 11 (10.0.22631.3085/23H2/2023Update/SunValley3)
AMD Ryzen 9 7950X, 1 CPU, 32 logical and 16 physical cores
.NET SDK 8.0.101
[Host] : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
DefaultJob : .NET 8.0.1 (8.0.123.58001), X64 RyuJIT AVX-512F+CD+BW+DQ+VL+VBMI
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|---|---|---|---|---|---|---|
| TurboXml - Stream | 3.993 ms | 0.0780 ms | 0.0729 ms | - | - | 13.18 KB |
| System.Xml.XmlReader - Stream | 4.163 ms | 0.0386 ms | 0.0361 ms | 328.1250 | 46.8750 | 5415.45 KB |
| Method | Mean | Error | StdDev | Gen0 | Gen1 | Allocated |
|---|---|---|---|---|---|---|
| TurboXml | 52.14 us | 1.040 us | 1.491 us | - | - | - |
| System.Xml.XmlReader | 56.98 us | 0.393 us | 0.348 us | 2.9297 | 0.2441 | 49304 B |
This parser is following the Extensible Markup Language (XML) 1.0 (Fifth Edition) and should support any XML valid documents, except for the known limitations described below:
<!DOCTYPE ...>). If you are looking for this, you should instead use System.Xml.XmlReader.You need to install the .NET 8 SDK. Then from the root folder:
$ dotnet build src -c Release
This software is released under the BSD-2-Clause license.
Alexandre Mutel aka xoofx.