Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add binary xml version to xml benchmarks #2557

Merged
merged 3 commits into from Mar 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/benchmarks/micro/Serializers/Xml_FromStream.cs
Expand Up @@ -26,6 +26,8 @@ public class Xml_FromStream<T>
private XmlSerializer xmlSerializer;
private DataContractSerializer dataContractSerializer;
private MemoryStream memoryStream;
private byte[] memoryBytes;
private XmlDictionaryReader xmlDictionaryReader;

[GlobalSetup(Target = nameof(XmlSerializer_))]
public void SetupXmlSerializer()
Expand Down Expand Up @@ -63,9 +65,35 @@ public T DataContractSerializer_()
return (T)dataContractSerializer.ReadObject(memoryStream);
}

// YAXSerializer is not included in the benchmarks because it does not allow to deserialize from stream (only from file and string)
[GlobalSetup(Target = nameof(DataContractSerializer_BinaryXml_))]
public void SetupDataContractSerializer_BinaryXml_()
{
value = DataGenerator.Generate<T>();
memoryStream = new MemoryStream(capacity: short.MaxValue);
memoryStream.Position = 0;
dataContractSerializer = new DataContractSerializer(typeof(T));
using (XmlDictionaryWriter writer = XmlDictionaryWriter.CreateBinaryWriter(memoryStream, null, null, ownsStream: false))
dataContractSerializer.WriteObject(writer, value);

memoryBytes = memoryStream.ToArray();
xmlDictionaryReader = XmlDictionaryReader.CreateBinaryReader(memoryBytes, XmlDictionaryReaderQuotas.Max);
}

[BenchmarkCategory(Categories.Libraries)]
[Benchmark(Description = nameof(XmlDictionaryReader))]
public T DataContractSerializer_BinaryXml_()
{
((IXmlBinaryReaderInitializer)xmlDictionaryReader).SetInput(memoryBytes, 0, memoryBytes.Length, null, XmlDictionaryReaderQuotas.Max, null, null);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

xmlDictionaryReader).SetInput

Consider using [IterationSetup] for this step. (https://github.com/dotnet/performance/blob/main/docs/microbenchmark-design-guidelines.md#iterationsetup)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did so earlier for my own benchmarks but that was not very successful for this case.

I think it might be fair game to benchmark with the SetInput call since that is needed for any real world scenario (corewcf , OpenRiaServices etc) where you want to read one "xml document" at a time but pool readers/writers for reuse.

When using iterationsetup the method itself should be quite long running (i think either above guidance or some other guidance says 100ms+) so it must process a lot of objects.

However I have prepared an alternative version using OperationsPerInvoke at https://github.com/Daniel-Svensson/dotnet_performance/tree/remote_setoutput with commit
128fcdf if you rather want that one. It will instead read N (100 but I am open for any value) similar objects inside a single "root" element. So the overhead will go from <= 1% to maybe 0,01% of the execution time, but will no longer match the other benchmarks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@danmoseley Do you prefer the current version which mimics the end user scenario or should the binary xml version of the benchmarks serialize many more objects than the other benchmark versions ?

unless the ci-failures are related to the changes here I think this is ready for possible merge.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is @StephenMolloy area to answer..

return (T)dataContractSerializer.ReadObject(xmlDictionaryReader);
}

// YAXSerializer is not included in the benchmarks because it does not allow to deserialize from stream (only from file and string)

[GlobalCleanup]
public void Cleanup() => memoryStream.Dispose();
public void Cleanup()
{
xmlDictionaryReader?.Dispose();
memoryStream?.Dispose();
}
}
}
18 changes: 17 additions & 1 deletion src/benchmarks/micro/Serializers/Xml_ToStream.cs
Expand Up @@ -25,6 +25,7 @@ public class Xml_ToStream<T>
private T value;
private XmlSerializer xmlSerializer;
private DataContractSerializer dataContractSerializer;
private XmlDictionaryWriter xmlDictionaryWriter;
private MemoryStream memoryStream;

[GlobalSetup]
Expand All @@ -34,6 +35,7 @@ public void Setup()
memoryStream = new MemoryStream(capacity: short.MaxValue);
xmlSerializer = new XmlSerializer(typeof(T));
dataContractSerializer = new DataContractSerializer(typeof(T));
xmlDictionaryWriter = XmlDictionaryWriter.CreateBinaryWriter(memoryStream, null, null, ownsStream: false);
}

[BenchmarkCategory(Categories.Libraries, Categories.Runtime)]
Expand All @@ -52,9 +54,23 @@ public void DataContractSerializer_()
dataContractSerializer.WriteObject(memoryStream, value);
}

[BenchmarkCategory(Categories.Libraries)]
[Benchmark(Description = nameof(XmlDictionaryWriter))]
public void DataContractSerializer_BinaryXml_()
{
memoryStream.Position = 0;
((IXmlBinaryWriterInitializer)xmlDictionaryWriter).SetOutput(memoryStream, null, null, ownsStream: false);
Daniel-Svensson marked this conversation as resolved.
Show resolved Hide resolved

dataContractSerializer.WriteObject(xmlDictionaryWriter, value);
}

// YAXSerializer is not included in the benchmarks because it does not allow to serialize to stream (only to file and string)

[GlobalCleanup]
public void Dispose() => memoryStream.Dispose();
public void Dispose()
{
xmlDictionaryWriter?.Dispose();
memoryStream?.Dispose();
}
}
}