未验证 提交 3e03eda5 编写于 作者: E Eirik Tsarpalis 提交者: GitHub

Recoup some of the perf losses in cold start serialization. (#73497)

上级 4734ee0a
......@@ -91,15 +91,19 @@ private static bool HasCustomAttributeWithName(this ICustomAttributeProvider mem
/// <summary>
/// Polyfill for BindingFlags.DoNotWrapExceptions
/// </summary>
public static object? InvokeNoWrapExceptions(this MethodInfo methodInfo, object? obj, object?[] parameters)
public static object? CreateInstanceNoWrapExceptions(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.NonPublicConstructors)] this Type type,
Type[] parameterTypes,
object?[] parameters)
{
ConstructorInfo ctorInfo = type.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, parameterTypes, null)!;
#if NETCOREAPP
return methodInfo.Invoke(obj, BindingFlags.DoNotWrapExceptions, null, parameters, null);
return ctorInfo.Invoke(BindingFlags.DoNotWrapExceptions, null, parameters, null);
#else
object? result = null;
try
{
result = methodInfo.Invoke(obj, parameters);
result = ctorInfo.Invoke(parameters);
}
catch (TargetInvocationException ex)
{
......
......@@ -69,6 +69,22 @@ public abstract partial class JsonConverter
throw new InvalidOperationException();
}
[RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
[RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
internal virtual JsonTypeInfo CreateReflectionJsonTypeInfo(JsonSerializerOptions options)
{
Debug.Fail("Should not be reachable.");
throw new InvalidOperationException();
}
internal virtual JsonTypeInfo CreateCustomJsonTypeInfo(JsonSerializerOptions options)
{
Debug.Fail("Should not be reachable.");
throw new InvalidOperationException();
}
internal abstract JsonParameterInfo CreateJsonParameterInfo();
internal abstract JsonConverter<TTarget> CreateCastingConverter<TTarget>();
......
......@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization.Converters;
using System.Text.Json.Serialization.Metadata;
......@@ -67,6 +68,18 @@ public override bool CanConvert(Type typeToConvert)
internal override ConverterStrategy ConverterStrategy => ConverterStrategy.Value;
[RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
[RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
internal sealed override JsonTypeInfo CreateReflectionJsonTypeInfo(JsonSerializerOptions options)
{
return new ReflectionJsonTypeInfo<T>(this, options);
}
internal sealed override JsonTypeInfo CreateCustomJsonTypeInfo(JsonSerializerOptions options)
{
return new CustomJsonTypeInfo<T>(this, options);
}
internal sealed override JsonParameterInfo CreateJsonParameterInfo()
{
return new JsonParameterInfo<T>();
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json.Serialization.Converters;
namespace System.Text.Json.Serialization.Metadata
{
......
......@@ -2,8 +2,8 @@
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text.Json.Reflection;
using System.Threading;
......@@ -85,20 +85,26 @@ public virtual JsonTypeInfo GetTypeInfo(Type type, JsonSerializerOptions options
[RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
private static JsonTypeInfo CreateJsonTypeInfo(Type type, JsonSerializerOptions options)
{
s_createReflectionJsonTypeInfoMethodInfo ??= typeof(DefaultJsonTypeInfoResolver).GetMethod(nameof(CreateReflectionJsonTypeInfo), BindingFlags.NonPublic | BindingFlags.Static)!;
return (JsonTypeInfo)s_createReflectionJsonTypeInfoMethodInfo.MakeGenericMethod(type)
.InvokeNoWrapExceptions(null, new object[] { options })!;
}
JsonTypeInfo jsonTypeInfo;
JsonConverter converter = GetConverterForType(type, options);
[RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
[RequiresDynamicCode(JsonSerializer.SerializationRequiresDynamicCodeMessage)]
private static JsonTypeInfo<T> CreateReflectionJsonTypeInfo<T>(JsonSerializerOptions options)
{
JsonConverter converter = GetConverterForType(typeof(T), options);
return new ReflectionJsonTypeInfo<T>(converter, options);
}
if (converter.TypeToConvert == type)
{
// For performance, avoid doing a reflection-based instantiation
// if the converter type matches that of the declared type.
jsonTypeInfo = converter.CreateReflectionJsonTypeInfo(options);
}
else
{
Type jsonTypeInfoType = typeof(ReflectionJsonTypeInfo<>).MakeGenericType(type);
jsonTypeInfo = (JsonTypeInfo)jsonTypeInfoType.CreateInstanceNoWrapExceptions(
parameterTypes: new Type[] { typeof(JsonConverter), typeof(JsonSerializerOptions) },
parameters: new object[] { converter, options })!;
}
private static MethodInfo? s_createReflectionJsonTypeInfoMethodInfo;
Debug.Assert(jsonTypeInfo.Type == type);
return jsonTypeInfo;
}
/// <summary>
/// Gets a list of user-defined callbacks that can be used to modify the initial contract.
......
......@@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text.Json.Reflection;
......@@ -56,7 +55,7 @@ public abstract partial class JsonTypeInfo
[RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)]
internal JsonPropertyInfo CreatePropertyUsingReflection(Type propertyType)
{
JsonPropertyInfo? jsonPropertyInfo;
JsonPropertyInfo jsonPropertyInfo;
if (Options.TryGetTypeInfoCached(propertyType, out JsonTypeInfo? jsonTypeInfo))
{
......@@ -69,9 +68,10 @@ internal JsonPropertyInfo CreatePropertyUsingReflection(Type propertyType)
{
// Metadata for `propertyType` has not been registered yet.
// Use reflection to instantiate the correct JsonPropertyInfo<T>
s_createJsonPropertyInfo ??= typeof(JsonTypeInfo).GetMethod(nameof(CreateJsonPropertyInfo), BindingFlags.NonPublic | BindingFlags.Static)!;
jsonPropertyInfo = (JsonPropertyInfo)s_createJsonPropertyInfo.MakeGenericMethod(propertyType)
.InvokeNoWrapExceptions(null, new object[] { this, Options })!;
Type propertyInfoType = typeof(JsonPropertyInfo<>).MakeGenericType(propertyType);
jsonPropertyInfo = (JsonPropertyInfo)propertyInfoType.CreateInstanceNoWrapExceptions(
parameterTypes: new Type[] { typeof(Type), typeof(JsonTypeInfo), typeof(JsonSerializerOptions) },
parameters: new object[] { Type, this, Options })!;
}
Debug.Assert(jsonPropertyInfo.PropertyType == propertyType);
......@@ -83,11 +83,6 @@ internal JsonPropertyInfo CreatePropertyUsingReflection(Type propertyType)
/// </summary>
private protected abstract JsonPropertyInfo CreateJsonPropertyInfo(JsonTypeInfo declaringTypeInfo, JsonSerializerOptions options);
private static JsonPropertyInfo CreateJsonPropertyInfo<T>(JsonTypeInfo declaringTypeInfo, JsonSerializerOptions options)
=> new JsonPropertyInfo<T>(declaringTypeInfo.Type, declaringTypeInfo, options);
private static MethodInfo? s_createJsonPropertyInfo;
// AggressiveInlining used although a large method it is only called from one location and is on a hot path.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal JsonPropertyInfo GetProperty(
......
......@@ -4,7 +4,6 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.ExceptionServices;
using System.Text.Json.Reflection;
......@@ -634,8 +633,6 @@ public static JsonTypeInfo<T> CreateJsonTypeInfo<T>(JsonSerializerOptions option
return new CustomJsonTypeInfo<T>(converter, options);
}
private static MethodInfo? s_createJsonTypeInfo;
/// <summary>
/// Creates a blank <see cref="JsonTypeInfo"/> instance.
/// </summary>
......@@ -673,9 +670,25 @@ public static JsonTypeInfo CreateJsonTypeInfo(Type type, JsonSerializerOptions o
ThrowHelper.ThrowArgumentException_CannotSerializeInvalidType(nameof(type), type, null, null);
}
s_createJsonTypeInfo ??= typeof(JsonTypeInfo).GetMethod(nameof(CreateJsonTypeInfo), new Type[] { typeof(JsonSerializerOptions) })!;
return (JsonTypeInfo)s_createJsonTypeInfo.MakeGenericMethod(type)
.InvokeNoWrapExceptions(null, new object[] { options })!;
JsonTypeInfo jsonTypeInfo;
JsonConverter converter = DefaultJsonTypeInfoResolver.GetConverterForType(type, options, resolveJsonConverterAttribute: false);
if (converter.TypeToConvert == type)
{
// For performance, avoid doing a reflection-based instantiation
// if the converter type matches that of the declared type.
jsonTypeInfo = converter.CreateCustomJsonTypeInfo(options);
}
else
{
Type jsonTypeInfoType = typeof(CustomJsonTypeInfo<>).MakeGenericType(type);
jsonTypeInfo = (JsonTypeInfo)jsonTypeInfoType.CreateInstanceNoWrapExceptions(
parameterTypes: new Type[] { typeof(JsonConverter), typeof(JsonSerializerOptions) },
parameters: new object[] { converter, options })!;
}
Debug.Assert(jsonTypeInfo.Type == type);
return jsonTypeInfo;
}
/// <summary>
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text.Json.Reflection;
namespace System.Text.Json.Serialization.Metadata
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册