Skip to content

Commit

Permalink
Improve RenderBase optimization with Type.GetTypeHandle (#632)
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Apr 23, 2022
1 parent f09d030 commit 210b39e
Showing 1 changed file with 38 additions and 18 deletions.
56 changes: 38 additions & 18 deletions src/Markdig/Renderers/RendererBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Markdig.Helpers;
using Markdig.Syntax;
using Markdig.Syntax.Inlines;
Expand All @@ -19,14 +17,33 @@ namespace Markdig.Renderers
/// <seealso cref="IMarkdownRenderer" />
public abstract class RendererBase : IMarkdownRenderer
{
private readonly Dictionary<Type, IMarkdownObjectRenderer?> _renderersPerType = new();
private readonly Dictionary<KeyWrapper, IMarkdownObjectRenderer?> _renderersPerType = new();
internal int _childrenDepth = 0;

/// <summary>
/// Initializes a new instance of the <see cref="RendererBase"/> class.
/// </summary>
protected RendererBase() { }

private IMarkdownObjectRenderer? GetRendererInstance(MarkdownObject obj)
{
KeyWrapper key = GetKeyForType(obj);
Type objectType = obj.GetType();

for (int i = 0; i < ObjectRenderers.Count; i++)
{
var renderer = ObjectRenderers[i];
if (renderer.Accept(this, objectType))
{
_renderersPerType[key] = renderer;
return renderer;
}
}

_renderersPerType[key] = null;
return null;
}

public ObjectRendererCollection ObjectRenderers { get; } = new();

public abstract object Render(MarkdownObject markdownObject);
Expand Down Expand Up @@ -124,10 +141,9 @@ public void Write(MarkdownObject obj)
// Calls before writing an object
ObjectWriteBefore?.Invoke(this, obj);

var objectType = obj.GetType();
if (!_renderersPerType.TryGetValue(objectType, out IMarkdownObjectRenderer? renderer))
if (!_renderersPerType.TryGetValue(GetKeyForType(obj), out IMarkdownObjectRenderer? renderer))
{
renderer = GetRendererInstance(objectType);
renderer = GetRendererInstance(obj);
}

if (renderer is not null)
Expand All @@ -147,20 +163,24 @@ public void Write(MarkdownObject obj)
ObjectWriteAfter?.Invoke(this, obj);
}

private IMarkdownObjectRenderer? GetRendererInstance(Type objectType)
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static KeyWrapper GetKeyForType(MarkdownObject obj)
{
var renderers = ObjectRenderers;
foreach (var renderer in renderers)
{
if (renderer.Accept(this, objectType))
{
_renderersPerType[objectType] = renderer;
return renderer;
}
}
IntPtr typeHandle = Type.GetTypeHandle(obj).Value;
return new KeyWrapper(typeHandle);
}

_renderersPerType[objectType] = null;
return null;
private readonly struct KeyWrapper : IEquatable<KeyWrapper>
{
public readonly IntPtr Key;

public KeyWrapper(IntPtr key) => Key = key;

public bool Equals(KeyWrapper other) => Key == other.Key;

public override int GetHashCode() => Key.GetHashCode();

public override bool Equals(object? obj) => throw new NotImplementedException();
}
}
}

0 comments on commit 210b39e

Please sign in to comment.