added custom LinkedList serializer + tests + perf tests

This commit is contained in:
Bartosz Sypytkowski 2016-12-15 16:42:44 +01:00
Родитель f9487dd154
Коммит 4b7c78bc49
6 изменённых файлов: 124 добавлений и 8 удалений

Просмотреть файл

@ -142,15 +142,14 @@ namespace Hyperion.Tests.Performance.Deserialization
InitStreamWith(new LinkedList<string>(new[] { "asdad", "asdabs3", "dfsdf9", "asdf4r", "sfsdf44g" }));
}
[NBenchFact(Skip = "FIXME: some problem with recursion, StackOverflowException")]
[NBenchFact]
[PerfBenchmark(
Description = "Benchmark linked list deserialization",
NumberOfIterations = StandardIterationCount,
RunMode = RunMode.Throughput,
RunTimeMilliseconds = StandardRunTime,
TestMode = TestMode.Test,
Skip = "FIXME: some problem with recursion, StackOverflowException")]
[CounterThroughputAssertion(TestCounterName, MustBe.GreaterThan, 80000)]
TestMode = TestMode.Test)]
[CounterThroughputAssertion(TestCounterName, MustBe.GreaterThan, 150000)]
public void Deserialize_LinkedList()
{
Stream.Position = 0; // don't move it up to Setup, I don't know why it needed here to work

Просмотреть файл

@ -80,15 +80,14 @@ namespace Hyperion.Tests.Performance.Serialization
SerializeAndCount(new List<string> { "asdad", "asdabs3", "sfsdf44g", "asdf4r", "sfsdf44g" });
}
[NBenchFact(Skip = "FIXME: Stack overflow exception")]
[NBenchFact]
[PerfBenchmark(
Description = "Benchmark linked list serialization",
NumberOfIterations = StandardIterationCount,
RunMode = RunMode.Throughput,
RunTimeMilliseconds = StandardRunTime,
TestMode = TestMode.Test,
Skip = "FIXME: Stack overflow exception")]
[CounterThroughputAssertion(TestCounterName, MustBe.GreaterThan, 210000)]
TestMode = TestMode.Test)]
[CounterThroughputAssertion(TestCounterName, MustBe.GreaterThan, 500000)]
public void Serialize_LinkedList()
{
var list = new LinkedList<string>(new[] { "asdad", "asdabs3", "dfsdf9", "asdf4r", "sfsdf44g" });

Просмотреть файл

@ -167,6 +167,30 @@ namespace Hyperion.Tests
Assert.Equal(expected, actual);
}
[Fact]
public void CanSerializeLinkedList()
{
var expected = new LinkedList<Something>(new[]
{
new Something
{
BoolProp = true,
Else = new Else
{
Name = "Yoho"
},
Int32Prop = 999,
StringProp = "Yesbox!"
},
new Something(), new Something(), null
});
Serialize(expected);
Reset();
var actual = Deserialize<LinkedList<Something>>();
Assert.Equal(expected, actual);
}
[Fact(Skip = "add support for multi dimentional arrays")]
public void CanSerializeMultiDimentionalArray()
{

Просмотреть файл

@ -68,6 +68,7 @@
<Compile Include="SerializerFactories\FSharpMapSerializerFactory.cs" />
<Compile Include="SerializerFactories\ImmutableCollectionsSerializerFactory.cs" />
<Compile Include="SerializerFactories\ISerializableSerializerFactory.cs" />
<Compile Include="SerializerFactories\LinkedListSerializerFactory.cs" />
<Compile Include="SerializerFactories\MethodInfoSerializerFactory.cs" />
<Compile Include="SerializerFactories\ToSurrogateSerializerFactory.cs" />
<Compile Include="SerializerFactories\ValueSerializerFactory.cs" />

Просмотреть файл

@ -0,0 +1,92 @@
#region copyright
// -----------------------------------------------------------------------
// <copyright file="LinkedListSerializerFactory.cs" company="Akka.NET Team">
// Copyright (C) 2015-2016 AsynkronIT <https://github.com/AsynkronIT>
// Copyright (C) 2016-2016 Akka.NET Team <https://github.com/akkadotnet>
// </copyright>
// -----------------------------------------------------------------------
#endregion
using System;
using System.Reflection;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Hyperion.Extensions;
using Hyperion.ValueSerializers;
namespace Hyperion.SerializerFactories
{
public sealed class LinkedListSerializerFactory : ValueSerializerFactory
{
private static readonly Type LinkedListType = typeof(LinkedList<>);
public override bool CanSerialize(Serializer serializer, Type type) => type.IsGenericType && type.GetGenericTypeDefinition() == LinkedListType;
public override bool CanDeserialize(Serializer serializer, Type type) => CanSerialize(serializer, type);
private static void WriteValues<T>(LinkedList<T> list, Stream stream, Type elementType, ValueSerializer elementSerializer, SerializerSession session)
{
Int32Serializer.WriteValueImpl(stream, list.Count, session);
var preserveObjectReferences = session.Serializer.Options.PreserveObjectReferences;
foreach (var value in list)
{
stream.WriteObject(value, elementType, elementSerializer, preserveObjectReferences, session);
}
}
private static void ReadValues<T>(int length, Stream stream, DeserializerSession session, LinkedList<T> list)
{
for (var i = 0; i < length; i++)
{
var value = (T)stream.ReadObject(session);
list.AddLast(value);
}
}
private static Type GetLinkedListType(Type type)
{
return type.GetTypeInfo().GetGenericArguments()[0];
}
public override ValueSerializer BuildSerializer(Serializer serializer, Type type,
ConcurrentDictionary<Type, ValueSerializer> typeMapping)
{
var elementType = GetLinkedListType(type);
var elementSerializer = serializer.GetSerializerByType(elementType);
var preserveObjectReferences = serializer.Options.PreserveObjectReferences;
//TODO: code gen this part
ObjectReader reader = (stream, session) =>
{
var length = stream.ReadInt32(session);
var array = Activator.CreateInstance(type);
if (preserveObjectReferences)
{
session.TrackDeserializedObject(array);
}
ReadValues(length, stream, session, (dynamic)array);
return array;
};
ObjectWriter writer = (stream, arr, session) =>
{
if (preserveObjectReferences)
{
session.TrackSerializedObject(arr);
}
WriteValues((dynamic)arr, stream, elementType, elementSerializer, session);
};
var ser = new ObjectSerializer(type);
ser.Initialize(reader, writer);
typeMapping.TryAdd(type, ser);
return ser;
}
}
}

Просмотреть файл

@ -39,6 +39,7 @@ namespace Hyperion
new DefaultDictionarySerializerFactory(),
new DictionarySerializerFactory(),
new ArraySerializerFactory(),
new LinkedListSerializerFactory(),
#if SERIALIZATION
new ISerializableSerializerFactory(), //TODO: this will mess up the indexes in the serializer payload
#endif