@@ -2,6 +2,12 @@ namespace SpacetimeDB.BSATN;
2
2
3
3
using System . Text ;
4
4
5
+ internal static class StructuralReadWrite < T >
6
+ where T : IStructuralReadWrite , new ( )
7
+ {
8
+ public static readonly System . Func < T > Constructor = ( ) => new T ( ) ;
9
+ }
10
+
5
11
public interface IStructuralReadWrite
6
12
{
7
13
void ReadFields ( BinaryReader reader ) ;
@@ -11,10 +17,16 @@ public interface IStructuralReadWrite
11
17
static T Read < T > ( BinaryReader reader )
12
18
where T : IStructuralReadWrite , new ( )
13
19
{
14
- // TODO: use `RuntimeHelpers.GetUninitializedObject` as an optimisation here.
15
- // We tried but couldn't do this because BitCraft relies on being able
16
- // to add and initialize custom fields on autogenerated classes.
17
- var result = new T ( ) ;
20
+ // Previously we attempted to use `GetUninitializedObject` as an optimisation here.
21
+ // This is because `new T()` can use reflection depending on the runtime, compiler, etc.
22
+ // And this is a cost that we must pay per deserialized row.
23
+ // Unfortunately BitCraft relies on being able to add and initialize custom fields on autogenerated classes.
24
+ // Therefore we couldn't use `GetUninitializedObject`.
25
+ //
26
+ // Instead we use a lambda inside a generic static class.
27
+ // Supposedly this always result in monomorphization.
28
+ // This may not be the case for generic methods depending on the runtime.
29
+ var result = StructuralReadWrite < T > . Constructor ( ) ;
18
30
result . ReadFields ( reader ) ;
19
31
return result ;
20
32
}
0 commit comments