-
Notifications
You must be signed in to change notification settings - Fork 10.1k
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
Memory Leak in new ASPNET 2.2 routing? #6102
Comments
As a workaround - could you try setting
|
Yes sir, thank you for the help! Will do, I'll report back what I find. |
If you have a dump I’d gladly take a look (david.fowler at microsoft) |
I did more testing and found a reliable repro on my machine: Straight up:
Executing the repro above in a fairly quick way you can ramp up the memory usage to 3 GB in almost no time flat. In my case, the new app almost consumes 1 GB / minute. (I have an AutoHotkey shortcut that refreshes the last browser tab used). Here is the project I used to create the following diag chart: fff.zip Check it out:
|
I have a hunch but I need to see the gc root of these: 000007fe75612c10 2739466 109578640 Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0
000007fe756129c0 2739473 175326272 System.Func`1[[Microsoft.Extensions.Primitives.IChangeToken, Microsoft.Extensions.Primitives]]
000007fed0a08868 2739477 175326528 System.Action
000007fed0a35b20 2739501 175328064 System.Action`1[[System.Object, System.Private.CoreLib]]
000007fed0a523c0 3381845 270547600 System.Threading.CancellationTokenSource+CallbackNode This looks like it's the leak. Something isn't cleaning up cancellation token registrations (I've been on a mission cleaning this up since 2.2 but we still have a ways to go). |
It looks like these aren't rooted though. I think they'll eventually get GCed. Still looking. |
I don't know if this is two sides to the same coin, but in my webapp, (generally following the same repro steps), I can get ASPNET to consume memory without any file saves or browser refreshes. In the GIF below:
Waited up to 7GB (not doing anything) and still no end in sight: Paused the debugger, caught Thread 7 in Created dump. Loaded in WinDbg: 0:000> .load C:\Program Files\dotnet\shared\Microsoft.NETCore.App\2.2.0\sos.dll
0:000> !threads -live
ThreadCount: 49
UnstartedThread: 0
BackgroundThread: 19
PendingThread: 0
DeadThread: 29
Hosted Runtime: no
Lock
ID OSID ThreadOBJ State GC Mode GC Alloc Context Domain Count Apt Exception
0 1 6c4 00000000004fcbf0 202a028 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA
15 2 32d0 0000000000561360 2b228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA (Finalizer)
16 3 1274 0000000000480ac0 102a228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA (Threadpool Worker)
17 7 3088 000000000d359270 10a9228 Preemptive 000000025D992928:000000025D9946F0 000000000045d670 4 MTA (Threadpool Worker)
18 8 2cb0 000000000d39de70 202b228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA
19 9 291c 000000000d482010 202b228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA
21 18 27e8 000000000d59ac70 10a9228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA (Threadpool Worker)
22 34 1218 000000001277d050 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
23 35 2ccc 000000001277d6e0 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
24 36 2c0c 000000001277dd70 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
25 37 2c94 000000001277e400 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
26 38 2d54 000000001277ea90 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
27 39 322c 000000001277f120 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
28 40 23a8 00000000127917c0 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
29 41 2d90 0000000012791e50 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
30 42 2e30 00000000127924e0 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
31 43 2d6c 0000000012792b70 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
32 44 33b8 0000000012793200 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
33 45 2434 0000000012793890 21228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 Ukn
34 33 2810 000000000d5998c0 8029228 Preemptive 0000000000000000:0000000000000000 000000000045d670 0 MTA (Threadpool Completion Port)
0:000> ~17s
ntdll!ZwWaitForSingleObject+0xa:
00000000`7742d9fa c3 ret
0:017> !clrstack
OS Thread Id: 0x3088 (17)
Child SP IP Call Site
000000000eacdca8 000000007742d9fa [HelperMethodFrame_1OBJ: 000000000eacdca8] System.Array.Copy(System.Array, Int32, System.Array, Int32, Int32, Boolean)
000000000eacdf90 000007fed47de7f8 System.Array.Copy(System.Array, Int32, System.Array, Int32, Int32) [E:\A\_work\287\s\src\mscorlib\src\System\Array.cs @ 231]
000000000eacdfd0 000007fed344236b System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib]].SetCapacity(Int32) [E:\A\_work\20\s\corefx\src\System.Collections\src\System\Collections\Generic\HashSet.cs @ 1192]
000000000eace030 000007fed34422e1 System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib]].IncreaseCapacity() [E:\A\_work\20\s\corefx\src\System.Collections\src\System\Collections\Generic\HashSet.cs @ 1174]
000000000eace060 000007fed344250f System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib]].AddIfNotPresent(System.__Canon) [E:\A\_work\20\s\corefx\src\System.Collections\src\System\Collections\Generic\HashSet.cs @ 1247]
000000000eace0e0 000007fed34411db System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib]].Add(System.__Canon) [E:\A\_work\20\s\corefx\src\System.Collections\src\System\Collections\Generic\HashSet.cs @ 469]
000000000eace110 000007fecfef6bc2 Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1[[System.__Canon, System.Private.CoreLib]].GenerateNode(TreeBuilderContext<System.__Canon>, Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterionValueEqualityComparer, System.Collections.Generic.List`1<Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1<System.__Canon>>) [/_/shared/Microsoft.AspNetCore.Routing.DecisionTree.Sources/DecisionTreeBuilder.cs @ 161]
000000000eace240 000007fecfef6623 Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1[[System.__Canon, System.Private.CoreLib]].GenerateTree(System.Collections.Generic.IReadOnlyList`1<System.__Canon>, Microsoft.AspNetCore.Routing.DecisionTree.IClassifier`1<System.__Canon>) [/_/shared/Microsoft.AspNetCore.Routing.DecisionTree.Sources/DecisionTreeBuilder.cs @ 91]
000000000eace2b0 000007fecff09932 Microsoft.AspNetCore.Routing.Internal.LinkGenerationDecisionTree..ctor(System.Collections.Generic.IReadOnlyList`1<Microsoft.AspNetCore.Routing.Tree.OutboundMatch>) [/_/src/Microsoft.AspNetCore.Routing/Internal/LinkGenerationDecisionTree.cs @ 27]
000000000eace2f0 000007fecfef5f06 Microsoft.AspNetCore.Routing.RouteValuesAddressScheme.BuildOutboundMatches() [/_/src/Microsoft.AspNetCore.Routing/RouteValuesAddressScheme.cs @ 95]
000000000eace340 000007fecfef5e53 Microsoft.AspNetCore.Routing.RouteValuesAddressScheme.HandleChange() [/_/src/Microsoft.AspNetCore.Routing/RouteValuesAddressScheme.cs @ 84]
000000000eace380 000007fed33ec5ba Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0.<OnChange>b__0(System.Object) [/_/src/Primitives/src/ChangeToken.cs @ 41]
000000000eace3c0 000007fed4897ae8 System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 637]
000000000eace450 000007fecfeecc68 Microsoft.AspNetCore.Routing.CompositeEndpointDataSource.HandleChange() [/_/src/Microsoft.AspNetCore.Routing/CompositeEndpointDataSource.cs @ 112]
000000000eace4c0 000007fed33ec5ba Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0.<OnChange>b__0(System.Object) [/_/src/Primitives/src/ChangeToken.cs @ 41]
000000000eace500 000007fed4897ae8 System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 637]
000000000eace590 000007fed2f6dc22 Microsoft.AspNetCore.Mvc.Internal.MvcEndpointDataSource.UpdateEndpoints() [/_/src/Microsoft.AspNetCore.Mvc.Core/Internal/MvcEndpointDataSource.cs @ 201]
000000000eace690 000007fed33ec5ba Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0.<OnChange>b__0(System.Object) [/_/src/Primitives/src/ChangeToken.cs @ 41]
000000000eace6d0 000007fed4897ae8 System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 637]
000000000eace760 000007fed2f792c6 Microsoft.AspNetCore.Mvc.Infrastructure.DefaultActionDescriptorCollectionProvider.UpdateCollection() [/_/src/Microsoft.AspNetCore.Mvc.Core/Infrastructure/DefaultActionDescriptorCollectionProvider.cs @ 153]
000000000eace7d0 000007fed33ec5ba Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0.<OnChange>b__0(System.Object) [/_/src/Primitives/src/ChangeToken.cs @ 41]
000000000eace810 000007fed48977f5 System.Threading.CancellationTokenSource.InternalRegister(System.Action`1<System.Object>, System.Object, System.Threading.SynchronizationContext, System.Threading.ExecutionContext) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 546]
000000000eace8a0 000007fed486aa40 System.Threading.CancellationToken.Register(System.Action`1<System.Object>, System.Object, Boolean, Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationToken.cs @ 236]
000000000eace910 000007fed486a93e System.Threading.CancellationToken.Register(System.Action`1<System.Object>, System.Object) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationToken.cs @ 192]
000000000eace950 000007fed33e9636 Microsoft.Extensions.Primitives.CompositeChangeToken.RegisterChangeCallback(System.Action`1<System.Object>, System.Object) [/_/src/Primitives/src/CompositeChangeToken.cs @ 48]
000000000eace9a0 000007fed33ec5d9 Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0.<OnChange>b__0(System.Object) [/_/src/Primitives/src/ChangeToken.cs @ 47]
000000000eace9e0 000007fed4791999 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [E:\A\_work\287\s\src\mscorlib\shared\System\Threading\ExecutionContext.cs @ 167]
000000000eacea60 000007fed4897ae8 System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 637]
000000000eaceaf0 000007fed33e992a Microsoft.Extensions.Primitives.CompositeChangeToken.OnChange(System.Object) [/_/src/Primitives/src/CompositeChangeToken.cs @ 117]
000000000eaceb50 000007fed4897ae8 System.Threading.CancellationTokenSource.ExecuteCallbackHandlers(Boolean) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\CancellationTokenSource.cs @ 637]
000000000eacebe0 000007fed2e0c370 Microsoft.Extensions.FileProviders.Physical.PhysicalFilesWatcher+<>c.<.cctor>b__43_0(System.Object) [/_/src/FileProviders/Physical/src/PhysicalFilesWatcher.cs @ 27]
000000000eacec10 000007fed4791999 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object) [E:\A\_work\287\s\src\mscorlib\shared\System\Threading\ExecutionContext.cs @ 167]
000000000eacec90 000007fed484453a System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef) [E:\A\_work\287\s\src\mscorlib\src\System\Threading\Tasks\Task.cs @ 2440]
000000000eaced30 000007fed487c0d2 System.Threading.ThreadPoolWorkQueue.Dispatch() [E:\A\_work\287\s\src\mscorlib\src\System\Threading\ThreadPool.cs @ 588]
000000000eacf1b0 000007fed51aa673 [DebuggerU2MCatchHandlerFrame: 000000000eacf1b0]
0:017> !DumpHeap -stat
Statistics:
MT Count TotalSize Class Name
.....
000007fed4b68ce8 123 263756 System.Char[]
000007fe766161f8 353 270608 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.Reflection.Metadata.TypeDefinitionHandle, System.Reflection.Metadata],[Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Microsoft.CodeAnalysis.CSharp]][]
000007fe7697fbe8 4 272000 Microsoft.CodeAnalysis.ArrayElement`1[[Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxToken, Microsoft.CodeAnalysis.CSharp]][]
000007fe76649530 4066 325280 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[System.Collections.Immutable.ImmutableArray`1[[Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol, Microsoft.CodeAnalysis.CSharp]], System.Collections.Immutable]]
000007fe7664d160 1720 330240 Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol+PENamedTypeSymbolGeneric
000007fed4b8a468 3366 350064 System.Reflection.RuntimeMethodInfo
000007fed4b87e40 9832 393280 System.RuntimeType
000007fe7641be48 13774 440768 Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1+TreeBuilderContext[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]]
000007fed4b661c8 2065 482992 System.Object[]
000007fe764165e0 10453 501744 System.Linq.Enumerable+SelectArrayIterator`2[[Microsoft.AspNetCore.Routing.Patterns.RoutePatternPathSegment, Microsoft.AspNetCore.Routing],[Microsoft.AspNetCore.Routing.Template.TemplateSegment, Microsoft.AspNetCore.Routing]]
000007fe76419298 14440 577600 Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]]
000007fe76415b10 24970 599280 Microsoft.AspNetCore.Routing.Template.TemplateSegment
000007fe76419348 15535 621400 System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]]
000007fe76412368 19976 639232 Microsoft.AspNetCore.Routing.Tree.OutboundMatch
000007fe766632e8 2983 653232 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[System.Collections.Immutable.ImmutableArray`1[[Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol, Microsoft.CodeAnalysis.CSharp]], System.Collections.Immutable]][]
000007fe762d5e88 11889 665784 System.Collections.Generic.Dictionary`2+Enumerator[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]]
000007fe764340f8 20874 667968 Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeNode`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]]
000007fe764329a0 13595 761320 System.Linq.OrderedEnumerable`2[[System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1+Criterion[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]], System.Private.CoreLib],[System.Int32, System.Private.CoreLib]]
000007fe76415e78 19976 799040 System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.Template.TemplateSegment, Microsoft.AspNetCore.Routing]]
000007fe764159f8 19976 799040 Microsoft.AspNetCore.Routing.Template.RouteTemplate
000007fe76431690 20875 835000 System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterion`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]]
000007fe76434be0 4864 841344 System.Collections.Generic.HashSet`1+Slot[[Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]][]
000007fe765dac58 359 844368 System.Reflection.Metadata.MetadataReader
000007fe7664c548 19839 866632 Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol[]
000007fe75e22920 12035 867736 System.Collections.Generic.HashSet`1+Slot[[System.String, System.Private.CoreLib]][]
000007fe7641bef0 13774 881536 System.Collections.Generic.HashSet`1[[Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]]
000007fe75e22568 13779 881856 System.Collections.Generic.HashSet`1[[System.String, System.Private.CoreLib]]
000007fe76616130 18637 894576 System.Collections.Concurrent.ConcurrentDictionary`2+Node[[System.Reflection.Metadata.TypeDefinitionHandle, System.Reflection.Metadata],[Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Microsoft.CodeAnalysis.CSharp]]
000007fe764123f8 22858 914320 System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]]
000007fe76419938 15536 921664 Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]][]
000007fe76433258 13573 977256 System.Linq.OrderedEnumerable`1+<GetEnumerator>d__3[[System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1+Criterion[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]], System.Private.CoreLib]]
000007fe76416b40 17480 978848 Microsoft.AspNetCore.Routing.Template.TemplateSegment[]
000007fe7698e060 1 1048600 Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxNodeCache+Entry[]
000007fe7697a7f0 1 1048600 Roslyn.Utilities.TextKeyedCache`1+SharedEntry[[Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxToken, Microsoft.CodeAnalysis.CSharp]][]
000007fe769796c0 1 1048600 Roslyn.Utilities.TextKeyedCache`1+SharedEntry[[Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxTrivia, Microsoft.CodeAnalysis.CSharp]][]
000007fe7641f450 13709 1096720 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeBuilder`1+Criterion[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]]
000007fe765dc760 4 1146976 Roslyn.Utilities.StringTable+Entry[]
000007fe7641a4c0 14440 1155200 System.Collections.Generic.Dictionary`2[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterionValue, Microsoft.AspNetCore.Routing]]
000007fe764310a8 4742 1183968 System.Collections.Generic.Dictionary`2+Entry[[Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterionValue, Microsoft.AspNetCore.Routing],[System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.DecisionTree.ItemDescriptor`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]], System.Private.CoreLib]][]
000007fe76417770 32462 1218560 Microsoft.AspNetCore.Routing.Template.TemplatePart[]
000007fed4b68d50 5018 1274282 System.Byte[]
000007fe76414128 22116 1301920 Microsoft.AspNetCore.Routing.Tree.OutboundMatch[]
000007fe76430240 23802 1332912 System.Collections.Generic.Dictionary`2+Enumerator[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterionValue, Microsoft.AspNetCore.Routing]]
000007fe7641b750 14440 1386240 System.Collections.Generic.Dictionary`2+Entry[[System.String, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionCriterionValue, Microsoft.AspNetCore.Routing]][]
000007fe76416ef0 24970 1398320 Microsoft.AspNetCore.Routing.Template.TemplatePart
000007fe76435098 5454 1454928 System.Collections.Generic.Dictionary`2+Entry[[System.Object, System.Private.CoreLib],[Microsoft.AspNetCore.Routing.DecisionTree.DecisionTreeNode`1[[Microsoft.AspNetCore.Routing.Tree.OutboundMatch, Microsoft.AspNetCore.Routing]], Microsoft.AspNetCore.Routing]][]
000007fe762e9bf0 39995 1599800 Microsoft.AspNetCore.Routing.RouteValueDictionary
000007fe76416f80 44946 1797840 System.Collections.Generic.List`1[[Microsoft.AspNetCore.Routing.Template.TemplatePart, Microsoft.AspNetCore.Routing]]
000007fe76415788 19976 1917696 Microsoft.AspNetCore.Routing.Tree.OutboundRouteEntry
000007fed4b62aa8 53683 2569680 System.Int32[]
000007fe7664d4b8 16917 2842056 Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol+PENamedTypeSymbolNonGeneric
000007fed4b7a4b0 40035 3521128 System.Collections.Generic.KeyValuePair`2[[System.String, System.Private.CoreLib],[System.Object, System.Private.CoreLib]][]
000007fed4b83770 39487 3634552 System.String
000000000054c350 5807424 291879606 Free
000007fe75792c10 15268935 610757400 Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0
000007fe757929c0 15268942 977212288 System.Func`1[[Microsoft.Extensions.Primitives.IChangeToken, Microsoft.Extensions.Primitives]]
000007fed4b48868 15268958 977213312 System.Action
000007fed4b75b20 15268971 977214144 System.Action`1[[System.Object, System.Private.CoreLib]]
000007fed4b923c0 28440798 2275263840 System.Threading.CancellationTokenSource+CallbackNode
Total 96275880 objects
Fragmented blocks larger than 0.5 MB:
Addr Size Followed by
00000003419c8240 0.6MB 0000000341a57b08 Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.PENamedTypeSymbol[] @davidfowl , this memory dump is on the same server with filename |
This call stack implies that the file watcher is triggering routing to recompute the route table after a file change occurs. Looking at the previous provided list of threads/stacks shows a LOT of threads with similar stacks. I don't think it's a leak because all of the memory is still live. So one of a few obvious possibilities seems possible:
I don't see anything obviously wrong in this call stack. DecisionTreeBuilder is thread-safe so there's no concurrency issue inside that. @davidfowl - if you're looking into this also, there interesting bits are here - in order:
|
I think you might be on to something @rynowak.
Earlier I tried to set Also, I'll try setting up ProcMon to monitor the file paths in the directory to see if I can pickup anything during the autopilot memory ramp up. |
Do you see the leak when you turn off file watching: https://github.com/aspnet/AspNetCore/blob/release/2.2/src/Mvc/src/Microsoft.AspNetCore.Mvc.Razor/RazorViewEngineOptions.cs#L198-L236? As of 2.2, it's disabled by default in non-Development environments. |
Hi @pranavkm , I added the following code before Let me know if I should be configuring it a different way. With Here's a 5-min MP4 video: https://files.bitarmory.com/screen_2600.mp4 The video shows how long each edit takes which progressively gets worse on each edit. At the very bottom of the video, there's a white-background area, that's the browser/website for the Razor page.
|
Are we sure change tokens are being registered (or disposed of) correctly? And that we don't have any kind of daisy chaining of change registrations? If we had daisy chained callbacks it would seem consistent with what I was experiencing as continued subsequent edits took more time to appear in the browser. Here's what I'm seeing inside There seems to be a never ending list of 000007fe75792c10 15268935 610757400 Microsoft.Extensions.Primitives.ChangeToken+<>c__DisplayClass0_0
000007fe757929c0 15268942 977212288 System.Func`1[[Microsoft.Extensions.Primitives.IChangeToken, Microsoft.Extensions.Primitives]]
000007fed4b48868 15268958 977213312 System.Action
000007fed4b75b20 15268971 977214144 System.Action`1[[System.Object, System.Private.CoreLib]]
000007fed4b923c0 28440798 2275263840 System.Threading.CancellationTokenSource+CallbackNode Specifically, when Following the jump, ultimately, we land here which causes the re-computation of routes: Rinse and repeat. This is the hot path the thread is on. Also, I breakpointed the file change events here and didn't notice anything abnormal popping off during automatic monotonically increasing memory usage. I'll continue to do more debugging. 🪲 🐛 🔨 PS. Fun fact, the
|
Oh wait I see a problem. That code is supposed to be called once ever. The underlying code re-registers for triggering on its own and this does it as well. |
Yea, pretty interesting behavior. Now that I have the Every iteration of the
Kinda neat. The situation can get out of hand pretty quick. So far, I'm pretty satisfied we have enough diagnostic information for the issue now. Y'all keepin' my debug skills freshhh 🍉. 😎 I can finally put my mind at rest; gonna to take a few day off now to enjoy the holidays. 🎄 🎄 🎄 🎄 Happy Holidays friends, 🚶♂️ 🚶♀️ Missing Persons - Walking in L.A. |
Wow thanks for the investigation here Brian. That's definitely a bug. |
Just throwing this in here that I'm also having the same issue. My dotnet.exe reached 3 GB's of RAM after wondering for like 15 minutes why my cshtml edits weren't even making it to the browser (browser kept reloading a very old copy!). I learned a lot reading this thread. Keep it up guys! |
I have the same issue in .net core 3.0. I cannot see changes when I refresh the .cshtml page.. (Markup and javascript changes.). I need to re-run the project. Visual Studio version - 2019 preview Thank you |
The issue here was that every time a Razor Page changed, we would subscribe an additional time to the endpoint change notifications. This means that if you tweaked a page 30 times, we would update the address table 31 times when you save the file. If you were doing a lot of editing then this would grow to a really large amount of computation. The fix is to use DataSourceDependentCache, which is an existing utility type we developed for this purpose. I'm not sure why it wasn't being used for this already. We're already using DataSourceDependentCache in a bunch of other places, and it's well tested. I also tweaked the stucture of this code to be more similar to EndpointNameAddressScheme. This involved some test changes that all seemed like good cleanup. The way this was being tested was a little wonky.
The issue here was that every time a Razor Page changed, we would subscribe an additional time to the endpoint change notifications. This means that if you tweaked a page 30 times, we would update the address table 31 times when you save the file. If you were doing a lot of editing then this would grow to a really large amount of computation. The fix is to use DataSourceDependentCache, which is an existing utility type we developed for this purpose. I'm not sure why it wasn't being used for this already. We're already using DataSourceDependentCache in a bunch of other places, and it's well tested. I also tweaked the stucture of this code to be more similar to EndpointNameAddressScheme. This involved some test changes that all seemed like good cleanup. The way this was being tested was a little wonky.
* Fix #6102 - Intense CPU utilization on page change The issue here was that every time a Razor Page changed, we would subscribe an additional time to the endpoint change notifications. This means that if you tweaked a page 30 times, we would update the address table 31 times when you save the file. If you were doing a lot of editing then this would grow to a really large amount of computation. The fix is to use DataSourceDependentCache, which is an existing utility type we developed for this purpose. I'm not sure why it wasn't being used for this already. We're already using DataSourceDependentCache in a bunch of other places, and it's well tested. I also tweaked the stucture of this code to be more similar to EndpointNameAddressScheme. This involved some test changes that all seemed like good cleanup. The way this was being tested was a little wonky. (cherry picked from commit a5658a8)
* Fix #6102 - Intense CPU utilization on page change The issue here was that every time a Razor Page changed, we would subscribe an additional time to the endpoint change notifications. This means that if you tweaked a page 30 times, we would update the address table 31 times when you save the file. If you were doing a lot of editing then this would grow to a really large amount of computation. The fix is to use DataSourceDependentCache, which is an existing utility type we developed for this purpose. I'm not sure why it wasn't being used for this already. We're already using DataSourceDependentCache in a bunch of other places, and it's well tested. I also tweaked the stucture of this code to be more similar to EndpointNameAddressScheme. This involved some test changes that all seemed like good cleanup. The way this was being tested was a little wonky. (cherry picked from commit a5658a8)
* Fix #6102 - Intense CPU utilization on page change The issue here was that every time a Razor Page changed, we would subscribe an additional time to the endpoint change notifications. This means that if you tweaked a page 30 times, we would update the address table 31 times when you save the file. If you were doing a lot of editing then this would grow to a really large amount of computation. The fix is to use DataSourceDependentCache, which is an existing utility type we developed for this purpose. I'm not sure why it wasn't being used for this already. We're already using DataSourceDependentCache in a bunch of other places, and it's well tested. I also tweaked the stucture of this code to be more similar to EndpointNameAddressScheme. This involved some test changes that all seemed like good cleanup. The way this was being tested was a little wonky. (cherry picked from commit a5658a8)
Is this fix available on 2.2 branch? |
@abdulkareemnalband Change 3e5b37f is included since version v2.2.2. |
Describe the bug
I was editing some Razor Pages (the
Project\Pages
kind) then refreshing the changes in Chrome (Version 71.0.3578.98). My dev loop is tight, so I make a small edit then refresh the page, and the change is visible in Chrome.Eventually, I noticed my edits were not making their way to the browser. On a few occasions, I noticed waiting a longer time delay before refreshing the browser sometimes helped the situation. Eventually, though, edits would no longer make their way to the browser.
Originally, I was using
InProcess
but decided to switch toOutOfProcess
, rebooted PC, and the same problem occurred. Somewhere between 15 minutes to 1 hour of constantly editing Razor Pages in Visual Studio, I begin to notice my edits not showing up in the browser.With out of
OutOfProcess
enabled, I noticed, a massive 9.7 GB memory usage indotnet.exe
(later, trying to debug
dotnet.exe
, we're up at 27GB)dotnet.exe
:As
dotnet.exe
consumes memory, there appears to be a few threads that pop offcoreclr_shutdown
. Not much to discern, but worth noting.Next, I attached a VS debugger to
dotnet.exe
, broke into the debugger and landed inProgram.Main()
. None of my user code was running. Continue & Pausing the debugger multiple times did show one thread standing out. Specifically, Thread 3952 playing around in the new ASPNET Core 22 routing code?Microsoft.AspNetCore.Routing.DecisionTree
.Specifically,
Array.Copy
,DecisionTree.Resize
andCapacity.set
seem to be popular destinations with Thread 3952. Thread 3952 is the only thread that appears to be active during this memory leak.To Reproduce
Steps to reproduce the behavior:
Expected behavior
I should be able to make edits in Razor Pages and see my changes in the browser without having to restart
IISExpress
or killdotnet.exe
manually or experience a memory leak during the editing experience.Additional context
Operating System
IDE
Also, here is Process Monitor monitoring file access during the memory leak event:
I will continue to do more testing to see if I can narrow down the issue. Thanks for your help in advance.
Thanks,
Brian Chavez
🍫 🍪 🍭 Ronald Jenkees - Stay Crunchy
The text was updated successfully, but these errors were encountered: