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

Improve binary size when using NativeAOT #1942

Open
roji opened this issue Mar 4, 2023 · 13 comments
Open

Improve binary size when using NativeAOT #1942

roji opened this issue Mar 4, 2023 · 13 comments
Labels
🙌 Up-for-Grabs Anyone interested in working on it can ask to be assigned

Comments

@roji
Copy link
Member

roji commented Mar 4, 2023

As pointed out by @vonzshik in #1941, a minimal SqlClient application weighs 45MB, which is quite a lot. For use in size-sensitive environments, it would be good to reduce this.

Note: this may be related to #1108 - the Azure-specific functionality is currently built-in, making it opt-in would also reduce binary size.

@vonzshik
Copy link

vonzshik commented Mar 4, 2023

Retested with .NET 8 preview 1, the size goes down to 29mb.

@kant2002
Copy link
Contributor

kant2002 commented Mar 5, 2023

From what I see there following offenders

image

  • System.Private.Xml
  • System.Text.Json

System.Private.Xml

This is coming from

else if (typeof(T) == typeof(XmlReader))
{
// XmlReader only allowed on XML types
if (metaData.metaType.SqlDbType != SqlDbType.Xml)
{
throw SQL.XmlReaderNotSupportOnColumnType(metaData.column);
}
if (IsCommandBehavior(CommandBehavior.SequentialAccess))
{
// Wrap the sequential stream in an XmlReader
_currentStream = new SqlSequentialStream(this, metaData.ordinal);
_lastColumnWithDataChunkRead = metaData.ordinal;
return (T)(object)SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(_currentStream, closeInput: true, async: isAsync);
}
else
{
if (data.IsNull)
{
// A 'null' stream
return (T)(object)SqlTypeWorkarounds.SqlXmlCreateSqlXmlReader(new MemoryStream(Array.Empty<byte>(), writable: false), closeInput: true, async: isAsync);
}
else
{
// Grab already read data
return (T)(object)data.SqlXml.CreateReader();
}
}
}

and from this place

SqlXml xmlValue = rawValue as SqlXml;
if (xmlValue != null)
{
if (xmlValue.IsNull)
{
rawValue = SqlString.Null;
}
else
{
rawValue = new SqlString(xmlValue.Value);
}
}

System.Text.Json

This one is a bit tricky, since it's indirectly referenced

Output of WhyDgml if interesting.

**** Match 1 ****
() System_Text_Json_System_Text_Json_Utf8JsonReader___ctor
  (call) System_Text_Json_System_Text_Json_JsonDocument__Parse
    (call) System_Text_Json_System_Text_Json_JsonDocument__Parse_5
      (call) System_Text_Json_System_Text_Json_JsonDocument__Parse_3
        (call) System_Text_Json_System_Text_Json_JsonDocument__Parse_4
          (call) Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken__ReadToken
            (Instance method on a constructed type) (Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken__ReadToken, ??_7Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken@@6B@ constructed)
              (Primary) Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken__ReadToken
                (call) Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken___ctor
                  (Instance method on a constructed type) (Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken___ctor, ??_7Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken@@6B@ constructed)
                    (Primary) Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebToken___ctor
                      (newobj) Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler__ReadJsonWebToken
                        (Instance method on a constructed type) (Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler__ReadJsonWebToken, ??_7Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler@@6B@ constructed)
                          (Primary) Tentative instance method: Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler__ReadJsonWebToken
                            (Virtual method) (??_7Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler@@6B@ constructed, VirtualMethodUse [Microsoft.IdentityModel.JsonWebTokens]Microsoft.IdentityModel.JsonWebTokens.JsonWebTokenHandler.ReadJsonWebToken(string))
                              (Primary) ??_7Microsoft_IdentityModel_JsonWebTokens_Microsoft_IdentityModel_JsonWebTokens_JsonWebTokenHandler@@6B@ constructed
                                (newobj) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__ValidateAttestationClaims
                                  (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__ValidateAttestationClaims, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider@@6B@ constructed)
                                    (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__ValidateAttestationClaims
                                      (call) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__VerifyAzureAttestationInfo
                                        (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__VerifyAzureAttestationInfo, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider@@6B@ constructed)
                                          (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__VerifyAzureAttestationInfo
                                            (call) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__CreateEnclaveSession
                                              (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__CreateEnclaveSession, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider@@6B@ constructed)
                                                (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider__CreateEnclaveSession
                                                  (Virtual method) (??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider@@6B@ constructed, VirtualMethodUse [Microsoft.Data.SqlClient]Microsoft.Data.SqlClient.SqlColumnEncryptionEnclaveProvider.CreateEnclaveSession(uint8[],ECDiffieHellman,EnclaveSessionParameters,uint8[],int32,SqlEnclaveSession&,int64&))
                                                    (Primary) ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_AzureAttestationEnclaveProvider@@6B@ constructed
                                                      (newobj) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__GetEnclaveProvider
                                                        (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__GetEnclaveProvider, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate@@6B@ constructed)
                                                          (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__GetEnclaveProvider
                                                            (call) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__InvalidateEnclaveSession
                                                              (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__InvalidateEnclaveSession, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate@@6B@ constructed)
                                                                (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_EnclaveDelegate__InvalidateEnclaveSession
                                                                  (callvirt) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlCommand__RunExecuteReader_0
                                                                    (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlCommand__RunExecuteReader_0, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlCommand@@6B@ constructed)
                                                                      (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlCommand__RunExecuteReader_0

Also from authentication here

if (parameters.AuthenticationMethod == SqlAuthenticationMethod.ActiveDirectoryDefault)
{
DefaultAzureCredentialOptions defaultAzureCredentialOptions = new()
{
AuthorityHost = new Uri(authority),
SharedTokenCacheTenantId = audience,
VisualStudioCodeTenantId = audience,
VisualStudioTenantId = audience,
ExcludeInteractiveBrowserCredential = true // Force disabled, even though it's disabled by default to respect driver specifications.
};
// Optionally set clientId when available
if (clientId is not null)
{
defaultAzureCredentialOptions.ManagedIdentityClientId = clientId;
defaultAzureCredentialOptions.SharedTokenCacheUsername = clientId;
}
AccessToken accessToken = await new DefaultAzureCredential(defaultAzureCredentialOptions).GetTokenAsync(tokenRequestContext, cts.Token).ConfigureAwait(false);
SqlClientEventSource.Log.TryTraceEvent("AcquireTokenAsync | Acquired access token for Default auth mode. Expiry Time: {0}", accessToken.ExpiresOn);
return new SqlAuthenticationToken(accessToken.Token, accessToken.ExpiresOn);
}

Output of WhyDgml if interesting.


**** Match 1 ****
() ??_7System_Text_Json_System_Text_Json_Utf8JsonWriter@@6B@ constructed
  (newobj) System_Text_Json_System_Text_Json_Nodes_JsonNode__ToString
    (Instance method on a constructed type) (Tentative instance method: System_Text_Json_System_Text_Json_Nodes_JsonNode__ToString, ??_7System_Text_Json_System_Text_Json_Nodes_JsonNode@@6B@ constructed)
      (Primary) Tentative instance method: System_Text_Json_System_Text_Json_Nodes_JsonNode__ToString
        (Virtual method) (??_7System_Text_Json_System_Text_Json_Nodes_JsonNode@@6B@ constructed, VirtualMethodUse object.ToString())
          (Primary) ??_7System_Text_Json_System_Text_Json_Nodes_JsonNode@@6B@ constructed
            (Dictionary dependency) [System.Text.Json]System.Text.Json.Serialization.JsonConverter`1<System.Text.Json.Nodes.JsonNode>.TryRead(Utf8JsonReader&,Type,JsonSerializerOptions,ReadStack&,JsonNode&) backed by System_Text_Json_System_Text_Json_Serialization_JsonConverter_1<System___Canon>__TryRead
              (Generic dictionary dependency) (__GenericDict_System_Text_Json_System_Text_Json_Serialization_JsonConverter_1<System_Text_Json_System_Text_Json_Nodes_JsonNode>, System_Text_Json_System_Text_Json_Serialization_JsonConverter_1<System___Canon>__TryRead)
                (Primary) __GenericDict_System_Text_Json_System_Text_Json_Serialization_JsonConverter_1<System_Text_Json_System_Text_Json_Nodes_JsonNode>
                  (reloc) ??_7System_Text_Json_System_Text_Json_Serialization_Converters_JsonNodeConverter@@6B@ constructed
                    (newobj) System_Text_Json_System_Text_Json_Serialization_Converters_JsonNodeConverter__get_Instance
                      (call) System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter__Read
                        (Instance method on a constructed type) (Tentative instance method: System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter__Read, ??_7System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter@@6B@ constructed)
                          (Primary) Tentative instance method: System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter__Read
                            (Virtual method) (??_7System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter@@6B@ constructed, VirtualMethodUse [System.Text.Json]System.Text.Json.Serialization.JsonConverter`1<object>.Read(Utf8JsonReader&,Type,JsonSerializerOptions))
                              (Primary) ??_7System_Text_Json_System_Text_Json_Serialization_Converters_ObjectConverter@@6B@ constructed
                                (newobj) System_Text_Json_System_Text_Json_Serialization_Metadata_JsonMetadataServices__get_ObjectConverter
                                  (call) System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver__GetDefaultSimpleConverters
                                    (call) System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver___ctor_0
                                      (Instance method on a constructed type) (Tentative instance method: System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver___ctor_0, ??_7System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver@@6B@ constructed)
                                        (Primary) Tentative instance method: System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver___ctor_0
                                          (newobj) System_Text_Json_System_Text_Json_Serialization_Metadata_DefaultJsonTypeInfoResolver__RootDefaultInstance
                                            (call) System_Text_Json_System_Text_Json_JsonSerializerOptions__InitializeForReflectionSerializer
                                              (Instance method on a constructed type) (Tentative instance method: System_Text_Json_System_Text_Json_JsonSerializerOptions__InitializeForReflectionSerializer, ??_7System_Text_Json_System_Text_Json_JsonSerializerOptions@@6B@ constructed)
                                                (Primary) Tentative instance method: System_Text_Json_System_Text_Json_JsonSerializerOptions__InitializeForReflectionSerializer
                                                  (callvirt) System_Text_Json_System_Text_Json_JsonSerializer__GetTypeInfo
                                                    (call) System_Text_Json_System_Text_Json_JsonSerializer__Deserialize_19<System___Canon>
                                                      (call) Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics__ExtractAzureErrorContent
                                                        (call) Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics__ExtractFailureContent
                                                          (Instance method on a constructed type) (Tentative instance method: Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics__ExtractFailureContent, ??_7Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics@@6B@ constructed)
                                                            (Primary) Tentative instance method: Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics__ExtractFailureContent
                                                              (Virtual method) (??_7Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics@@6B@ constructed, VirtualMethodUse [Azure.Identity]Azure.Core.Pipeline.ClientDiagnostics.ExtractFailureContent(string,ResponseHeaders,IDictionary`2<string,string>&))
                                                                (Primary) ??_7Azure_Identity_Azure_Core_Pipeline_ClientDiagnostics@@6B@ constructed
                                                                  (newobj) Azure_Identity_Azure_Identity_CredentialPipeline___ctor
                                                                    (Instance method on a constructed type) (Tentative instance method: Azure_Identity_Azure_Identity_CredentialPipeline___ctor, ??_7Azure_Identity_Azure_Identity_CredentialPipeline@@6B@ constructed)
                                                                      (Primary) Tentative instance method: Azure_Identity_Azure_Identity_CredentialPipeline___ctor
                                                                        (newobj) Azure_Identity_Azure_Identity_CredentialPipeline__GetInstance
                                                                          (call) Azure_Identity_Azure_Identity_ManagedIdentityCredential___ctor_0
                                                                            (Instance method on a constructed type) (Tentative instance method: Azure_Identity_Azure_Identity_ManagedIdentityCredential___ctor_0, ??_7Azure_Identity_Azure_Identity_ManagedIdentityCredential@@6B@ constructed)
                                                                              (Primary) Tentative instance method: Azure_Identity_Azure_Identity_ManagedIdentityCredential___ctor_0
                                                                                (newobj) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync_d__17__MoveNext
                                                                                  (callvirt) S_P_CoreLib_System_Runtime_CompilerServices_AsyncMethodBuilderCore__Start<Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync_d__17>
                                                                                    (call) S_P_CoreLib_System_Runtime_CompilerServices_AsyncTaskMethodBuilder_1<System___Canon>__Start<Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync_d__17>
                                                                                      (call) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync
                                                                                        (Instance method on a constructed type) (Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync, ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider@@6B@ constructed)
                                                                                          (Primary) Tentative instance method: Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider__AcquireTokenAsync
                                                                                            (Virtual method) (??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider@@6B@ constructed, VirtualMethodUse [Microsoft.Data.SqlClient]Microsoft.Data.SqlClient.SqlAuthenticationProvider.AcquireTokenAsync(SqlAuthenticationParameters))
                                                                                              (Primary) ??_7Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_ActiveDirectoryAuthenticationProvider@@6B@ constructed
                                                                                                (newobj) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlAuthenticationProviderManager__SetDefaultAuthProviders
                                                                                                  (call) Microsoft_Data_SqlClient_Microsoft_Data_SqlClient_SqlAuthenticationProviderManager___cctor

Ideas

For me, most easier way to reduce size of NativeAOT executable to exclude support for Xml columns by default via AppContextSwitch or at make it opt-out of Xml support. I maybe wrong, but Xml is not that important now for workloads which most likely adopt NativeAOT, but I may be wrong.

If Azure-related stuff can be make opt-in that I can take a look at other places and provide more info since I think there more places which related to Azure which can be rooted-out.

@roji
Copy link
Member Author

roji commented Mar 5, 2023

For those interested, npgsql/npgsql#4965 tracks one of the main approaches to reduce size in Npgsql. In a nutshell, this leverages the new DbDataSource abstraction from .NET 6.0 to allow users to start with only the basic featureset, and opt into specific required features in granular fashion. The fact that this is done via a new builder maintains 100% backwards compatibility.

@kant2002
Copy link
Contributor

kant2002 commented Mar 5, 2023

case SqlConnectionAttestationProtocol.HGS:
HostGuardianServiceEnclaveProvider hostGuardianServiceEnclaveProvider = new HostGuardianServiceEnclaveProvider();
s_enclaveProviders[attestationProtocol] = hostGuardianServiceEnclaveProvider;
sqlColumnEncryptionEnclaveProvider = s_enclaveProviders[attestationProtocol];
break;

This class brings System.Runtime.Serialization.Json which to my surprise uses System.Private.Xml.

Also AzureAttestationEnclaveProvider bring dependency on Microsoft.IdentityModel.Json.JsonSerializer which for unkown for me reasons also like to deserialize XML.

Other questionable dependency is ConfigurationManager usage from these places where it can be disabled using AppConfig switch.

public static T FetchConfigurationSection<T>(string name)
{
string methodName = MethodBase.GetCurrentMethod().Name;
object section = null;
try
{
section = ConfigurationManager.GetSection(name);
}

private static T FetchConfigurationSection<T>(string name)
{
Type t = typeof(T);
object section = ConfigurationManager.GetSection(name);
if (null != section)

and also hard dependency on ConfigurationManager is here.

Same for EnclaveProviderBase which also has instantiation of MemoryCache. After couple more attemps I see MemoryCache everywhere and I think I should get rid of dependency on ConfigurationManager in that class first. Otherwise nothing really can be done here.

At max I was able to remove 0.5Mb from original 25.8Mb using nighlty .NET 8 ILC when attempt to disable XML support.
If I nuke enclave support I would be able reclaim up to 2.7Mb by disabling enclave support here (for experiments only)
https://github.com/dotnet/SqlClient/blob/73c6b2ff3ef3b55431cf187e72d5de918caccf76/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/EnclaveDelegate.Crypto.cs#LL86

@lcheunglci lcheunglci added this to Needs triage in SqlClient Triage Board via automation Mar 6, 2023
@lcheunglci lcheunglci moved this from Needs triage to Ideas for Future in SqlClient Triage Board Mar 7, 2023
@lcheunglci lcheunglci added 🙌 Up-for-Grabs Anyone interested in working on it can ask to be assigned and removed untriaged labels Mar 7, 2023
@roji
Copy link
Member Author

roji commented Mar 7, 2023

@kant2002 I think that rather than introducing feature switches to strip out ConfigurationManager (and other similar blocks), a better overall approach would be to introduce a new entry point where ConfigurationManager simply isn't used by default (this is the "slim" data source builder approach I mentioned in my comment above). This means that for regular users not concerned with size, the current APIs continue to work exactly as they do today, but those concerned with perf can use the new entry point, and opt only into what they want.

This kind of approach would also handle things like Azure.Identity, which you can't really put behind a feature switch but still need to solve.

@kant2002
Copy link
Contributor

kant2002 commented Mar 7, 2023

@roji I did not ignore your comment about "slim" data source builder. I clearly see other locations where it 100% would be working solution. I'm not so sure about ConfigurationManager. Look at the usages of System.Runtime.Caching.MemoryCache which bring ConfigurationManager dependency internally. https://github.com/search?q=repo%3Adotnet%2FSqlClient%20MemoryCache&type=code
All places except first one from addon folder (which use M.E.Caching.Memory) uses that compatibility class.

So I still have questions what to do. Replace S.R.Cachine.MemoryCache usage with M.E.Caching.Memory.MemoryCache?

  • Does that acceptable solution for NetFx?
  • Does switching dependency reduce code size? I can measure that if that solution has a chance to land this repo.

@roji
Copy link
Member Author

roji commented Mar 7, 2023

So I still have questions what to do. Replace S.R.Cachine.MemoryCache usage with M.E.Caching.Memory.MemoryCache?

I don't know enough about the differences here, but that definitely could be a way forward... If that eliminates the dependency on ConfigurationManager, that possibly also means that existing settings in App.config (around cache size?) would no longer be respected - I'm guessing all that would have to be clarified.

@kant2002
Copy link
Contributor

kant2002 commented Mar 7, 2023

In addition to MemoryCache, ConfigurationManager also used in couple places in codebase https://github.com/search?q=repo%3Adotnet%2FSqlClient+ConfigurationManager+language%3AC%23&type=code&l=C%23 but unfortunately ConfigurationManager still across all samples folder. So changing samples potentially additional work item here.

@Wraith2
Copy link
Contributor

Wraith2 commented Mar 7, 2023

What are we using MemoryCache for anyway? And how is DataContractSerialization being used?

@kant2002
Copy link
Contributor

kant2002 commented Mar 7, 2023

@Wraith2 you can take a look at search results here. It's used in relatively lot of places. Session caches, query metadata caches, key caches, And theoretically it can be configured via app.config/web.config - that's feature of S.R.Caching.MemoryCache.

@kant2002
Copy link
Contributor

kant2002 commented Mar 7, 2023

DataContractSerialization is coming from HostGuardianServiceEnclaveProvider here

var deserializer = new DataContractJsonSerializer(typeof(byte[]));

@Wraith2 Wraith2 mentioned this issue Mar 8, 2023
@Wraith2
Copy link
Contributor

Wraith2 commented Mar 21, 2023

@David-Engel is there a spec that defines what is going to come back from the call made in

using (Stream stream = s_client.GetStreamAsync(url).ConfigureAwait(false).GetAwaiter().GetResult())
{
var deserializer = new DataContractJsonSerializer(typeof(byte[]));
return (byte[])deserializer.ReadObject(stream);
}

If it's well defined we can easily write our own deserialization code rather than use the DataContractDeserializer.

@David-Engel
Copy link
Contributor

If it's well defined we can easily write our own deserialization code rather than use the DataContractDeserializer.

@Wraith2 I'm not sure. But maybe this one?
https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-hgsa/7730337b-53d6-4f83-bc76-a156c3cfd342

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🙌 Up-for-Grabs Anyone interested in working on it can ask to be assigned
Projects
SqlClient Triage Board
  
Ideas for Future
Development

No branches or pull requests

6 participants