aws-lambda-dotnet icon indicating copy to clipboard operation
aws-lambda-dotnet copied to clipboard

Example of removing trim warnings from RuntimeSupport Library

Open Beau-Gosse-dev opened this issue 3 years ago • 0 comments

Overview

As a test to see how hard it is to prepare a library for trimming, I made these changes and then published a NativeAOT binary from a sample lambda.CustomRuntime template. With these changes, the RuntimeSupport library no longer gives any trim warnings. (The Lambda serialization library still warns).

In some parts of the code, mainly error reporting, I just removed calls to reflection and replaced them with something else. These aren't production ready and would take a bit more though to really make work.

In other parts of the code, mainly the RunAsync, I just created a new code path that NativeAOT code can use instead which avoids reflection. This was possible, since the main RunAysnc code was using reflection to pre-JIT things, which wouldn't be needed anyway with NativeAOT.

This only fixes 100% of trim warnings when using the code below, if you're calling other parts of the library, you might get other trim warnings. It would be important to eventually cover all entry points into the library.

        Func<string, ILambdaContext, Task<string>> handler = FunctionHandler;
        await LambdaBootstrapBuilder.Create(handler, new DefaultLambdaJsonSerializer())
            .Build()
            .RunNativeAotAsync();

Runtime Errors

This should make the code a bit safer, although I need to do further testing to see what the real results to x-ray logging are when a trimmed type is attempted to be used. I have previously hit missing metadata exceptions in test Lambdas and didn't notice any issues in the logs, so I'm not sure how much this change actually helps.

Binary Size

For code size, I wasn't able to actually get the binary file to change size with or without trimming (using IsTrimmable in the RuntimeSupport csproj, might be a bug in NativeAOT). I tried publishing the lib natively on it's own but it needs to pull in the whole .NET runtime with it, so it's hard to tell what Lambda is adding. However, with some very loose assumptions below, we can estimate that we could reduce file size by 1 to 2 MB.

In testing, a pretty much empty, Hello World .NET app in Release config came out as 4583KB. A Hello World Custom Runtime Lambda in Release config came out as 13389KB. So all of the Lambda code added about 9MB and probably came from from these 5 sources:

  1. Amazon.Lambda.Core
  2. Amazon.Lambda.RuntimeSupport
  3. Amazon.Lambda.Serialization.Json
  4. (Maybe Newtonsoft.Json, which Amazon.Lambda.Serialization.Json depends on)
  5. All the parts of .NET that these depend on, that a basic .NET HelloWorld doesn't already.

If we assume (and this is a big assumption) that Amazon.Lambda.RuntimeSupport code was only 20% of the 9MB, then RuntimeSupport only added 1.8MB. However we won't ever be able to trim out all the RuntimeSupport code, so if we assume we can only trim 75% of the code, that leaves us with 1.35MB trimmed. So by enabling trimming in this library and we can hope to reduce the final binary size by a very-loose estimate of 1 to 2 MB. For reference the limit for a Lambda binary is 250MB.

(These numbers were taken from a Windows file system, I'm not sure if that changes any of this based kilobyte vs kibibytes)

Beau-Gosse-dev avatar Jun 23 '22 19:06 Beau-Gosse-dev