-
Notifications
You must be signed in to change notification settings - Fork 865
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
Remove assembly scanning from DynamoDBEntryConversion #3258
Remove assembly scanning from DynamoDBEntryConversion #3258
Conversation
d62155b
to
a4a9c6a
Compare
I like this idea of getting rid of the Assembly scan. This was written at a time predating Lambda when cold starts weren't so critical. We need a way to make sure if somebody adds a new converter it doesn't get forgotten to be added here. I'm thinking a simple approach is add a |
@normj (Not sure I like it though, focusing on the implementation details, but probably better than nothing). |
@@ -20,6 +19,8 @@ | |||
#else | |||
#error Unknown platform constant - unable to set correct AssemblyDescription | |||
#endif | |||
[assembly: InternalsVisibleTo("AWSSDK.UnitTests.DynamoDBv2.Net35, PublicKey=0024000004800000940000000602000000240000525341310004000001000100db5f59f098d27276c7833875a6263a3cc74ab17ba9a9df0b52aedbe7252745db7274d5271fd79c1f08f668ecfa8eaab5626fa76adc811d3c8fc55859b0d09d3bc0a84eecd0ba891f2b8a2fc55141cdcc37c2053d53491e650a479967c3622762977900eddbf1252ed08a2413f00a28f3a0752a81203f03ccb7f684db373518b4")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The AssemblyInfo.cs
file is generated so this change would get whipped out the next time we do a build. You would need to add that change to the tt
file in the generator here and then parameterize the service name. https://github.com/aws/aws-sdk-net/blob/02ec2a6188696a765eebbf50c5fd0bf2f1321b11/generator/ServiceClientGeneratorLib/Generators/SourceFiles/AssemblyInfo.tt
To run the generator you open the AWSSDKGenerator.sln solution and then run the ServiceClientGenerator
project. That will regenerate the the AssemblyInfo.cs
. You don't want to include the generated code in the PR because then the PR will be huge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@normj
I have updated the generator to sign UnitTests projects, and include them in InternalsVisibleTo attributes.
Let me know if you'd prefer any other approach.
Thanks for the help!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@normj
The other option would be to remove this IVT attribute, and add unit tests for DynamoDBEntryConversion itself.
E.g. test that DynamoDBEntryConversion is able to convert to and from byte
instead of testing that ByteConverter is registered.
(I wasn't able to find existing tests for that, correct me if I'm wrong).
On its own, that wouldn't prevent from adding a converter and forgetting to add it to the schema, but hopefully it will encourage to add corresponding tests.
WDYT?
Sorry @Dreamescaper for going silent I was out of the office for a bit. I feel like getting the using Amazon.DynamoDBv2;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace AWSSDK_DotNet35.UnitTests
{
[TestClass]
public class DynamoDBEntryConversionTests
{
[TestMethod]
public void ValidateAllConvertersAreRegisteredForConversionV1()
{
AssertAllConvertersAreRegistered(DynamoDBEntryConversion.V1, "ConverterV1");
}
[TestMethod]
public void ValidateAllConvertersAreRegisteredForConversionV2()
{
AssertAllConvertersAreRegistered(DynamoDBEntryConversion.V2, "ConverterV2");
}
private void AssertAllConvertersAreRegistered(DynamoDBEntryConversion conversion, string suffix)
{
var converters = GetConverters(suffix);
var tryGetConverterInfo = conversion.GetType().GetMethod("TryGetConverter", BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var converter in converters)
{
var getTargetTypeInfo = converter.GetType().GetMethod("GetTargetTypes");
IEnumerable<Type> targetTypes = (IEnumerable < Type >)getTargetTypeInfo.Invoke(converter, new object[0]);
foreach (var type in targetTypes)
{
var tryGetConverterParams = new object[] { type, null };
tryGetConverterInfo.Invoke(conversion, tryGetConverterParams);
var registeredConverter = tryGetConverterParams[1];
Assert.IsNotNull(registeredConverter);
Assert.AreEqual(converter.GetType(), registeredConverter.GetType());
}
}
}
private IEnumerable<object> GetConverters(string suffix)
{
const string converterTypeName = "Amazon.DynamoDBv2.Converter";
var assembly = typeof(DynamoDBEntryConversion).Assembly;
var allTypes = assembly.GetTypes();
var typedConverterType = allTypes.FirstOrDefault(x => string.Equals(converterTypeName, x.FullName));
foreach (var type in allTypes)
{
if (type.IsAbstract)
continue;
if (!type.Name.EndsWith(suffix, StringComparison.Ordinal))
continue;
if (!typedConverterType.IsAssignableFrom(type))
continue;
var constructor = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new Type[0], null);
yield return constructor.Invoke(new object[0]);
}
}
}
} |
f3fe02b
to
009c9be
Compare
@normj I have updated the PR with your suggestion |
Looks good. I'm running the PR through our internal validation system. |
Internal dry run was successful. Let me get another reviewer to approve the change. |
The PR went out today as part of version |
Description
Replace assembly scanning in DynamoDBEntryConversion which finds converter types with explicit types created.
Motivation and Context
Assembly scanning has a cold start performance impact, which is especially important for serverless applications. In this case, it scans own assembly for types, which doesn't have much sense, as the results of that scan is static, it will never change. Therefore, it doesn't make sense to find those types in runtime.
Besides, it is more AOT-friendly, and it probably allows to remove most of RequiresUnreferencedCode attributes (not sure).
Testing
I have created a small benchmark to test cold start performance.
Benchmark
Before:
After:
Types of changes
Checklist
License