Skip to content

Commit 1785f17

Browse files
committed
Optimize size of PackedFieldDescriptor struct from 16 bytes to 8
1 parent 29d716d commit 1785f17

File tree

3 files changed

+44
-34
lines changed

3 files changed

+44
-34
lines changed

Orm/Xtensive.Orm/Tuples/Packed/PackedFieldAccessor.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2013-2021 Xtensive LLC.
1+
// Copyright (C) 2013-2022 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -10,6 +10,8 @@ namespace Xtensive.Tuples.Packed
1010
{
1111
internal abstract class PackedFieldAccessor
1212
{
13+
public static readonly PackedFieldAccessor[] All = new PackedFieldAccessor[20];
14+
1315
/// <summary>
1416
/// Getter delegate.
1517
/// </summary>
@@ -33,6 +35,7 @@ internal abstract class PackedFieldAccessor
3335
public readonly int Rank;
3436
public readonly int ValueBitCount;
3537
protected readonly long ValueBitMask;
38+
public readonly byte Index;
3639

3740
public void SetValue<T>(PackedTuple tuple, ref PackedFieldDescriptor descriptor, bool isNullable, T value)
3841
{
@@ -70,9 +73,14 @@ public abstract bool ValueEquals(PackedTuple left, ref PackedFieldDescriptor lef
7073

7174
public abstract int GetValueHashCode(PackedTuple tuple, ref PackedFieldDescriptor descriptor);
7275

73-
protected PackedFieldAccessor(int rank)
76+
protected PackedFieldAccessor(int rank, byte index)
7477
{
7578
Rank = rank;
79+
Index = index;
80+
if (All[Index] != null) {
81+
throw new IndexOutOfRangeException($"Duplicated Index {Index} of PackedFieldAccessor instance");
82+
}
83+
All[Index] = this;
7684
ValueBitCount = 1 << Rank;
7785

7886
// What we want here is to shift 1L by ValueBitCount to left and then subtract 1
@@ -128,7 +136,7 @@ public override int GetValueHashCode(PackedTuple tuple, ref PackedFieldDescripto
128136
}
129137

130138
public ObjectFieldAccessor()
131-
: base(-1)
139+
: base(-1, 19)
132140
{ }
133141
}
134142

@@ -146,8 +154,8 @@ private static int GetRank(int bitSize)
146154
return rank;
147155
}
148156

149-
protected ValueFieldAccessor(int bitCount)
150-
: base(GetRank(bitCount))
157+
protected ValueFieldAccessor(int bitCount, byte index)
158+
: base(GetRank(bitCount), index)
151159
{}
152160
}
153161

@@ -255,8 +263,8 @@ private T Load(PackedTuple tuple, ref PackedFieldDescriptor d)
255263
return Decode(encoded);
256264
}
257265

258-
protected ValueFieldAccessor(int bits)
259-
: base(bits)
266+
protected ValueFieldAccessor(int bits, byte index)
267+
: base(bits, index)
260268
{
261269
FieldType = typeof(T);
262270
Getter = (GetValueDelegate<T>) GetValue;
@@ -280,7 +288,7 @@ protected override bool Decode(long value)
280288
}
281289

282290
public BooleanFieldAccessor()
283-
: base(1)
291+
: base(1, 1)
284292
{
285293
}
286294
}
@@ -303,7 +311,7 @@ protected override float Decode(long value)
303311
}
304312

305313
public FloatFieldAccessor()
306-
: base(sizeof(float) * 8)
314+
: base(sizeof(float) * 8, 2)
307315
{
308316
}
309317
}
@@ -321,7 +329,7 @@ protected override double Decode(long value)
321329
}
322330

323331
public DoubleFieldAccessor()
324-
: base(sizeof(double) * 8)
332+
: base(sizeof(double) * 8, 3)
325333
{
326334
}
327335
}
@@ -339,7 +347,7 @@ protected override TimeSpan Decode(long value)
339347
}
340348

341349
public TimeSpanFieldAccessor()
342-
: base(sizeof(long) * 8)
350+
: base(sizeof(long) * 8, 4)
343351
{
344352
}
345353
}
@@ -357,7 +365,7 @@ protected override DateTime Decode(long value)
357365
}
358366

359367
public DateTimeFieldAccessor()
360-
: base(sizeof(long) * 8)
368+
: base(sizeof(long) * 8, 5)
361369
{
362370
}
363371
}
@@ -375,7 +383,7 @@ protected override byte Decode(long value)
375383
}
376384

377385
public ByteFieldAccessor()
378-
: base(sizeof(byte) * 8)
386+
: base(sizeof(byte) * 8, 6)
379387
{
380388
}
381389
}
@@ -393,7 +401,7 @@ protected override sbyte Decode(long value)
393401
}
394402

395403
public SByteFieldAccessor()
396-
: base(sizeof(sbyte) * 8)
404+
: base(sizeof(sbyte) * 8, 7)
397405
{
398406
}
399407
}
@@ -411,7 +419,7 @@ protected override short Decode(long value)
411419
}
412420

413421
public ShortFieldAccessor()
414-
: base(sizeof(short) * 8)
422+
: base(sizeof(short) * 8, 8)
415423
{
416424
}
417425
}
@@ -429,7 +437,7 @@ protected override ushort Decode(long value)
429437
}
430438

431439
public UShortFieldAccessor()
432-
: base(sizeof(ushort) * 8)
440+
: base(sizeof(ushort) * 8, 9)
433441
{
434442
}
435443
}
@@ -447,7 +455,7 @@ protected override int Decode(long value)
447455
}
448456

449457
public IntFieldAccessor()
450-
: base(sizeof(int) * 8)
458+
: base(sizeof(int) * 8, 10)
451459
{
452460
}
453461
}
@@ -465,7 +473,7 @@ protected override uint Decode(long value)
465473
}
466474

467475
public UIntFieldAccessor()
468-
: base(sizeof(uint) * 8)
476+
: base(sizeof(uint) * 8, 11)
469477
{
470478
}
471479
}
@@ -483,7 +491,7 @@ protected override long Decode(long value)
483491
}
484492

485493
public LongFieldAccessor()
486-
: base(sizeof(long) * 8)
494+
: base(sizeof(long) * 8, 12)
487495
{
488496
}
489497
}
@@ -501,7 +509,7 @@ protected override ulong Decode(long value)
501509
}
502510

503511
public ULongFieldAccessor()
504-
: base(sizeof(ulong) * 8)
512+
: base(sizeof(ulong) * 8, 13)
505513
{
506514
}
507515
}
@@ -530,7 +538,7 @@ private static unsafe int GetSize()
530538
}
531539

532540
public GuidFieldAccessor()
533-
: base(GetSize() * 8)
541+
: base(GetSize() * 8, 14)
534542
{
535543
}
536544
}
@@ -553,7 +561,7 @@ protected override void Encode(decimal value, long[] values, int offset)
553561
}
554562
}
555563
public DecimalFieldAccessor()
556-
: base(sizeof(decimal) * 8)
564+
: base(sizeof(decimal) * 8, 15)
557565
{
558566
}
559567
}
@@ -582,7 +590,7 @@ private static unsafe int GetSize()
582590
}
583591

584592
public DateTimeOffsetFieldAccessor()
585-
: base(GetSize() * 8)
593+
: base(GetSize() * 8, 16)
586594
{ }
587595
}
588596
}

Orm/Xtensive.Orm/Tuples/Packed/PackedFieldDescriptor.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// Copyright (C) 2003-2012 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2003-2022 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
55
// Created: 2012.12.29
66

@@ -15,10 +15,12 @@ internal struct PackedFieldDescriptor
1515
private const int OffsetMask = (1 << OffsetBitCount) - 1;
1616

1717
internal int DataPosition;
18-
internal int StatePosition;
18+
internal ushort StatePosition;
1919

2020
[NonSerialized]
21-
public PackedFieldAccessor Accessor;
21+
internal byte AccessorIndex;
22+
23+
public PackedFieldAccessor Accessor => PackedFieldAccessor.All[AccessorIndex];
2224

2325
public bool IsObjectField => Accessor.Rank < 0;
2426

Orm/Xtensive.Orm/Tuples/Packed/TupleLayout.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,15 @@ ValueFieldAccessor ResolveByNullableType(Type type)
111111

112112
[MethodImpl(MethodImplOptions.AggressiveInlining)]
113113
public static void ConfigureFieldAccessor(ref PackedFieldDescriptor descriptor, Type fieldType) =>
114-
descriptor.Accessor = (PackedFieldAccessor) ValueFieldAccessorResolver.GetValue(fieldType) ?? ObjectAccessor;
114+
descriptor.AccessorIndex = ((PackedFieldAccessor)ValueFieldAccessorResolver.GetValue(fieldType) ?? ObjectAccessor).Index;
115115

116116
[MethodImpl(MethodImplOptions.AggressiveInlining)]
117117
public static void ConfigureLen1(Type[] fieldTypes, ref PackedFieldDescriptor descriptor, out int valuesLength,
118118
out int objectsLength)
119119
{
120120
var valueAccessor = ValueFieldAccessorResolver.GetValue(fieldTypes[0]);
121121
if (valueAccessor != null) {
122-
descriptor.Accessor = valueAccessor;
122+
descriptor.AccessorIndex = valueAccessor.Index;
123123
descriptor.DataPosition = Val064BitCount;
124124

125125
valuesLength = (valueAccessor.ValueBitCount + ((Val064BitCount * 2) - 1)) >> Val064Rank;
@@ -128,7 +128,7 @@ public static void ConfigureLen1(Type[] fieldTypes, ref PackedFieldDescriptor de
128128
return;
129129
}
130130

131-
descriptor.Accessor = ObjectAccessor;
131+
descriptor.AccessorIndex = ObjectAccessor.Index;
132132
valuesLength = 1;
133133
objectsLength = 1;
134134
}
@@ -234,19 +234,19 @@ private static void UpdateDescriptorPosition(ref PackedFieldDescriptor descripto
234234
private static void ConfigureFieldPhase1(ref PackedFieldDescriptor descriptor, ref Counters counters,
235235
Type[] fieldTypes, int fieldIndex)
236236
{
237-
descriptor.StatePosition = fieldIndex << 1;
237+
descriptor.StatePosition = checked((ushort)(fieldIndex << 1));
238238

239239
var valueAccessor = ValueFieldAccessorResolver.GetValue(fieldTypes[fieldIndex]);
240240
if (valueAccessor != null) {
241-
descriptor.Accessor = valueAccessor;
241+
descriptor.AccessorIndex = valueAccessor.Index;
242242

243243
IncrementerByRank[valueAccessor.Rank].Invoke(ref counters);
244244

245245
fieldTypes[fieldIndex] = valueAccessor.FieldType;
246246
return;
247247
}
248248

249-
descriptor.Accessor = ObjectAccessor;
249+
descriptor.AccessorIndex = ObjectAccessor.Index;
250250
descriptor.DataPosition = counters.ObjectCounter++;
251251
}
252252

0 commit comments

Comments
 (0)