Skip to content
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

Avoid creating unnecessary intermediate strings #3439

Merged
merged 7 commits into from
Aug 24, 2024

Conversation

paulomorgado
Copy link

Addresses #3415

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist

  • My code follows the code style of this project
  • My change requires a change to the documentation
  • I have updated the documentation accordingly
  • I have read the README document
  • I have added tests to cover my changes
  • All new and existing tests passed

License

  • I confirm that this pull request can be released under the Apache 2 license

/cc @bhoradc

@dscpinheiro dscpinheiro changed the base branch from main to v4-development August 14, 2024 15:39
Copy link
Contributor

@slang25 slang25 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix typo

@slang25
Copy link
Contributor

slang25 commented Aug 15, 2024

This change would be awesome, I spotted this a few months back, basically all JSON APIs are using triple the necessary memory for the request body.

@peterrsongg
Copy link
Contributor

+1 to fixing the typo, otherwise change looks okay. I'm running a version of this branch with the typo fix through our build system, will approve if it passes the dry-run.

@peterrsongg
Copy link
Contributor

The change caused some existing unit tests to fail in our build system. I'll need to take a look at why this is the case

@paulomorgado
Copy link
Author

@peterrsongg,

The change caused some existing unit tests to fail in our build system. I'll need to take a look at why this is the case

Is this something I can have a look at?

@peterrsongg
Copy link
Contributor

@peterrsongg,

The change caused some existing unit tests to fail in our build system. I'll need to take a look at why this is the case

Is this something I can have a look at?

If you wanted to take a look that'd be great. I'm caught up in something else right now, but here are the failed tests

====== TestWrapper Run Attempt 3 =====
--
899 | MSTestRunner
900 | Failed Tests :
901 | NotRequiredEnabledNoIdentifiersNoWait
902 |  
903 | RequiredNoIdentifiersFailedDiscovery
904 |  
905 | RequiredWithIdentifiers
906 |  
907 | NotRequiredEnabledHasIdentifiersWait
908 |  
909 | RequiredNoIdentifiersEvictCache
910 |  
911 | CacheEvictionTestUsingEndpointDiscoveryCallStack
912 |  
913 | NotRequiredEnabledHasIdentifiersNoWait
914 |  
915 | NotRequiredNoIdentifiersFailedDiscoveryWait
916 |  
917 | NotRequiredEnabledNoIdentifiersWait
918 |  
919 | NotRequiredNoIdentifiersFailedDiscoveryNoWait
920 |  
921 | RequiredNoIdentifiersCached
922 |  
923 | RequiredWithIdentifiersCached
924 |  
925 | RequiredNoIdentifiers
926 |  
927 | Passed : 0, Failed : 17

All of the failures have the same error message

Error Message:
--
1013 | Test method AWSSDK.UnitTests.EndpointDiscoveryTests.RequiredNoIdentifiers threw exception:
1014 | System.ArgumentNullException: Value cannot be null.
1015 | Parameter name: encoding
1016 | Stack Trace:
1017 | at System.IO.StreamWriter..ctor(Stream stream, Encoding encoding, Int32 bufferSize, Boolean leaveOpen)

at Amazon.DynamoDBv2.Model.Internal.MarshallTransformations.CreateTableRequestMarshaller.Marshall(CreateTableRequest publicRequest) ins rc\aws-sdk-net\sdk\src\Services\DynamoDBv2\Generated\Model\Internal\MarshallTransformations\CreateTableRequestMarshaller.cs:line 68
--
1019 | at AWSSDK.UnitTests.EndpointDiscoveryTests.CreateExecutionContext(EndpointDiscoveryTestClient client, AmazonDynamoDBConfig config, Boolean required, SortedDictionary`2 identifiers) in src\aws-sdk-net\sdk\test\UnitTests\Custom\Runtime\EndpointDiscoveryTests.cs:line 374
1020 | at AWSSDK.UnitTests.EndpointDiscoveryTests.RequiredNoIdentifiers(String endpoint, String expectedEndpoint) in src2154271321\src\aws-sdk-net\sdk\test\UnitTests\Custom\Runtime\EndpointDiscoveryTests.cs:line 64

I haven't had the chance to investigate further yet.

@paulomorgado
Copy link
Author

@peterrsongg,

The change caused some existing unit tests to fail in our build system. I'll need to take a look at why this is the case

Is this something I can have a look at?

If you wanted to take a look that'd be great. I'm caught up in something else right now, but here are the failed tests

Are, by any chance, the tests failing only on .NET Framework?

Because MemoryStream allows to invoke ToArray() after being disposed, I've changed to use the StreamWriter(Stream) constructor, that closes the output stream, but uses UTF-8 with no BOM, which is what I intended to guarantee.

@peterrsongg
Copy link
Contributor

peterrsongg commented Aug 19, 2024

@peterrsongg,

The change caused some existing unit tests to fail in our build system. I'll need to take a look at why this is the case

Is this something I can have a look at?

If you wanted to take a look that'd be great. I'm caught up in something else right now, but here are the failed tests

Are, by any chance, the tests failing only on .NET Framework?

Because MemoryStream allows to invoke ToArray() after being disposed, I've changed to use the StreamWriter(Stream) constructor, that closes the output stream, but uses UTF-8 with no BOM, which is what I intended to guarantee.

Yup the tests are only failing in .NET Framework. Looks like your change addresses the issue. I'll run it through our system once more once you feel it is ready.

@paulomorgado
Copy link
Author

Yup the tests are only failing in .NET Framework. Looks like your change addresses the issue. I'll run it through our system once more once you feel it is ready.

Check if the new version passes all tests.

I haven't figured out how to run the code generation and tests.

@dscpinheiro
Copy link
Contributor

I'm running your latest commit through our build system. Can you also rebase your branch on top of v4-development? Your other PR (for the user-agent refactoring) was already merged, so it doesn't need to be included here.


We don't have a guide for external contributors yet, but this is how I usually make changes to the generator:

  • Open the generator\AWSSDKGenerator.sln solution and set ServiceClientGenerator as starting project
  • Update any .tt files (since you already modified JsonRPCRequestMarshaller.tt, you may have to right click -> Run Custom Tool in Visual Studio so that the code behind file - JsonRPCRequestMarshaller.cs - gets updated too)
  • Run the ServiceClientGenerator project
    • Since you're modifying marshallers, this will update a lot of generated files - you do not need to include them in PRs, our build system takes care of updating them

At this point, you should be able to open the sdk\AWSSDK.CoreAndCustomUnitTests.NetFramework.sln or sdk\AWSSDK.CoreAndCustomUnitTests.NetStandard.sln solutions and run their unit tests (note that the complete set of tests are in the sdk\AWSSDK.NetFramework.sln and sdk\AWSSDK.NetStandard.sln solutions but those include all services and aren't easy to work with locally).

paulomorgado and others added 4 commits August 20, 2024 13:52
Replaced StringWriter with MemoryStream and StreamWriter for JSON serialization to improve efficiency. JsonWriter is now initialized with StreamWriter. Adjusted indentation levels in ProcessStructure and ProcessMembers methods. Final request content is now obtained as a byte array from MemoryStream.
…nRPCRequestMarshaller.tt

Co-authored-by: Stuart Lang <stuart.b.lang@gmail.com>
…nRPCRequestMarshaller.tt

Co-authored-by: Stuart Lang <stuart.b.lang@gmail.com>
Refactor the instantiation of the `StreamWriter` object within a `using` statement by removing unnecessary parameters. The original code included `null` for encoding, `-1` for buffer size, and `true` for leaving the stream open. The updated code uses the default constructor, which only requires the `MemoryStream` object, as the default behavior is sufficient for the intended use case.
@paulomorgado
Copy link
Author

Hi @dscpinheiro,

I've rebased on v4-development.

It would be nice if building would run the templates.

Beware that there are NuGet packages with known vulnerabilities being referenced.

@normj
Copy link
Member

normj commented Aug 23, 2024

With this change we are losing the setting of CultureInfo.InvariantCulture as the IFormatProvider which was previously done with the StringWriter. There isn't a way to set the IFormatProvider directly on the StreamWriter. I'm wondering if we should create a subclass StreamWriter in Amazon.Runtime.Internal.Util so we can set the IFormatProvider and then reference that type instead of StreamWriter in the generated code. Something like this

public class InvariantCultureStreamWriter : StreamWriter
{
    public InvariantCultureStreamWriter (Stream stream)
        : base(stream)
    {
    }

    public override IFormatProvider FormatProvider
    {
        get
        {
            return CultureInfo.InvariantCulture;
        }
    }
}

@paulomorgado
Copy link
Author

@normj,

With this change we are losing the setting of CultureInfo.InvariantCulture as the IFormatProvider which was previously done with the StringWriter. There isn't a way to set the IFormatProvider directly on the StreamWriter. I'm wondering if we should create a subclass StreamWriter in Amazon.Runtime.Internal.Util so we can set the IFormatProvider and then reference that type instead of StreamWriter in the generated code. Something like this

public class InvariantCultureStreamWriter : StreamWriter
{
    public InvariantCultureStreamWriter (Stream stream)
        : base(stream)
    {
    }

    public override IFormatProvider FormatProvider
    {
        get
        {
            return CultureInfo.InvariantCulture;
        }
    }
}

Probably the safest option.

Have any of the tests failed? I thought this was used only with JSON and XML writers that already take care of this.

@normj
Copy link
Member

normj commented Aug 23, 2024

Have any of the tests failed? I thought this was used only with JSON and XML writers that already take care of this.

@peterrsongg and @dscpinheiro can speak for the state of the tests. They asked me to take pass because they were concerned about the CultureInfo.InvariantCulture change. It is possible the subclass is overkill but I'm not confident the LitJson JsonWriter handles everything as CultureInfo.InvariantCulture so I would rather play it safe.

@paulomorgado
Copy link
Author

Have any of the tests failed? I thought this was used only with JSON and XML writers that already take care of this.

@peterrsongg and @dscpinheiro can speak for the state of the tests. They asked me to take pass because they were concerned about the CultureInfo.InvariantCulture change. It is possible the subclass is overkill but I'm not confident the LitJson JsonWriter handles everything as CultureInfo.InvariantCulture so I would rather play it safe.

It's a safe and small overhead. Where do you want me to put it?

@dscpinheiro
Copy link
Contributor

None of the tests failed, but our integration tests do not validate different cultures at the moment.

You can put the file Norm mentioned in this location: https://github.com/aws/aws-sdk-net/tree/v4-development/sdk/src/Core/Amazon.Runtime/Internal/Util

@paulomorgado
Copy link
Author

paulomorgado commented Aug 23, 2024

None of the tests failed, but our integration tests do not validate different cultures at the moment.

You can put the file Norm mentioned in this location: https://github.com/aws/aws-sdk-net/tree/v4-development/sdk/src/Core/Amazon.Runtime/Internal/Util

Done!

Introduce InvariantCultureStreamWriter class to enforce invariant
culture formatting. Replace StreamWriter with
InvariantCultureStreamWriter in JsonRPCRequestMarshaller.tt to
ensure consistent JSON formatting regardless of system culture.
@dscpinheiro dscpinheiro merged commit 30f26e4 into aws:v4-development Aug 24, 2024
1 check passed
@paulomorgado paulomorgado deleted the performance/StringWriter branch August 27, 2024 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants