namespace Lawo.EmberPlusSharp.S101
{
using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using EmberLib.Glow.Framing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Threading.Tasks;
[TestClass]
public class PerformanceComparison : CommunicationTestBase
{
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", Justification = "Text references code elements.")]
[TestMethod]
public void S101ReadTest()
{
AsyncPump.Run(
async () =>
{
byte[] input;
using (var stream = new MemoryStream())
{
var writer = new S101Writer(stream.WriteAsync, 1024);
using (var payloadStream = await writer.WriteMessageAsync(EmberDataMessage, CancellationToken.None))
{
var payload = new byte[BlockSize];
this.Random.NextBytes(payload);
await payloadStream.WriteAsync(payload, 0, payload.Length);
await payloadStream.DisposeAsync(CancellationToken.None);
}
await writer.DisposeAsync(CancellationToken.None);
input = stream.ToArray();
}
Console.WriteLine(
"S101Reader asynchronous: {0}ms",
await TimeMethod(count => TestS101ReaderAsync(input, count), LoopCount));
});
}
[SuppressMessage("Microsoft.Naming", "CA2204:Literals should be spelled correctly", Justification = "Text references code elements.")]
[TestMethod]
public void S101WriteTest()
{
AsyncPump.Run(
async () =>
{
var input = new byte[BlockSize];
this.Random.NextBytes(input);
var glowOutputMilliseconds = await TimeMethod(count => TestGlowOutput(input, count), LoopCount);
var s101WriterAsyncMilliseconds = await TimeMethod(count => TestS101WriterAsync(input, count), LoopCount);
Console.WriteLine("GlowOutput: {0}ms", glowOutputMilliseconds);
Console.WriteLine("S101Writer asynchronous: {0}ms", s101WriterAsyncMilliseconds);
Console.WriteLine("Ratio: {0}", (double)glowOutputMilliseconds / s101WriterAsyncMilliseconds);
});
}
private const int BlockSize = 4096;
private const int BlockCount = 4096;
private const int LoopCount = 3;
private static async Task TestS101ReaderAsync(byte[] message, int messageCount)
{
byte[] buffer = new byte[BlockSize];
using (var stream = new MemoryStream(message))
{
var reader = new S101Reader(stream.ReadAsync, 1024);
for (int index = 0; index < messageCount; ++index)
{
await reader.ReadAsync(CancellationToken.None);
using (var payload = reader.Payload)
{
await payload.ReadAsync(buffer, 0, buffer.Length);
await payload.DisposeAsync(CancellationToken.None);
}
stream.Position = 0;
}
await reader.DisposeAsync(CancellationToken.None);
}
}
private static Task TestGlowOutput(byte[] block, int blockCount)
{
using (var output = new GlowOutput(1024, 0, (s, e) => { }))
{
for (int index = 0; index < blockCount; ++index)
{
output.WriteBytes(block);
}
output.Finish();
}
return Task.FromResult(false);
}
private static async Task TestS101WriterAsync(byte[] block, int blockCount)
{
var completed = Task.FromResult(false);
var writer = new S101Writer((b, o, c, t) => completed, 1024);
using (var payloadStream = await writer.WriteMessageAsync(EmberDataMessage, CancellationToken.None))
{
for (int index = 0; index < blockCount; ++index)
{
await payloadStream.WriteAsync(block, 0, block.Length);
}
await payloadStream.DisposeAsync(CancellationToken.None);
}
await writer.DisposeAsync(CancellationToken.None);
}
[SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect", Justification = "Necessary for performance testing.")]
private static async Task<long> TimeMethod(Func<int, Task> method, int loopCount)
{
await method(1);
var stopwatch = new Stopwatch();
for (var current = 0; current < loopCount; ++current)
{
GC.Collect();
stopwatch.Start();
await method(BlockCount);
GC.Collect();
stopwatch.Stop();
}
return stopwatch.ElapsedMilliseconds / loopCount;
}
}
}