Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions src/benchmarks/micro/Serializers/Xml_FromStream.cs
Original file line number Diff line number Diff line change
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

@StephenMolloy StephenMolloy Aug 17, 2022

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

@Daniel-Svensson Daniel-Svensson Aug 17, 2022

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
Original file line number Diff line number Diff line change
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);

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();
}
}
}