The attached patch addresses the issue by changing the memory manager to do some cleaning of the list whenever a databag is registered.
I tried two previous approaches that did not work.
First, I had the memory manager spin a separate thread that woke up every five seconds and cleaned the list. For reasons that are entirely unclear to me this solution ran out of memory faster than before.
Second, I had the register call clean the entire list. This proved to be far too expensive, and slowed down performance by about 10x.
So, in this final register begins searching at the head of list, cleaning any weak references it can. As soon as it encounters an entry in the list that is valid, it quits looking. This avoids long searches through the list when most of the entries are valid. It rests on the assumption that data bags generally live about the same amount of time, thus there won't be a long lived databag at the head of the list blocking the cleaning of many stale references later in the list.