Skip to content

Commit

Permalink
Merge pull request #99 from Nexus-Mods/decouple-registry
Browse files Browse the repository at this point in the history
Decouple Registry
  • Loading branch information
halgari authored Sep 20, 2024
2 parents babefcb + b7d50dc commit a0fd0af
Show file tree
Hide file tree
Showing 164 changed files with 3,230 additions and 1,974 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
## Changelog

### 0.9.83 - 20/09/2024
* Optimized the interface with RocksDB used all throughout the library. Results in a 30% speedup on search operations
inside RocksDB.
* Removed the IAttributeRegistry and all associated IDs and implementations. Functionality is now split into two sub-modules
* AttributeCache - sealed class that is created by the backend store and is purely based on the database schema, used by most of the system
* AttributeResolver - DI dependant code that the frontend of the system uses to resolve DB datoms to C# attributes. Used very rarely
* It is now possible for most DB operations to be run completely ignorant of the C# attribute definitions.

### 0.9.82 - 12/09/2024
* Fix a O(n) issue caused by Rx storing observers in a ImmutableList inside a `BehaviorSubject`. Switched to using R3 internally. Over
time Rx's uses will be replaced with R3 to avoid these and several other issues
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ public class IndexSegmentABenchmarks

public IndexSegmentABenchmarks()
{
var registry = new AttributeRegistry(null!, []);
using var builder = new IndexSegmentBuilder(registry);
var cache = new AttributeCache();
using var builder = new IndexSegmentBuilder(cache);

for (int a = 1; a < 100; a++)
{
var prefix = new KeyPrefix(EntityId.From(42), AttributeId.From((ushort)a), TxId.From(42), false,
ValueTags.Null);
builder.Add(new Datom(prefix, ReadOnlyMemory<byte>.Empty, registry));
builder.Add(new Datom(prefix, ReadOnlyMemory<byte>.Empty));
}

_index = builder.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public class IndexSegmentEBenchmarks

public IndexSegmentEBenchmarks()
{
var registry = new AttributeRegistry(null!, []);
var registry = new AttributeCache();
using var builder = new IndexSegmentBuilder(registry);

for (var e = 1; e < 100; e++)
{
for (var a = 0; a < 20; a++)
{
builder.Add(new Datom(new KeyPrefix(EntityId.From((ulong)e), AttributeId.From((ushort)a), TxId.From((ulong)(e + a)), false,
ValueTags.Null), ReadOnlyMemory<byte>.Empty, registry));
ValueTags.Null), ReadOnlyMemory<byte>.Empty));
}
}

Expand Down
81 changes: 20 additions & 61 deletions src/NexusMods.MnemonicDB.Abstractions/Attribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,6 @@ public abstract partial class Attribute<TValueType, TLowLevelType> : IAttribute<

private static Encoding Utf8Encoding = Encoding.UTF8;


protected RegistryId.InlineCache Cache;

protected Attribute(
ValueTags lowLevelType,
string ns,
Expand All @@ -51,23 +48,23 @@ protected Attribute(
/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(byte value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(byte value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ushort value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(ushort value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(uint value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(uint value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}
Expand All @@ -76,15 +73,15 @@ protected virtual TValueType FromLowLevel(uint value, ValueTags tags, RegistryId
/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(string value, ValueTags tag, RegistryId registryId)
protected virtual TValueType FromLowLevel(string value, ValueTags tag, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ReadOnlySpan<byte> value, ValueTags tag, RegistryId registryId)
protected virtual TValueType FromLowLevel(ReadOnlySpan<byte> value, ValueTags tag, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + tag + " on attribute " + Id);
}
Expand All @@ -93,7 +90,7 @@ protected virtual TValueType FromLowLevel(ReadOnlySpan<byte> value, ValueTags ta
/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(ulong value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(ulong value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}
Expand All @@ -102,55 +99,55 @@ protected virtual TValueType FromLowLevel(ulong value, ValueTags tags, RegistryI
/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(UInt128 value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(UInt128 value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(short value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(short value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(int value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(int value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(long value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(long value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(Int128 value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(Int128 value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(float value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(float value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}

/// <summary>
/// Converts a low-level value to a high-level value
/// </summary>
protected virtual TValueType FromLowLevel(double value, ValueTags tags, RegistryId registryId)
protected virtual TValueType FromLowLevel(double value, ValueTags tags, AttributeResolver resolver)
{
throw new NotSupportedException("Unsupported low-level type " + value + " on attribute " + Id);
}
Expand All @@ -173,48 +170,33 @@ protected virtual TValueType FromLowLevel(double value, ValueTags tags, Registry
/// <inheritdoc />
public virtual bool DeclaredOptional { get; protected init; }

/// <inheritdoc />
public void SetDbId(RegistryId id, AttributeId attributeId)
{
Cache[id.Value] = attributeId;
}

/// <inheritdoc />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public AttributeId GetDbId(RegistryId id)
{
var aid = Cache[id.Value];
Debug.Assert(aid.Value != 0, $"Attribute ID is 0 for {Id}, was it registered?");
return aid;
}

/// <inheritdoc />
public Type ValueType => typeof(TValueType);

/// <inheritdoc />
public bool IsReference => LowLevelType == ValueTags.Reference;

/// <inheritdoc />
IReadDatom IAttribute.Resolve(in KeyPrefix prefix, ReadOnlySpan<byte> valueSpan, RegistryId registryId)
IReadDatom IAttribute.Resolve(in KeyPrefix prefix, ReadOnlySpan<byte> valueSpan, AttributeResolver resolver)
{
return new ReadDatom(in prefix, ReadValue(valueSpan, prefix.ValueTag, registryId), this);
return new ReadDatom(in prefix, ReadValue(valueSpan, prefix.ValueTag, resolver), this);
}

/// <summary>
/// Resolves the value from the given value span into a high-level ReadDatom
/// </summary>
public ReadDatom Resolve(in KeyPrefix prefix, ReadOnlySpan<byte> valueSpan, RegistryId registryId)
public ReadDatom Resolve(in KeyPrefix prefix, ReadOnlySpan<byte> valueSpan, AttributeResolver resolver)
{
return new ReadDatom(in prefix, ReadValue(valueSpan, prefix.ValueTag, registryId), this);
return new ReadDatom(in prefix, ReadValue(valueSpan, prefix.ValueTag, resolver), this);
}

/// <summary>
/// Resolves the low-level Datom into a high-level ReadDatom
/// </summary>
public ReadDatom Resolve(in Datom datom, RegistryId id)
public ReadDatom Resolve(in Datom datom, AttributeResolver resolver)
{
var prefix = datom.Prefix;
return new ReadDatom(in prefix, ReadValue(datom.ValueSpan, datom.Prefix.ValueTag, id), this);
return new ReadDatom(in prefix, ReadValue(datom.ValueSpan, datom.Prefix.ValueTag, resolver), this);
}

/// <summary>
Expand Down Expand Up @@ -286,23 +268,7 @@ public override string ToString()
{
return Id.ToString();
}

/// <summary>
/// Gets a service provider thats specific to this registry defined by the registry id
/// </summary>
protected IServiceProvider GetServiceProvider(RegistryId registryId)
{
return AttributeRegistryRegistry.Registries[registryId.Value]!.ServiceProvider;
}

/// <summary>
/// Gets the registry for the given registry id
/// </summary>
protected IAttributeRegistry GetRegistry(RegistryId registryId)
{
return AttributeRegistryRegistry.Registries[registryId.Value]!;
}

/// <summary>
/// Typed datom for this attribute
/// </summary>
Expand Down Expand Up @@ -359,9 +325,7 @@ public void Retract(ITransaction tx)

/// <inheritdoc />
public Type ValueType => typeof(TValueType);

public KeyPrefix prefix { get; init; }


/// <inheritdoc />
public override string ToString()
{
Expand All @@ -381,10 +345,5 @@ public int HashCodeByValue()
{
return HashCode.Combine(A, E, V);
}

public void Deconstruct(out KeyPrefix prefix)
{
prefix = this.prefix;
}
}
}
Loading

0 comments on commit a0fd0af

Please sign in to comment.