Skip to content

Commit

Permalink
Improved performance
Browse files Browse the repository at this point in the history
  • Loading branch information
NikolayPianikov committed Apr 27, 2024
1 parent 68c2c07 commit 8789eea
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 14 deletions.
26 changes: 25 additions & 1 deletion src/Pure.DI.Core/Core/Code/BlockCodeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,31 @@ variable.Node.Lifetime is Lifetime.Singleton or Lifetime.Scoped
finally
{
info.HasCode = true;
ctx.Code.AppendLines(info.Code.Lines);
// ctx.Code.AppendLines(info.Code.Lines);
if (block.Parent is not null
&& info is { PerBlockRefCount: > 2, Code.Lines.Count: > 3 })
{
var localFunctionsCode = ctx.LocalFunctionsCode;
var localMethodName = $"{Names.LocalMethodPrefix}{variable.VariableName}{Names.EnsureExistsMethodNamePostfix}";
if (variable.Node.Binding.SemanticModel.Compilation.GetLanguageVersion() >= LanguageVersion.CSharp9)
{
localFunctionsCode.AppendLine($"[{Names.MethodImplAttribute}(({Names.MethodImplOptions})0x100)]");
}

localFunctionsCode.AppendLine($"void {localMethodName}()");
localFunctionsCode.AppendLine("{");
using (localFunctionsCode.Indent())
{
localFunctionsCode.AppendLines(info.Code.Lines);
}

localFunctionsCode.AppendLine("}");
ctx.Code.AppendLine($"{localMethodName}();");
}
else
{
ctx.Code.AppendLines(info.Code.Lines);
}
}
}

Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Code/BuildContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ internal record BuildContext(
DependencyGraph DependencyGraph,
Variable Variable,
LinesBuilder Code,
LinesBuilder LocalFunctionsCode,
object? ContextTag,
bool? LockIsRequired,
ImmutableArray<Accumulator> Accumulators);
2 changes: 2 additions & 0 deletions src/Pure.DI.Core/Core/Code/CompositionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public CompositionCode Build(DependencyGraph graph)
graph,
rootBlock.Current,
new LinesBuilder(),
new LinesBuilder(),
root.Injection.Tag != MdTag.ContextTag ? root.Injection.Tag : default,
default,
root.Node.Accumulators.ToImmutableArray());
Expand All @@ -46,6 +47,7 @@ public CompositionCode Build(DependencyGraph graph)

blockBuilder.Build(ctx, rootBlock);
ctx.Code.AppendLine($"return {buildTools.OnInjected(ctx, rootBlock.Current)};");
ctx.Code.AppendLines(ctx.LocalFunctionsCode.Lines);

var args = GetRootArgs(map.Values).ToImmutableArray();
var processedRoot = root with
Expand Down
7 changes: 6 additions & 1 deletion src/Pure.DI.Core/Core/Code/VariableInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,25 @@

internal class VariableInfo
{
private readonly HashSet<int> _perBlockRefCounts = [];
public readonly HashSet<Block> Owners = [];
public bool IsCreated;
public bool HasCode;
public LinesBuilder Code = new();

public int RefCount { get; private set; } = 1;

public void AddRef()
public int PerBlockRefCount => _perBlockRefCounts.Count;

public void AddRef(Block parentBlock)
{
RefCount++;
_perBlockRefCounts.Add(parentBlock.Id);
}

public void Reset()
{
_perBlockRefCounts.Clear();
Owners.Clear();
RefCount = 1;
IsCreated = false;
Expand Down
10 changes: 7 additions & 3 deletions src/Pure.DI.Core/Core/Code/VariablesBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,17 @@ public Block Build(
var counter = 0;
while (blocks.TryPop(out var currentBlock))
{
if (cancellationToken.IsCancellationRequested)
{
break;
}

var stack = new Stack<IStatement>(currentBlock.Statements);
while (stack.TryPop(out var currentStatement))
{
cancellationToken.ThrowIfCancellationRequested();
if (counter++ > Const.MaxIterationsCount)
{
throw new CompileErrorException("Cyclic dependency has been found.", rootNode.Binding.Source.GetLocation(), LogId.ErrorCyclicDependency);
throw new CompileErrorException($"The composition is too large. Stopped on the #{counter} instance.", rootNode.Binding.Source.GetLocation(), LogId.ErrorInvalidMetadata);
}

switch (currentStatement)
Expand Down Expand Up @@ -219,7 +223,7 @@ private Variable GetVariable(

if (map.TryGetValue(node.Binding, out var variable))
{
variable.Info.AddRef();
variable.Info.AddRef(parentBlock);
return variable with
{
Parent = parentBlock,
Expand Down
10 changes: 3 additions & 7 deletions src/Pure.DI.Core/Core/CodeBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,10 @@ public Unit Build(MdSetup setup)
composition = classBuilder.Build(composition);

cancellationToken.ThrowIfCancellationRequested();
var code = new StringBuilder(composition.Code.Sum(i => i.Length + 2));
foreach (var line in composition.Code)
{
code.AppendLine(line);
}

var size = composition.Code.SaveToArray(Encoding.UTF8, out var buffer);

cancellationToken.ThrowIfCancellationRequested();
sources.AddSource($"{setup.Name.FullName}.g.cs", SourceText.From(code.ToString(), Encoding.UTF8));
sources.AddSource($"{setup.Name.FullName}.g.cs", SourceText.From(buffer, size, Encoding.UTF8, SourceHashAlgorithm.Sha1, false, true));
return Unit.Shared;
}
}
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/Const.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public static class Const
{
public const int MaxIterationsCount = 0xffff;
public const int MaxIterationsCount = 0x8FFFF;
}
2 changes: 1 addition & 1 deletion src/Pure.DI.Core/Core/DependencyGraphBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ public IEnumerable<DependencyNode> TryBuild(
cancellationToken.ThrowIfCancellationRequested();
if (counter++ > Const.MaxIterationsCount)
{
throw new CompileErrorException("Cyclic dependency has been found.", setup.Source.GetLocation(), LogId.ErrorCyclicDependency);
throw new CompileErrorException($"The composition is too large. Stopped on the #{counter} dependency.", setup.Source.GetLocation(), LogId.ErrorInvalidMetadata);
}

var targetNode = node.Node;
Expand Down
27 changes: 27 additions & 0 deletions src/Pure.DI.Core/Core/LinesBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// ReSharper disable ReturnTypeCanBeEnumerable.Global
namespace Pure.DI.Core;

using System.Buffers;

internal sealed class LinesBuilder: IEnumerable<string>
{
private static readonly string[] Indents = new string[64];
Expand Down Expand Up @@ -87,6 +89,31 @@ public IEnumerator<string> GetEnumerator()
return _lines.Select(i => $"{GetIndent(i.Indent)}{i.Text}").GetEnumerator();
}

public int SaveToArray(Encoding encoding, out byte[] buffer)
{
var charCount = 0;
var newLine = Environment.NewLine;
foreach (var line in _lines)
{
charCount += GetIndent(line.Indent).Length;
charCount += line.Text.Length;
charCount += newLine.Length;
}

var size = encoding.GetMaxByteCount(charCount);
buffer = ArrayPool<byte>.Shared.Rent(size);
var position = 0;
foreach (var line in _lines)
{
var indent = GetIndent(line.Indent);
position += encoding.GetBytes(indent, 0, indent.Length, buffer, position);
position += encoding.GetBytes(line.Text, 0, line.Text.Length, buffer, position);
position += encoding.GetBytes(newLine, 0, newLine.Length, buffer, position);
}

return position;
}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

private void FlushLines()
Expand Down
1 change: 1 addition & 0 deletions src/Pure.DI.Core/Core/Names.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ internal static class Names

// Local methods
public const string LocalMethodPrefix = "Local";
public const string EnsureExistsMethodNamePostfix = "EnsureExists";

// Fields
public static readonly string BucketsFieldName = $"_buckets{Salt}";
Expand Down

0 comments on commit 8789eea

Please sign in to comment.