fadden / CiderPress2

Tool for working with Apple II and vintage Mac disk images and file archives.
https://ciderpress2.com/
Apache License 2.0
44 stars 7 forks source link

WPF DataGrid performance issue affecting file list #5

Open fadden opened 9 months ago

fadden commented 9 months ago

First noted in https://github.com/fadden/CiderPress2/commit/3f97bd1a63a5bc59f811abf54b412b73c4980ac6 .

Steps to reproduce:

When the archive is reopened, the program appears to stall, but eventually opens the file. When it does, the file list is positioned at the end of the archive, and the scroll bar is inactive. The debugger memory view shows a constant series of GCs. Clicking on any GUI element clears things up.

The main thread appears to be in a state of constant activity. Pausing the program to look at the stack trace shows it deep in WPF code (dozens of method calls down). The traces are a bit different every time, but often have something to do with dependency object property change events and DataGridRow objects.

The problem doesn't happen if the file list doesn't have a lot of elements in it. A large archive viewed with single-directory mode won't exhibit the problem (unless it has a lot of stuff in one directory). The width of the main window also matters. If the window is narrow enough to cut off part of the rightmost column ("Access"), the problem doesn't happen.

My best guess is that this has something to do with DataGrid virtualization, which is fraught with peril on a good day. Changing fileListDataGrid's VirtualizingStackPanel.VirtualizationMode value from "Recycling" to "Standard" changes the behavior somewhat. When the reproduction steps are followed, the load process will still appear to stall for a few seconds, showing the list scrolled all the way to the end. However, it will recover on its own, and move the file list position to the top. Again, partially obscuring the Access column fixes the issue.

(I tried setting the width of the Access column to "*" as a work-around, but for some reason the column width didn't change.)

The file list contents, which come out of an ObservableCollection in proper WPF fashion, are cleared when the file is closed. I even threw in an UpdateLayout() call to try to get it to return to its base state.

There's a second issue that is probably related to this one. Steps to reproduce:

When scrolling down, the leftmost column (status icon) will sometimes have a gray rectangle on the left side that pushes the line contents to the right. Not just for that column, but for the entire row, so the vertical column markers are out of whack.

image

The extra rect appears and disappears on a given line as the file list is scrolled, again suggesting the involvement of the GUI element recycling system. (Update: issue happens whether or not there is an icon present in the row.)

In any event, I believe this is a problem in WPF rather than the application code, but it may be possible to find a workaround that reduces the impact.

Update: today it isn't stalling, but it is spitting out about 70 of these when the archive is re-opened:

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DataGrid', AncestorLevel='1''. BindingExpression:Path=HeadersVisibility; DataItem=null; target element is 'DataGridRowHeader' (Name=''); target property is 'Visibility' (type 'Visibility')

Those messages and the extra rect go away if the recycling mode is changed to "standard". Curiously, switching between ProDOS volumes within a2gem.iso doesn't cause the messages to reappear; it's only when the archive is closed and reopened. The GUI elements are hidden, not discarded, when an archive is closed.

Update: none of the problems happen with the "release" build of 0.4.0. Maybe it's a debug-mode-only problem? That would be nice.

Update: it's stalling with the 1.0.0-alpha1 "release" builds (tried win-x86 and win-x64). Maybe I didn't have the window wide enough in the previous round of tests? I'm not seeing the secondary graphical glitches though.