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

Make TypeDescriptor thread safe with custom providers by enlarging lock region #92521

Closed
wants to merge 13 commits into from

Conversation

karakasa
Copy link
Contributor

@karakasa karakasa commented Sep 23, 2023

Summary

Fix #92394 and add a test.

see comment for the reason of race conditions.

The fix is conservative as it just extends the range of lock statement. If the performance decrease in this PR is acceptable, I would recommend enlarging lock region because it is unlikely to result in bugs.

I did code another aggressive approach (#92548) that minimizes lock use but it seems causing stack overflow in certain conditions so I'm not gonna PR that.

Risk

There would be performance impact due to the extended use of lock.

The bottleneck would be querying many to-be-created TypeDescriptionNodes at the same time - as they are forced to be created one by one - which may decrease startup perf. Otherwise the impact should be minimal because most queries quit at the first if block.

@ghost ghost added the community-contribution Indicates that the PR has been added by a community member label Sep 23, 2023
@ghost
Copy link

ghost commented Sep 23, 2023

Tagging subscribers to this area: @dotnet/area-system-componentmodel
See info in area-owners.md if you want to be subscribed.

Issue Details

Fix #92394 and add a test.

Author: karakasa
Assignees: -
Labels:

area-System.ComponentModel

Milestone: -

@karakasa karakasa changed the title Make TypeDescriptor.GetProperties thread safe Make TypeDescriptor thread safe Sep 23, 2023
@karakasa karakasa changed the title Make TypeDescriptor thread safe Make TypeDescriptor thread safe with custom providers Sep 23, 2023
Originally a race condition exists in `CheckDefaultProvider` and leads
to wrong results when many methods are called simultaneously.

The PR fixes that by extending the lock statement.

Fix dotnet#92934
to wrong results when many methods are called simultaneously.

The PR fixes that by extending the lock statement.

Fix dotnet#92394
@karakasa karakasa marked this pull request as ready for review September 23, 2023 10:50
@karakasa karakasa changed the title Make TypeDescriptor thread safe with custom providers Make TypeDescriptor thread safe with custom providers by enlaring lock region Sep 24, 2023
@karakasa karakasa changed the title Make TypeDescriptor thread safe with custom providers by enlaring lock region Make TypeDescriptor thread safe with custom providers by enlarging lock region Sep 24, 2023
@steveharter
Copy link
Member

This touches the same files as the closed PR https://github.com/dotnet/runtime/pull/85156/files for issue #30024. It was closed since it didn't make sense to force this potentially risky issue late into v8.0. Both issues appear to be the same root cause around using the hashtable in s_defaultProviders, but have different use cases so it makes sense to keep open both issues for now.

Performance here will suffer quite a bit - because of the lock area expanding as well as the use of GetCustomAttributes(). The other PR should be used as a reference implementation to address perf, but there may be other ways to address the issues without the extensive changes there and added use the Environment.CurrentManagedThreadId.

@steveharter steveharter self-requested a review September 27, 2023 21:21
@karakasa karakasa marked this pull request as draft September 28, 2023 03:24
@karakasa karakasa marked this pull request as ready for review September 29, 2023 05:25
@karakasa karakasa marked this pull request as draft October 20, 2023 01:37
public int OneProperty { get; set; }
}
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Do you think the tests at https://github.com/dotnet/runtime/pull/85156/files#diff-13f56d055c80679284090c59b45d396ab44378385c1f7ad0b597eec15fa5cf0fR813-R909 add any value here?

FWIW locally I added those tests to this file, and ran them in loop for 200 times are no issues were found.

Copy link
Contributor Author

@karakasa karakasa Nov 15, 2023

Choose a reason for hiding this comment

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

The other tests are not fundamentally different - but I add them if they produce errors on your computer and they don't use Thread (compared to my tests), which is unsupported on browsers.

Nevertheless, both mine and the other tests failed on my PC. Can the issue be platform-specific?

test log
✘ System.ComponentModel.Tests.TypeDescriptorTests.GetConverterWithAddProvider_ByMultithread_Success(typeForGetConverter: typeof(System.ComponentModel.Tests.TypeDescriptorTests+MyClass), expectedConverterType: typeof(System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter))​5ms
Error:
Assert.All() Failure: 1 out of 200 items in the collection did not pass.
[2]: Item: System.ComponentModel.TypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Actual:   System.ComponentModel.TypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69

Stack trace:
   at System.ComponentModel.Tests.TypeDescriptorTests.GetConverterWithAddProvider_ByMultithread_Success(Type typeForGetConverter, Type expectedConverterType) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1370
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state) in D:\repos\karakasa\runtime\src\libraries\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs:line 1914

✘ System.ComponentModel.Tests.TypeDescriptorTests.GetConverterWithAddProvider_ByMultithread_Success(typeForGetConverter: typeof(System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProvider), expectedConverterType: typeof(System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter))​2ms
Error:
Assert.All() Failure: 11 out of 200 items in the collection did not pass.
[11]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
      Xunit.Sdk.IsTypeException: Assert.IsType() Failure
      Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
      Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
         at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
         at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
         at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
         at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[10]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
      Xunit.Sdk.IsTypeException: Assert.IsType() Failure
      Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
      Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
         at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
         at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
         at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
         at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[9]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[8]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[7]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[6]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[5]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[4]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[3]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[2]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69
[0]: Item: System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
     Xunit.Sdk.IsTypeException: Assert.IsType() Failure
     Expected: System.ComponentModel.Tests.TypeDescriptorTests+MyInheritedClassWithCustomTypeDescriptionProviderConverter
     Actual:   System.ComponentModel.Tests.TypeDescriptorTests+MyTypeConverter
        at Xunit.Assert.IsType(Type expectedType, Object object) in /_/src/Microsoft.DotNet.XUnitAssert/src/TypeAsserts.cs:line 140
        at System.ComponentModel.Tests.TypeDescriptorTests.<>c__DisplayClass80_0.<GetConverterWithAddProvider_ByMultithread_Success>b__0(TypeConverter currentConverter) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1371
        at Xunit.Assert.<>c__DisplayClass11_0`1.<All>b__0(T item, Int32 index) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 40
        at Xunit.Assert.All[T](IEnumerable`1 collection, Action`2 action) in /_/src/Microsoft.DotNet.XUnitAssert/src/CollectionAsserts.cs:line 69

Stack trace:
   at System.ComponentModel.Tests.TypeDescriptorTests.GetConverterWithAddProvider_ByMultithread_Success(Type typeForGetConverter, Type expectedConverterType) in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1370
   at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__128_0(Object state) in D:\repos\karakasa\runtime\src\libraries\System.Private.CoreLib\src\System\Threading\Tasks\Task.cs:line 1914

✘ System.ComponentModel.Tests.TypeDescriptorTests.GetProperties_ReturnsExpected​25ms
Error:
Fallback type descriptor is used. Possible race condition.
Expected: False
Actual:   True

Stack trace:
   at System.ComponentModel.Tests.TypeDescriptorTests.GetProperties_ReturnsExpected() in D:\repos\karakasa\runtime\src\libraries\System.ComponentModel.TypeConverter\tests\TypeDescriptorTests.cs:line 1287
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
   at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args) in D:\repos\karakasa\runtime\src\coreclr\System.Private.CoreLib\src\System\Reflection\MethodBaseInvoker.CoreCLR.cs:line 36
   at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) in D:\repos\karakasa\runtime\src\libraries\System.Private.CoreLib\src\System\Reflection\MethodBaseInvoker.cs:line 57

Copy link
Member

@steveharter steveharter left a comment

Choose a reason for hiding this comment

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

Left some comments in the test file.

@ghost ghost added the needs-author-action An issue or pull request that requires more info or actions from the author. label Oct 20, 2023
@steveharter
Copy link
Member

Note the PR is still marked as Draft.

@karakasa
Copy link
Contributor Author

karakasa commented Oct 25, 2023

Note the PR is still marked as Draft.

I am testing on adding another HashTable to reduce lock. Will mark the PR as ready once I decide whether to add the extra hashtable. Do you have thoughts on this?

I will also check the extra tests, thank you.

public sealed class TypeDescriptor
{

....

    private static readonly Hashtable s_defaultProviders = new Hashtable();
    private static readonly Hashtable s_defaultProvidersCreated = new Hashtable();

....

    private static void CheckDefaultProvider(Type type)
    {
        bool providerAdded = false;
    
        if (s_defaultProvidersCreated.ContainsKey(type))
        {
            return;
        }
    
        lock (s_internalSyncObject)
        {
            if (s_defaultProviders.ContainsKey(type))
            {
                return;
            }
    
            object[] attrs = type.GetCustomAttributes(typeof(TypeDescriptionProviderAttribute), false);
            for (int idx = attrs.Length - 1; idx >= 0; idx--)
            {
                ....
            }
    
            s_defaultProvidersCreated[type] = null;
        }
    
        ....
    }

....

}

@ghost ghost removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Oct 25, 2023
karakasa and others added 2 commits November 15, 2023 22:47
Moved tests to the main testing file
Adopted tests from dotnet#85156

Co-authored-by: Maximys <mixim33@yandex.ru>
@karakasa
Copy link
Contributor Author

karakasa commented Nov 15, 2023

latest benchmark with an extra hashtable to reduce locks. The perf is on par with the main repo.

BenchmarkDotNet v0.13.8, Windows 10 (10.0.19045.2546/22H2/2022Update)
Intel Core i7-8700K CPU 3.70GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores
.NET SDK 8.0.100-rc.2.23502.2
  [Host]     : .NET 8.0.0 (8.0.23.47906), X64 RyuJIT AVX2
  Job-IOOUIL : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2
  Job-QTNBWJ : .NET 9.0.0 (42.42.42.42424), X64 RyuJIT AVX2
Method Toolchain Mean Error StdDev Ratio Gen0 Gen1 Gen2 Allocated Alloc Ratio
MultipleThreads main 1,987.632 μs 14.8732 μs 13.9124 μs 1.00 35.1563 7.8125 7.8125 10.39 KB 1.00
MultipleThreads pr 1,959.046 μs 21.4355 μs 20.0508 μs 0.99 35.1563 7.8125 7.8125 10.39 KB 1.00
SingleThread main 5.042 μs 0.0173 μs 0.0145 μs 1.00 0.3052 - - 1.92 KB 1.00
SingleThread pr 5.061 μs 0.0664 μs 0.0621 μs 1.00 0.3052 - - 1.92 KB 1.00

@karakasa karakasa marked this pull request as ready for review November 15, 2023 16:10
@karakasa karakasa marked this pull request as draft November 16, 2023 02:21
ConcurrentGetProperties_ReturnsExpected
is skipped on browsers because Thread.Start
is unsupported.
@ericstj
Copy link
Member

ericstj commented Dec 12, 2023

Before seeing this PR I happened to be looking at this problem and made a suggestion in #30024. I think that suggestion could be considered here as a slight alternative to what's been implemented so far.

@steveharter
Copy link
Member

steveharter commented Jan 11, 2024

Replaced by #96846 so we can apply the sentinel pattern mentioned in #30024

@github-actions github-actions bot locked and limited conversation to collaborators Feb 11, 2024
@karakasa karakasa deleted the issue-92394 branch May 25, 2024 08:45
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.ComponentModel community-contribution Indicates that the PR has been added by a community member
Projects
None yet
Development

Successfully merging this pull request may close these issues.

TypeDescriptor.GetProperties(object instance) is not thread-safe
3 participants