Skip to content

Commit

Permalink
types lookup optimization for RuntimeTypeModel
Browse files Browse the repository at this point in the history
  • Loading branch information
AqlaSolutions committed Aug 5, 2016
1 parent 615ac9e commit c698ef6
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 12 deletions.
176 changes: 176 additions & 0 deletions protobuf-net/Meta/RuntimeTypeModel.TypesFastFinder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
#if !PHONE8 && !PORTABLE && !SILVERLIGHT
#define ENABLED
#if WINRT
#define SLIM
#endif
#endif

// Modified by Vladyslav Taranov for AqlaSerializer, 2016
#if !NO_RUNTIME
using System;
using System.Collections;
#if !NO_GENERICS
using System.Collections.Generic;
#endif
#if !PORTABLE
using System.Runtime.Serialization;
#endif
using System.Text;
#if FEAT_IKVM
using Type = IKVM.Reflection.Type;
using IKVM.Reflection;
#if FEAT_COMPILER
using IKVM.Reflection.Emit;
using TriAxis.RunSharp;
#endif
#else
using System.Reflection;
#if FEAT_COMPILER
using System.Reflection.Emit;
using TriAxis.RunSharp;
#endif
#endif
#if FEAT_COMPILER
using AqlaSerializer.Compiler;
#endif
#if !FEAT_IKVM
using AqlaSerializer.Meta.Data;
#endif
using AqlaSerializer;
using AqlaSerializer.Serializers;
using System.Threading;
using System.IO;
using AltLinq;
using System.Linq;


#if ENABLED
#if SLIM
using ApplicationException = System.TimeoutException;
#endif
#endif


namespace AqlaSerializer.Meta
{
/// <summary>
/// Provides protobuf serialization support for a number of types that can be defined at runtime
/// </summary>
partial class RuntimeTypeModel
{
struct TypeInfoElement
{
public readonly MetaType MetaType;
public readonly int Key;

public TypeInfoElement(int key, MetaType metaType)
{
Key = key;
MetaType = metaType;
}
}

private BasicList _types = new BasicList();

#if ENABLED
Dictionary<Type, TypeInfoElement> _typesDictionary = new Dictionary<Type, TypeInfoElement>();
ReaderWriterLock _typesDictionaryLock = new ReaderWriterLock();

#if SLIM
class ReaderWriterLock
{
readonly System.Threading.ReaderWriterLockSlim _lock = new System.Threading.ReaderWriterLockSlim();

public void AcquireReaderLock(int timeout)
{
if (!_lock.TryEnterReadLock(timeout))
throw new ApplicationException("Lock enter timeout exceeded");
}

public void ReleaseReaderLock()
{
_lock.ExitReadLock();
}

public void AcquireWriterLock(int timeout)
{
if (!_lock.TryEnterReadLock(timeout))
throw new ApplicationException("Lock enter timeout exceeded");
}

public void ReleaseWriterLock()
{
_lock.ExitReadLock();
}
}
#endif


#endif
void ResetTypesDictionary()
{
#if ENABLED
_typesDictionary = new Dictionary<Type, TypeInfoElement>();
_typesDictionaryLock = new ReaderWriterLock();
#endif
}

/// <summary>
/// Used to speedup type key search (instead of IndexOf on linked list)
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
TypeInfoElement? GetTypeInfoFromDictionary(Type type)
{
#if ENABLED
bool released = false;
try
{
_typesDictionaryLock.AcquireReaderLock(60000);
TypeInfoElement v;
if (_typesDictionary.TryGetValue(type, out v)) return v;
return null;
}
catch (ApplicationException ex)
{
released = true;
throw new TimeoutException("Can't obtain a reader lock on types dictionary", ex);
}
finally
{
if (!released) _typesDictionaryLock.ReleaseReaderLock();
}
#endif
int key = _types.IndexOf(MetaTypeFinder, type);
if (key < 0) return null;
return new TypeInfoElement(key, (MetaType)_types[key]);
}

int Add(MetaType metaType)
{
_overridingManager.SubscribeTo(metaType);
int key = _types.Add(metaType);
#if ENABLED
var info = new TypeInfoElement(key, metaType);
bool released = false;

try
{
_typesDictionaryLock.AcquireWriterLock(60000);
_typesDictionary.Add(metaType.Type, info);
}
catch (ApplicationException)
{
throw new TimeoutException("Can't obtain a writer lock on types dictionary to add meta type " + metaType.Type.FullName);
}
finally
{
if (!released)
_typesDictionaryLock.ReleaseWriterLock();
}
#endif
return key;
}
}
}
#endif
20 changes: 8 additions & 12 deletions protobuf-net/Meta/RuntimeTypeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
using System.IO;
using AltLinq; using System.Linq;


namespace AqlaSerializer.Meta
{
#if !NO_GENERiCS
Expand Down Expand Up @@ -408,12 +409,14 @@ internal int FindOrAddAuto(Type type, bool demand, bool addWithContractOnly, boo
internal int FindOrAddAuto(Type type, bool demand, bool addWithContractOnly, bool addEvenIfAutoDisabled, out MetaType metaType)
{
metaType = null;
int key = _types.IndexOf(MetaTypeFinder, type);

var info = GetTypeInfoFromDictionary(type);
int key = -1;

// the fast happy path: meta-types we've already seen
if (key >= 0)
if (info != null)
{
metaType = (MetaType)_types[key];
key = info.Value.Key;
metaType = info.Value.MetaType;
if (metaType.IsPending)
{
WaitOnLock(metaType);
Expand Down Expand Up @@ -523,12 +526,6 @@ void AddDependencies(MetaType type)

OverridingManager _overridingManager = new OverridingManager();

int Add(MetaType metaType)
{
_overridingManager.SubscribeTo(metaType);
return _types.Add(metaType);
}

/// <summary>
/// Type overrides are run before preparing type serializer
/// </summary>
Expand Down Expand Up @@ -886,8 +883,6 @@ public void Freeze()
SetOption(OPTIONS_Frozen, true);
}

private BasicList _types = new BasicList();

/// <summary>
/// Provides the key that represents a given type in the current model.
/// </summary>
Expand Down Expand Up @@ -1373,6 +1368,7 @@ public RuntimeTypeModel CloneAsUnfrozen()
m.AutoAddStrategy = AutoAddStrategy.Clone(m);
m._basicTypes = new BasicList();
m._overridingManager = m._overridingManager.CloneAsUnsubscribed();
m.ResetTypesDictionary();
var cache = new MetaTypeCloneCache(m);
m._types = new BasicList();
m.ValueSerializerBuilder = new ValueSerializerBuilder(m);
Expand Down
1 change: 1 addition & 0 deletions protobuf-net/aqlaserializer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@
<Compile Include="Meta\MetaType.Surrogate.cs" />
<Compile Include="Meta\OverridingManager.cs" />
<Compile Include="Meta\ReflectionObjectMap.cs" />
<Compile Include="Meta\RuntimeTypeModel.TypesFastFinder.cs" />
<Compile Include="Meta\ValueSerializationSettings.cs" />
<Compile Include="Meta\ValueSerializerBuilder.cs" />
<Compile Include="ProtoAggregateException.cs" />
Expand Down

0 comments on commit c698ef6

Please sign in to comment.