Skip to content

Optimize PackedFieldDescriptor to avoid Bit operations; DO_MAX_1000_COLUMNS definition #200

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 11 commits into from
Mar 30, 2024
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -143,5 +143,6 @@

<DefineConstants Condition="'$(DO_SAFE_COLLECTION_WRAPPER)'=='true'">$(DefineConstants);DO_SAFE_COLLECTION_WRAPPER</DefineConstants>
<DefineConstants Condition="'$(DO_CONFIGURE_AWAIT_FALSE)'=='true'">$(DefineConstants);DO_CONFIGURE_AWAIT_FALSE</DefineConstants>
<DefineConstants Condition="'$(DO_MAX_1000_COLUMNS)'!='false'">$(DefineConstants);DO_MAX_1000_COLUMNS</DefineConstants>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,9 @@ public void InsertTest07()
}
}

#if !DO_MAX_1000_COLUMNS
[Test]
#endif
public void InsertTest08()
{
using (var session = Domain.OpenSession())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,15 @@ public void OnDefinitionsBuilt(BuildingContext context, DomainModelDef model)
var originalCount = context.Domain.Handlers.ProviderInfo.MaxQueryParameterCount;
var maxcount = originalCount;

#if DO_MAX_1000_COLUMNS
if (maxcount > 989) {
maxcount = 989;
}
#else
if (maxcount > 1024) {
maxcount = 1000;
}

#endif
var validFieldCount = maxcount - 1;
var invalidFieldCount = validFieldCount + 10;
var t = model.Types[typeof(ALotOfFieldsEntityValid)];
Expand Down Expand Up @@ -220,6 +225,9 @@ public void OnDefinitionsBuilt(BuildingContext context, DomainModelDef model)
indexToWrite = 0;
currentFieldCount = 0;
var fieldsCount = 2100;
#if DO_MAX_1000_COLUMNS
fieldsCount = 990;
#endif
foreach (var fieldName in GetFieldNames(fieldsCount)) {
_ = types[indexToWrite].DefineField(fieldName, typeof(int));
currentFieldCount++;
Expand Down
28 changes: 14 additions & 14 deletions Orm/Xtensive.Orm/Tuples/Packed/PackedFieldAccessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,12 @@ public override object GetUntypedValue(PackedTuple tuple, PackedFieldDescriptor
{
var state = tuple.GetFieldState(descriptor);
fieldState = state;
return state == TupleFieldState.Available ? tuple.Objects[descriptor.GetObjectIndex()] : null;
return state == TupleFieldState.Available ? tuple.Objects[descriptor.Index] : null;
}

public override void SetUntypedValue(PackedTuple tuple, PackedFieldDescriptor descriptor, object value)
{
tuple.Objects[descriptor.GetObjectIndex()] = value;
tuple.Objects[descriptor.Index] = value;
tuple.SetFieldState(descriptor, value != null ? TupleFieldState.Available : (TupleFieldState.Available | TupleFieldState.Null));
}

Expand All @@ -161,18 +161,18 @@ public override void SetValue(PackedTuple tuple, PackedFieldDescriptor descripto
public override void CopyValue(PackedTuple source, PackedFieldDescriptor sourceDescriptor,
PackedTuple target, PackedFieldDescriptor targetDescriptor)
{
target.Objects[targetDescriptor.GetObjectIndex()] = source.Objects[sourceDescriptor.GetObjectIndex()];
target.Objects[targetDescriptor.Index] = source.Objects[sourceDescriptor.Index];
}

public override bool ValueEquals(PackedTuple left, PackedFieldDescriptor leftDescriptor,
PackedTuple right, PackedFieldDescriptor rightDescriptor)
{
return Equals(left.Objects[leftDescriptor.GetObjectIndex()], right.Objects[rightDescriptor.GetObjectIndex()]);
return Equals(left.Objects[leftDescriptor.Index], right.Objects[rightDescriptor.Index]);
}

public override int GetValueHashCode(PackedTuple tuple, PackedFieldDescriptor descriptor)
{
return tuple.Objects[descriptor.GetObjectIndex()]?.GetHashCode() ?? 0;
return tuple.Objects[descriptor.Index]?.GetHashCode() ?? 0;
}

public ObjectFieldAccessor()
Expand Down Expand Up @@ -265,14 +265,14 @@ private void SetNullableValue(PackedTuple tuple, PackedFieldDescriptor descripto
protected virtual void Store(PackedTuple tuple, PackedFieldDescriptor d, T value)
{
var encoded = Encode(value);
ref var block = ref tuple.Values[d.GetValueIndex()];
var valueBitOffset = d.GetValueBitOffset();
ref var block = ref tuple.Values[d.Index];
var valueBitOffset = d.ValueBitOffset;
var mask = ValueBitMask << valueBitOffset;
block = (block & ~mask) | ((encoded << valueBitOffset) & mask);
}

protected virtual T Load(PackedTuple tuple, PackedFieldDescriptor d) =>
Decode((tuple.Values[d.GetValueIndex()] >> d.GetValueBitOffset()) & ValueBitMask);
Decode((tuple.Values[d.Index] >> d.ValueBitOffset) & ValueBitMask);

protected ValueFieldAccessor(int bits, byte index)
: base(bits, index)
Expand Down Expand Up @@ -569,15 +569,15 @@ internal sealed class GuidFieldAccessor : ValueFieldAccessor<Guid>
protected override Guid Load(PackedTuple tuple, PackedFieldDescriptor d)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
return *(Guid*) valuePtr;
}
}

protected override void Store(PackedTuple tuple, PackedFieldDescriptor d, Guid value)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
*(Guid*) valuePtr = value;
}
}
Expand All @@ -601,15 +601,15 @@ internal sealed class DecimalFieldAccessor : ValueFieldAccessor<decimal>
protected override decimal Load(PackedTuple tuple, PackedFieldDescriptor d)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
return *(decimal*) valuePtr;
}
}

protected override void Store(PackedTuple tuple, PackedFieldDescriptor d, decimal value)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
*(decimal*) valuePtr = value;
}
}
Expand All @@ -628,15 +628,15 @@ internal sealed class DateTimeOffsetFieldAccessor : ValueFieldAccessor<DateTimeO
protected override DateTimeOffset Load(PackedTuple tuple, PackedFieldDescriptor d)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
return *(DateTimeOffset*) valuePtr;
}
}

protected override void Store(PackedTuple tuple, PackedFieldDescriptor d, DateTimeOffset value)
{
unsafe {
fixed (long* valuePtr = &tuple.Values[d.GetValueIndex()])
fixed (long* valuePtr = &tuple.Values[d.Index])
*(DateTimeOffset*) valuePtr = value;
}
}
Expand Down
20 changes: 0 additions & 20 deletions Orm/Xtensive.Orm/Tuples/Packed/PackedFieldDescriptiorExtensions.cs

This file was deleted.

89 changes: 85 additions & 4 deletions Orm/Xtensive.Orm/Tuples/Packed/PackedFieldDescriptor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,97 @@
// Created: 2012.12.29

using System;
using System.Runtime.CompilerServices;

namespace Xtensive.Tuples.Packed
{
[Serializable]
internal struct PackedFieldDescriptor
{
internal int DataPosition;
internal ushort StatePosition;
#if DO_MAX_1000_COLUMNS
private int bitFields;

[NonSerialized]
internal int Index
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => bitFields & 0x7FF;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => bitFields = bitFields & ~0x7FF | value;
}

internal int StateIndex
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (bitFields >> 11) & 0x1F;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => bitFields = bitFields & ~(0x1F << 11) | (value << 11);
}

internal int ValueBitOffset
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (bitFields >> 16) & 0x3F;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => bitFields = bitFields & ~0x3F0000 | (value << 16);
}

internal int StateBitOffset
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (bitFields >> 21) & 0x3E; // Even always

[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => bitFields = bitFields & ~(0x3E << 21) | (value << 21);
}

internal int AccessorIndex
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => (bitFields >> 27) & 0x1F;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
set => bitFields = bitFields & ~(0x1F << 27) | (value << 27);
}
#else
internal ushort Index;
internal ushort StateIndex;
internal byte ValueBitOffset;
internal byte StateBitOffset;
internal byte AccessorIndex;

#endif // DO_MAX_1000_COLUMNS

internal int DataPosition
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set {
Index = (ushort) (value >> 6);
ValueBitOffset = (byte) (value & 0x3F);
}
}

internal int StatePosition
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
set {
StateIndex = (ushort) (value >> 6);
StateBitOffset = (byte) (value & 0x3F);
}
}

internal PackedFieldAccessor Accessor
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => PackedFieldAccessor.All[AccessorIndex];
}

internal bool IsObjectField
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => Accessor.Rank < 0;
}
}
}
}
29 changes: 13 additions & 16 deletions Orm/Xtensive.Orm/Tuples/Packed/PackedTuple.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public override bool Equals(Tuple other)
return false;
}
if (thisState == TupleFieldState.Available &&
!descriptor.GetAccessor().ValueEquals(this, descriptor, packedOther, descriptor)) {
!descriptor.Accessor.ValueEquals(this, descriptor, packedOther, descriptor)) {
return false;
}
}
Expand All @@ -72,7 +72,7 @@ public override int GetHashCode()
ref readonly var descriptor = ref fieldDescriptors[i];
var state = GetFieldState(descriptor);
var fieldHash = state == TupleFieldState.Available
? descriptor.GetAccessor().GetValueHashCode(this, descriptor)
? descriptor.Accessor.GetValueHashCode(this, descriptor)
: 0;
result = HashCodeMultiplier * result ^ fieldHash;
}
Expand All @@ -94,27 +94,27 @@ protected internal override void SetFieldState(int fieldIndex, TupleFieldState f
public override object GetValue(int fieldIndex, out TupleFieldState fieldState)
{
ref readonly var descriptor = ref PackedDescriptor.FieldDescriptors[fieldIndex];
return descriptor.GetAccessor().GetUntypedValue(this, descriptor, out fieldState);
return descriptor.Accessor.GetUntypedValue(this, descriptor, out fieldState);
}

public override T GetValue<T>(int fieldIndex, out TupleFieldState fieldState)
{
var isNullable = null == default(T); // Is nullable value type or class
ref readonly var descriptor = ref PackedDescriptor.FieldDescriptors[fieldIndex];
return descriptor.GetAccessor().GetValue<T>(this, descriptor, isNullable, out fieldState);
return descriptor.Accessor.GetValue<T>(this, descriptor, isNullable, out fieldState);
}

public override void SetValue(int fieldIndex, object fieldValue)
{
ref readonly var descriptor = ref PackedDescriptor.FieldDescriptors[fieldIndex];
descriptor.GetAccessor().SetUntypedValue(this, descriptor, fieldValue);
descriptor.Accessor.SetUntypedValue(this, descriptor, fieldValue);
}

public override void SetValue<T>(int fieldIndex, T fieldValue)
{
var isNullable = null==default(T); // Is nullable value type or class
ref readonly var descriptor = ref PackedDescriptor.FieldDescriptors[fieldIndex];
descriptor.GetAccessor().SetValue(this, descriptor, isNullable, fieldValue);
descriptor.Accessor.SetValue(this, descriptor, isNullable, fieldValue);
}

public override void SetValueFromDataReader(in MapperReader mr)
Expand All @@ -124,27 +124,24 @@ public override void SetValueFromDataReader(in MapperReader mr)
}
else {
ref readonly var descriptor = ref PackedDescriptor.FieldDescriptors[mr.FieldIndex];
descriptor.GetAccessor().SetValue(this, descriptor, mr);
descriptor.Accessor.SetValue(this, descriptor, mr);
}
}

public void SetFieldState(PackedFieldDescriptor d, TupleFieldState fieldState)
{
var bits = (long) fieldState;
ref var block = ref Values[d.GetStateIndex()];
var stateBitOffset = d.GetStateBitOffset();
ref var block = ref Values[d.StateIndex];
var stateBitOffset = d.StateBitOffset;
block = (block & ~(3L << stateBitOffset)) | (bits << stateBitOffset);

if (fieldState != TupleFieldState.Available && d.IsObjectField()) {
Objects[d.GetObjectIndex()] = null;
if (fieldState != TupleFieldState.Available && d.IsObjectField) {
Objects[d.Index] = null;
}
}

public TupleFieldState GetFieldState(PackedFieldDescriptor d)
{
int stateIndex = d.GetStateIndex(), stateBitOffset = d.GetStateBitOffset();
return (TupleFieldState) ((Values[stateIndex] >> stateBitOffset) & 3);
}
public TupleFieldState GetFieldState(PackedFieldDescriptor d) =>
(TupleFieldState) ((Values[d.StateIndex] >> d.StateBitOffset) & 3);

public PackedTuple(in TupleDescriptor descriptor)
{
Expand Down
Loading
Loading