AllocZero / EfficientDynamoDb

High-performance C# DynamoDb library
https://alloczero.github.io/EfficientDynamoDb/
MIT License
197 stars 17 forks source link

Native AOT #245

Open wahmedswl opened 1 month ago

wahmedswl commented 1 month ago

Hi!

Thanks for this awesome library. Does this support Native AOT?

Thanks

firenero commented 1 month ago

Hi @wahmedswl. Unfortunately, Native AOT is not supported. We use runtime code generation (System.Reflection.Emit) that is not compatible with the Native AOT. There could be more incompatibilities but I've never done a full evaluation and don't know the effort required to make EfficientDynamoDb Native AOT compatible.

Do you use the library in Lambda with AOT runtime for better cold starts? If not, do you mind sharing where did you plan to use the Native AOT?

wahmedswl commented 4 weeks ago

@firenero We are using AWS Lambda and yes we are evaluating Native AOT to get better cold-start time. We are evaluating EfficientDynamoDb as well to see how it will help. Following is the screenshot with aws sdk and invoking only dynamodb (Above is .Net 8.0 and below is for .Net 8.0 Native AOT).

image

firenero commented 2 weeks ago

As far as I understand from .NET AWS SDK GitHub issues, they only support low-level API because it doesn't use reflection:

There is a draft PR that's supposed to improve Native AOT compatibility but I haven't looked into what it actually does yet:

I think it should be relatively easy to add Native AOT support for low-level APIs in EfficientDynamoDb as well because there is no reflection used. I always tried to avoid using the low-level APIs in production code because it's annoying to deal with so I don't know how useful it would be. @wahmedswl is it something that sounds beneficial for your use-case?

wahmedswl commented 2 weeks ago

@firenero If we don't trim, it's only size isn't it? So, we can add EfficientDynamoDb to no trim list, then it should work isn't it?

firenero commented 2 weeks ago

I haven't checked it myself but according to https://github.com/aws/aws-sdk-net/issues/2542#issuecomment-1506468557 and the following comments you also have to exclude some system code. Also, I'm not sure that it will be enough because Limitations of native AOT deployment states that runtime code generation is not supported. We at least use System.Reflection.Emit for converters but there is a chance that something else is incompatible.

I would like to have Native AOT supported though. So it would be great if you're up to testing it and describing required changes to make it work (or submitting a PR). That said, most likely we need to keep codegen for performance reasons so most likely we'll need some compilation flags to support both cases.

Dreamescaper commented 1 week ago

In order to be fully AOT-compatible, it would probably require a source generator (similar to what System.Text.Json has). On the other hand, maybe this source-generator could even replace Reflection.Emit approach for non-AOT scenarios.

Reflection itself is somewhat supported with AOT, but traversing the properties is not. Also, lots of MakeGenericType calls wouldn't work with AOT, and they are used extensively with Convertors.

I wanted to take a quick look how hard would it be to add AOT support, but the project doesn't compile with "net8.0" target framework :).

wahmedswl commented 1 week ago

Dapper also has AOT version which they based on the Interceptors, its also new and experimental. https://aot.dapperlib.dev/

firenero commented 5 days ago

@Dreamescaper yes, I think source-gen (or interceptors as mentioned by @wahmedswl) is the way to go and it should be used for non-AOT as well just for performance gains. There is a PR #237 that compiles for .net8 and it would be great if you can take a look. There are a couple bugs with the thread-safety in converters in this PR that I mentioned in comments but it should be good enough for trying out AOT. Please let me know if you're up for looking into AOT support using this branch.

Dreamescaper commented 3 days ago

Yes, I'll take a look. Seems like most of AOT incompatibilities are in Converter Factories and in Metadata types. I would suggest the following plan of actions (similar to how it is done for System.Text.Json).

  1. Annotate all AOT incompatible code.
  2. Extract all the code, which is responsible for building the metadata to some separate type(s), with abstract base class, e.g. AbstractMetadataBuilder. Reflection and emit approach would the default implemetation of this MetadataBuilder, but it should be possible to provide a custom reflection-free implementation of it for a specific type.
  3. Create a source generator, which would generate a reflection-free MetadataBuilder for provided types.