Nov 15, 2011 at 4:17 PM
Edited Nov 15, 2011 at 6:27 PM
I am entirely convinced that I don't need to deactivate UC on the large data set -- I just need to figure out how to coax UC into managing it more efficiently. I think UC needs some kind of "map-reduce" system for these kinds of situations (i.e. large data
set is projected onto a much smaller data set with incremental changes being made to the large data set -- large-to-large is also worth considering). I'll be thinking about it. Plus, I don't know how to write a "mixed-mode" program that uses UC in the ViewModel
but not in the Model.
Sorry, I forgot to add a comment on my last checkin. I tried to click Cancel during the checkin but it was too late! I just checked in the two changes I mentioned, and fixed the test suite to match:
// Started at 336.
// Making Precedent a base class: 312.
// Removing Gain/LoseDependent events: 288.
// Making IsUpToDate no longer a precident: 248.
// Custom linked list implementation for dependents: 200.
// Custom linked list implementation for precedents: 160.
// Other optimizations: 144.
// Added WeakReferenceToSelf: 148.
Assert.AreEqual(148 + IndependentPlatformOffset, end - start);
It's curious that there is no mention in these comments about the (original) addition of WeakReferences; I thought the change to WRs was made after the memory optimizations, and of course WRs occupy some memory.
A Dictionary wouldn't help that much. It might speed up Precedent.Delete and Precedent.Contains, but now that String.Format is not called, the profiler tells me now that Delete() uses 6.9% and Contains() uses 7.1%. Dependent.AddPrecedent still takes 12%
even though it is an O(1) operation (11% in mscorwks.dll, 1% in AddPrecedent itself). Similarly, Precedent.Insert() takes 12.3% with 10.9% in mscorwks.dll. So trying to optimize the low-level operations further will enjoy diminishing returns. (Besides, you'd
need a special dictionary that supports WeakReference keys properly.)
Update: I just remembered that only Dependents tend to have large lists of Independents, while Independents (and other Precedents) tend to have short lists of Dependents. So it's no wonder that Precedent.Delete() and Precedent.Contains()
aren't super costly. As for a Dependent's list of Precedents, only three operations are done on the list represented by Dependent._firstPrecedent: iterate over all items; add an item; clear the list. Thus, a linked list, List<T> and a dictionary would
all be roughly the same speed.
I've noticed that my app has "bimodal" behavior. If it processes network messages in a timely fashion, then it is usable, if a bit sluggish. However, if the messages get backed up then the app becomes almost completely unresponsive. I think the problem is
the priority of UC updates; perhaps UC updates give themselves higher priority than UI updates and user input. I'll look into that today.
Update: The code in UpdateControls.XAML/Wrapper is not documented. I think it would help me a lot to hear a description of how all of these classes work and fit together. Could you write something about UC.XAML internals? In particular,
I would like to understand how list updating works in UC when a list's ItemsSource is set to a LINQ query wrapped by ForView.Wrap, as compared to a ObservableCollection.