What’s causing this ‘Hashtable insert failed. Load factor too high.’ error?

On a number of occasions I’ve seen this error on an ASP.NET Web Application that’s under a fairly heavy load.

Hashtable insert failed. Load factor too high.  At:
    at System.Collections.Hashtable.Insert(Object key, Object nvalue, Boolean add)
    at System.Runtime.Serialization.SerializationEventsCache.GetSerializationEventsForType(Type t)
    at System.Runtime.Serialization.SerializationObjectManager.RegisterObject(Object obj)
    
    at System.Web.Util.AltSerialization.WriteValueToStream(Object value, BinaryWriter writer)

The problem is that it just doesn’t happen once or twice and go away. It requires a restart of the W3SVC service which takes the entire web server down. After looking at the stack trace in the error my first thought was that there was a Hashtable being used in the application that wasn’t thread safe. Unfortunately, it wasn’t that easy. There were no Hashtables being used directly in the code. So I decided to use a Support Services call to try to get to the bottom of what was going on.

After a number of back-and-forths, Microsoft sent a patch (which is now available publically at http://support.microsoft.com/kb/968432 ). They didn’t explain what the problem was, so I fired up ildasm and looked at the changes. What I noticed were changes to a number of methods in the System.ComponentModel.ReflectTypeDescriptionProvider class. This class is a .NET internal class that is responsible for providing Type information about particular classes.

If you look at the Before and After snippets below, you’ll see the kind of changes that were made to all of the methods in this class. Basically, the code that is responsible for building a Hashtable wasn’t thread safe, hence the additional lock in the After snippet.

Before (System.dll version 2.0.50727.4016):

private static Attribute[] ReflectGetAttributes(Type type)
{
    if (_attributeCache == null)
    {
        lock (_internalSyncObject)
        {
            if (_attributeCache == null)
            {
                _attributeCache = new Hashtable();
            }
        }
    }

    Attribute[] array = (Attribute[]) _attributeCache[type];
    if (array == null)
    {
         object[] customAttributes = type.GetCustomAttributes(typeof(Attribute), false);
         array = new Attribute[customAttributes.Length];
         customAttributes.CopyTo(array, 0);
         _attributeCache[type] = array;
    }
    return array;
}

After (System.dll version 2.0.50727.4038):

private static Attribute[] ReflectGetAttributes(Type type)
{
    if (_attributeCache == null)
    {
        lock (_internalSyncObject)
        {
            if (_attributeCache == null)
            {
                _attributeCache = new Hashtable();
            }
        }
    } 

    Attribute[] array = (Attribute[]) _attributeCache[type];
    if (array == null)
    {
        lock (_internalSyncObject)
        {
            array = (Attribute[]) _attributeCache[type];
            if (array == null)
            {
                object[] customAttributes = type.GetCustomAttributes(typeof(Attribute), false);
                array = new Attribute[customAttributes.Length];
                customAttributes.CopyTo(array, 0);
                _attributeCache[type] = array;
            }
        }
    }
    return array;
}

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

w

Connecting to %s