From 9c2e79c4f892828cb787106cef58bd7ed3d6571d Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Wed, 5 Apr 2017 10:07:06 -0400 Subject: [PATCH] Increase ObjectManager.MaxArraySize To support fix-ups during BinaryFormatter deserialization, ObjectManager maintains a table of ObjectHolders. This table is an array, where each element/bucket of the array is a linked list of ObjectHolders, and where the right bucket is found via `id % MaxArraySize`. IDs are allocated monotonically and contiguously, such that the max list size is equal to the total number of object holders divided by MaxArraySize. Every time an object is searched for, we need to find the right bucket, and then walk the list, and so for large numbers of objects, searching for every object is effectively an O(N^2) operation. There are a variety of ways to address this. But a very simple stop-gap is to simply increase the MaxArraySize. Doing so doesn't impact small deserializations, as the array wouldn't have grown beyond MaxArraySize anyway, and for large deserializations, we allocate more memory for the array but only proportionally to the number of objects added to the table. The primary downside is such a large array is more likely to end up in the LOH, which will make collecting the array more expensive, but nowhere near as expensive as the O(N^2) algorithm that would result with a smaller array of long lists. Thus, this mitigation simply increases the MaxArraySize from 4K to 1MB. --- .../src/System/Runtime/Serialization/ObjectManager.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs b/src/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs index d62d2acf3f6c..6fe8b74ef282 100644 --- a/src/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs +++ b/src/System.Runtime.Serialization.Formatters/src/System/Runtime/Serialization/ObjectManager.cs @@ -11,7 +11,7 @@ namespace System.Runtime.Serialization public class ObjectManager { private const int DefaultInitialSize = 16; - private const int MaxArraySize = 0x1000; //MUST BE A POWER OF 2! + private const int MaxArraySize = 0x100000; //MUST BE A POWER OF 2! private const int ArrayMask = MaxArraySize - 1; private const int MaxReferenceDepth = 100;