Synchronization Complexity in the .NET Framework


Several people here (you know who you are) have been nagging me to do an analysis similar to the one I did for allocations but to get an idea of which methods might do locking and how much.  So I repeated my experiment, this time counting any calls to Monitor.Enter in the subtree of any given method.


The results were very surprising, you can see that the bulk of the methods (78%) do no synchronization at all.  However, once you go down the dark path, it gets bad fast.  The synchronization complexity of the biggest is over 10^19.  Remember as with the allocation metric the number is offset by 1 so that 0 -> 0,  1 -> 1,  10->2,  100->3, etc.


Anyone care to guess what class has the methods with the greatest synchronization complexity?


In a coming article I will write a few words about how to interpret these numbers.  Clearly a complexity of 10^19 does not mean that 10^19 synchronizations actually happen when you call the method.


 


 

Comments (11)

  1. barrkel says:

    Can you explain what the axes of the graph represent?

    I assume the Y-axis is number of calls to Monitor.Enter, but what are the fractional values on the X-axis?

  2. Mike Dunn says:

    X axis = log10(complexity)

    Y axis = number of methods with that complexity

  3. My guess would have to be System.Threading.Thread. It’s probably not something that obvious though.

  4. Maybe one of the lock classes, like ReaderWriterLock? Dunno, but this sure is interesting stuff, Rico – thanks.

  5. Norman Diamond says:

    > Anyone care to guess what class has the

    > methods with the greatest allocation

    > complexity?

    s/allocation/synchronization/?

    If the numbers mean something other than the quantity of synchronizations, I guess they relate to an average length of time that methods are expected to wait while synchronizing.  Maybe that would be clients of networking stuff.

  6. ricom says:

    >> s/allocation/synchronization/?

    Yes, sorry, I fixed that.

  7. I’m retracting my guess because I think RWLocks would implement their own locking mechanism rather than relying on Monitor.

    I’ll offer another vague cop-out of a guess: something in ASP.NET’s caching infrastructure somewhere. Surely there’d have to be some pretty heavy locking there somewhere . . . ?

  8. Alois Kraus says:

    Hi Rico,

    I guess you count the in the call graph Monitor.Enter where the winner function must be contained inside a deeply nested perhaps even recursive call graph. Recursive high level functions would qualify as good candiates for such a thing. A wild guess would be

    System.Xml.Schema.XmlSchemaSet.RemoveRecursive(XmlSchema)

    System.Configuration.BaseConfigurationRecord.CloseRecursive()

    Calls to synchronized wrapper classes such as SyncArrayList could also produce such deep call graphs.

    Yours,

      Alois Kraus

  9. Keith Patrick says:

    Since it’s just guessing, and I don’t have to browse through any classes, I’ll throw out ThreadPool or WebRequest for most synch complexity, being that a thread or IO management would require a great deal of locking, and the file-based IO stuff can depend a lot on the FS to ensure locks

  10. David Conrad says:

    I second Norman Diamond’s choice of Thread.

  11. Well it seems like an eternity ago but at last I’m writing the followup to my initial question about