Skip to content

Avoid Hashtable-related allocations in DataBindEngine #6501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,14 @@ internal IValueConverter GetDefaultValueConverter(Type sourceType,
Type targetType,
bool targetToSource)
{
IValueConverter result = _valueConverterTable[sourceType, targetType, targetToSource];

if (result == null)
ValueConverterTableKey key = new ValueConverterTableKey(sourceType, targetType, targetToSource);
if (!_valueConverterTable.TryGetValue(key, out IValueConverter result))
{
result = DefaultValueConverter.Create(sourceType, targetType, targetToSource, this);
if (result != null)
_valueConverterTable.Add(sourceType, targetType, targetToSource, result);
{
_valueConverterTable.Add(key, result);
}
}

return result;
Expand Down Expand Up @@ -657,63 +658,26 @@ private void OnLayoutUpdated(object sender, EventArgs e)
//
//------------------------------------------------------

// cache of default value converters (so that all uses of string-to-int can
// share the same converter)
class ValueConverterTable : Hashtable
private readonly struct ValueConverterTableKey : IEquatable<ValueConverterTableKey>
{
struct Key
{
Type _sourceType, _targetType;
bool _targetToSource;

public Key(Type sourceType, Type targetType, bool targetToSource)
{
_sourceType = sourceType;
_targetType = targetType;
_targetToSource = targetToSource;
}
private readonly Type _sourceType, _targetType;
private readonly bool _targetToSource;

public override int GetHashCode()
{
return _sourceType.GetHashCode() + _targetType.GetHashCode();
}

public override bool Equals(object o)
{
if (o is Key)
{
return (this == (Key)o);
}
return false;
}

public static bool operator ==(Key k1, Key k2)
{
return k1._sourceType == k2._sourceType &&
k1._targetType == k2._targetType &&
k1._targetToSource == k2._targetToSource;
}

public static bool operator !=(Key k1, Key k2)
{
return !(k1 == k2);
}
}

public IValueConverter this[Type sourceType, Type targetType, bool targetToSource]
public ValueConverterTableKey(Type sourceType, Type targetType, bool targetToSource)
{
get
{
Key key = new Key(sourceType, targetType, targetToSource);
object value = base[key];
return (IValueConverter)value;
}
_sourceType = sourceType;
_targetType = targetType;
_targetToSource = targetToSource;
}

public void Add(Type sourceType, Type targetType, bool targetToSource, IValueConverter value)
{
base.Add(new Key(sourceType, targetType, targetToSource), value);
}
public override int GetHashCode() => _sourceType.GetHashCode() + _targetType.GetHashCode();

public override bool Equals(object o) => o is ValueConverterTableKey other && Equals(other);

public bool Equals(ValueConverterTableKey other) =>
_sourceType == other._sourceType &&
_targetType == other._targetType &&
_targetToSource == other._targetToSource;
}

private sealed class DataBindEngineShutDownListener : ShutDownListener
Expand Down Expand Up @@ -741,7 +705,7 @@ internal override void OnShutDown(object target, object sender, EventArgs e)
private UIElement _layoutElement;
private ViewManager _viewManager = new ViewManager();
private CommitManager _commitManager = new CommitManager();
private ValueConverterTable _valueConverterTable = new ValueConverterTable();
private Dictionary<ValueConverterTableKey, IValueConverter> _valueConverterTable = new Dictionary<ValueConverterTableKey, IValueConverter>();
private PathParser _pathParser = new PathParser();
private IAsyncDataDispatcher _defaultAsyncDataDispatcher;
private HybridDictionary _asyncDispatchers;
Expand Down