Skip to content

Commit

Permalink
Merge pull request #1 from skbkontur/mikheev.a/ConvertersPrecompiler
Browse files Browse the repository at this point in the history
Mikheev.a/converters precompiler
  • Loading branch information
AndrewKostousov authored Aug 14, 2018
2 parents 6e750fc + 1dca8f4 commit e4e252a
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 55 deletions.
11 changes: 6 additions & 5 deletions Mutators/AutoEvaluators/NullifyIfConfiguration.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
Expand Down Expand Up @@ -59,12 +59,13 @@ public override Expression Apply(Expression path, List<KeyValuePair<Expression,
var infoToLog = new AssignLogInfo(path, Expression.Constant(ToString(), typeof(string)));
var condition = Expression.Equal(Expression.Convert(Condition.Body.ResolveAliases(aliases), typeof(bool?)), Expression.Constant(true, typeof(bool?)));
path = PrepareForAssign(path);
var applyResult = Expression.IfThen(condition, Expression.Assign(path, Expression.Constant(path.Type.GetDefaultValue(), path.Type)));
if (MutatorsAssignRecorder.IsRecording())
{
MutatorsAssignRecorder.RecordCompilingExpression(infoToLog);
return Expression.Block(
Expression.Call(typeof(MutatorsAssignRecorder).GetMethod("RecordExecutingExpression"), Expression.Constant(infoToLog)),
Expression.IfThen(condition, Expression.Assign(path, Expression.Constant(path.Type.GetDefaultValue(), path.Type)))
);
return Expression.Block(Expression.Call(typeof(MutatorsAssignRecorder).GetMethod("RecordExecutingExpression"), Expression.Constant(infoToLog)), applyResult);
}
return applyResult;
}

public LambdaExpression Condition { get; private set; }
Expand Down
81 changes: 34 additions & 47 deletions Mutators/ConverterCollection.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
Expand All @@ -15,7 +16,6 @@
using GrobExp.Mutators.Visitors;

using Vostok.Logging.Abstractions;
using Vostok.Logging.Abstractions.Extensions;

namespace GrobExp.Mutators
{
Expand Down Expand Up @@ -47,7 +47,7 @@ public Action<TSource, TDest> GetMerger(MutatorsContext context)

public MutatorsTreeBase<TSource> Migrate(MutatorsTreeBase<TDest> mutatorsTree, MutatorsContext context)
{
return mutatorsTree == null ? null : mutatorsTree.Migrate<TSource>(GetOrCreateHashtableSlot(context).ConverterTree);
return mutatorsTree?.Migrate<TSource>(GetOrCreateHashtableSlot(context).ConverterTree);
}

public MutatorsTreeBase<TSource> GetValidationsTree(MutatorsContext context, int priority)
Expand All @@ -71,7 +71,7 @@ public MutatorsTreeBase<TSource> GetValidationsTree(MutatorsContext context, int

public MutatorsTreeBase<TDest> MigratePaths(MutatorsTreeBase<TDest> mutatorsTree, MutatorsContext context)
{
return mutatorsTree == null ? null : mutatorsTree.MigratePaths<TSource>(GetOrCreateHashtableSlot(context).ConverterTree);
return mutatorsTree?.MigratePaths<TSource>(GetOrCreateHashtableSlot(context).ConverterTree);
}

protected abstract void Configure(MutatorsContext context, ConverterConfigurator<TSource, TDest> configurator);
Expand Down Expand Up @@ -103,28 +103,39 @@ private HashtableSlot GetOrCreateHashtableSlot(MutatorsContext context)
ConfigureInternal(context, new ConverterConfigurator<TSource, TDest>(tree));
var validationsTree = ModelConfigurationNode.CreateRoot(typeof(TSource));
tree.ExtractValidationsFromConverters(validationsTree);
var treeMutator = (Expression<Action<TDest, TSource>>)tree.BuildTreeMutator(typeof(TSource));
logger.Info($"Started compiling converter from {typeof(TSource).FullName} to {typeof(TDest).FullName} with context: {key}");
var compiledTreeMutator = LambdaCompiler.Compile(treeMutator, CompilerOptions.All);
logger.Info($"Finished compiling converter from {typeof(TSource).FullName} to {typeof(TDest).FullName}");

var treeConverter = (Expression<Action<TDest, TSource>>)tree.BuildTreeMutator(typeof(TSource));

Action<TDest, TSource> compiledTreeConverter;
var sw = Stopwatch.StartNew();
try
{
compiledTreeConverter = LambdaCompiler.Compile(treeConverter, CompilerOptions.All);
}
finally
{
sw.Stop();
LogConverterCompilation(context, sw);
}

slot = new HashtableSlot
{
ConverterTree = tree,
ValidationsTree = validationsTree,
Converter = (source =>
Converter = source =>
{
var dest = new TDest();
BeforeConvert(source);
compiledTreeMutator(dest, source);
compiledTreeConverter(dest, source);
AfterConvert(dest, source);
return dest;
}),
Merger = ((source, dest) =>
},
Merger = (source, dest) =>
{
BeforeConvert(source);
compiledTreeMutator(dest, source);
compiledTreeConverter(dest, source);
AfterConvert(dest, source);
}),
},
ValidationMutatorsTrees = new Hashtable()
};
//if(!MutatorsAssignRecorder.IsRecording())
Expand All @@ -136,33 +147,17 @@ private HashtableSlot GetOrCreateHashtableSlot(MutatorsContext context)
return slot;
}

private HashtableSlot CreateHashtableSlot(MutatorsContext context)
private void LogConverterCompilation(MutatorsContext context, Stopwatch sw)
{
var converterTree = ModelConfigurationNode.CreateRoot(typeof(TDest));
ConfigureInternal(context, new ConverterConfigurator<TSource, TDest>(converterTree));
var validationsTree = ModelConfigurationNode.CreateRoot(typeof(TSource));
converterTree.ExtractValidationsFromConverters(validationsTree);
var treeMutator = (Expression<Action<TDest, TSource>>)converterTree.BuildTreeMutator(typeof(TSource));
var compiledTreeMutator = LambdaCompiler.Compile(treeMutator, CompilerOptions.All);
return new HashtableSlot
var logProperties = new Dictionary<string, object>
{
ConverterTree = converterTree,
ValidationsTree = validationsTree,
Converter = source =>
{
var dest = new TDest();
BeforeConvert(source);
compiledTreeMutator(dest, source);
AfterConvert(dest, source);
return dest;
},
Merger = (source, dest) =>
{
BeforeConvert(source);
compiledTreeMutator(dest, source);
AfterConvert(dest, source);
}
{"ConverterCollectionName", GetType().Name},
{"CompilationTimeMilliseconds", sw.ElapsedMilliseconds}
};
var mutatorsContextTypeName = context.GetType().Name;
foreach (var propertyInfo in context.GetType().GetProperties())
logProperties.Add($"{mutatorsContextTypeName}.{propertyInfo.Name}", propertyInfo.GetValue(context));
logger.Log(new LogEvent(LogLevel.Info, DateTimeOffset.UtcNow, "{ConverterCollectionName} was compiled in {CompilationTimeMilliseconds} ms", logProperties));
}

private static TypeCode GetTypeCode(Type type)
Expand Down Expand Up @@ -421,13 +416,6 @@ private Expression MakeConvert(Expression value, Type type)
return Expression.Convert(value, type);
}

private static bool IsPrimitive(Type type)
{
if (type.IsNullable())
return IsPrimitive(type.GetGenericArguments()[0]);
return type.IsPrimitive || type == typeof(decimal);
}

private void ConfigureCustomFields(ConverterConfigurator<TSource, TDest> configurator)
{
var sourceParameter = Expression.Parameter(typeof(TSource));
Expand Down Expand Up @@ -472,8 +460,7 @@ private void ConfigureCustomFieldsForArrays(ConverterConfigurator<TSource, TDest
if (node == null)
continue;
var arrays = node.GetArrays();
Expression pathToSourceArray;
if (!arrays.TryGetValue(typeof(TSource), out pathToSourceArray))
if (!arrays.TryGetValue(typeof(TSource), out var pathToSourceArray))
continue;
var pathToDestArrayItem = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(pathToDestArray.Type.GetItemType()), pathToDestArray);
var pathToSourceArrayItem = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(pathToSourceArray.Type.GetItemType()), pathToSourceArray);
Expand All @@ -482,7 +469,7 @@ private void ConfigureCustomFieldsForArrays(ConverterConfigurator<TSource, TDest
}
}

private void ConfigureInternal(MutatorsContext context, ConverterConfigurator<TSource, TDest> configurator)
protected void ConfigureInternal(MutatorsContext context, ConverterConfigurator<TSource, TDest> configurator)
{
Configure(context, configurator);
ConfigureCustomFields(configurator);
Expand Down
5 changes: 3 additions & 2 deletions Mutators/MutatorsContext.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
namespace GrobExp.Mutators
namespace GrobExp.Mutators
{
public abstract class MutatorsContext
{
public abstract string GetKey();

public static readonly MutatorsContext Empty = new EmptyMutatorsContext();
}

public sealed class EmptyMutatorsContext : MutatorsContext
{
public override string GetKey()
{
return "";
return string.Empty;
}
}
}
2 changes: 1 addition & 1 deletion Mutators/MutatorsTreeBase.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
Expand Down

0 comments on commit e4e252a

Please sign in to comment.