Mac: Support projection changes that add new files and delete folder#239
Mac: Support projection changes that add new files and delete folder#239wilbaker merged 18 commits intomicrosoft:masterfrom
Conversation
22fefa5 to
4674617
Compare
sanoursa
left a comment
There was a problem hiding this comment.
I haven't totally digested the GitIndexProjection changes yet. Going to test this out for a bit, then come back to that code.
sanoursa
left a comment
There was a problem hiding this comment.
I tested this a bunch and it seems to work well! And the code is complex but makes sense. Nice work on this change.
|
|
||
| public static IEnumerable<T> ShouldMatchInOrder<T>(this IEnumerable<T> group, params T[] expectedValues) | ||
| { | ||
| return group.ShouldMatchInOrder(expectedValues, (t1, t2) => t1.Equals(t2)); |
There was a problem hiding this comment.
Should this be calling the method that takes IEnumerable<T>?
There was a problem hiding this comment.
Good idea, I had trouble doing that before, but I think I forgot to cast expectedValues to an IEnumerable
| { | ||
| ConcurrentHashSet<string> folderPlaceholdersToKeep = new ConcurrentHashSet<string>(); | ||
| ConcurrentBag<PlaceholderListDatabase.PlaceholderData> updatedPlaceholderList = new ConcurrentBag<PlaceholderListDatabase.PlaceholderData>(); | ||
| ConcurrentDictionary<string, PlaceholderListDatabase.PlaceholderData> updatedPlaceholderList = new ConcurrentDictionary<string, PlaceholderListDatabase.PlaceholderData>(StringComparer.Ordinal); |
There was a problem hiding this comment.
This isn't a list anymore. Also how much overhead does adding the string key add? Should this be a ConcurrentDictionary<string, string> and we build the PlaceholderListDatabase.PlaceholderData when calling WriteAllEntriesAndFlush?
There was a problem hiding this comment.
Also how much overhead does adding the string key add?
Let me measure that. If it's significant we might need to further split this code out between Mac and Windows (because we do need the dictionary on Mac).
Should this be a ConcurrentDictionary<string, string> and we build the PlaceholderListDatabase.PlaceholderData when calling WriteAllEntriesAndFlush?
That's a good idea, let me give that a try before making any perf measurements.
There was a problem hiding this comment.
Should this be a ConcurrentDictionary<string, string> and we build the PlaceholderListDatabase.PlaceholderData when calling WriteAllEntriesAndFlush
I'm actually going to start with the perf overhead (starting that testing this morning) and see how things look before and after this change. We're using the same string instances in both the ConcurrentDictionary and the PlaceholderData and so the memory overhead is just an extra reference.
There was a problem hiding this comment.
Should this be a ConcurrentDictionary<string, string> and we build the PlaceholderListDatabase.PlaceholderData when calling WriteAllEntriesAndFlush?
Also, to confirm, what was the main concern here? Perf or memory usage?
| // so that we don't try to delete a folder placeholder that has file placeholders and just fails | ||
| IEnumerable<PlaceholderListDatabase.PlaceholderData> folderPlaceholderData = placeholderListCopy.Where(x => x.IsFolder); | ||
|
|
||
| HashSet<string> folderPlaceholders = new HashSet<string>(folderPlaceholderData.Select(x => x.Path), StringComparer.OrdinalIgnoreCase); |
There was a problem hiding this comment.
placeholderListCopy is now being enumerated twice. Here and the line below. What is the performance impact when there are say a million placeholders?
There was a problem hiding this comment.
Let me measure that as well.
One question I had looking at this code, do you remember why the folder placeholder list is ordered by descending before calling TryRemoveFolderPlaceholder?
I assumed it was being done so that child folders would be removed before their parents, does that sound right to you?
is now being enumerated twice. Here and the line below
Another option I'll look into is removing this call (higher up in the method):
placeholderListCopy.Where(x => !x.IsFolder).ToList(),
And replacing it with code that will walk placeholderListCopy to build both a file list and the HashSet.
There was a problem hiding this comment.
Yes, we have to make sure all the children are removed first so that we can remove the folder when it is empty since we are only removing individual folders and are depending on getting the directory not empty error if we can't delete because of existing files or folders.
There was a problem hiding this comment.
Do we have tests that fail if we drop that ordering? This is a very subtle detail that is easy to lose track of over time.
There was a problem hiding this comment.
Do we have tests that fail if we drop that ordering? This is a very subtle detail that is easy to lose track of over time.
I'll try taking that out and see if any tests fail. The tricky part is even if the ordering were to be removed, I'm not sure that we can come up with a test that would be guaranteed to catch it (as whatever random ordering VFSForGit would use in the future might just happen to work with the test).
|
Here are the initial numbers comparing the total time of
We are noticabley worse with the changes, and so I'll keep digging into where the time is going. Details
|
|
@sanoursa @kewillford I just pushed a commit that goes back to using
|
GVFS/GVFS.FunctionalTests.Windows/Windows/Tests/DiskLayoutUpgradeTests.cs
Show resolved
Hide resolved
| @@ -1374,7 +1554,7 @@ private void ProcessGvUpdateDeletePlaceholderResult( | |||
| PlaceholderListDatabase.PlaceholderData placeholder, | |||
There was a problem hiding this comment.
Not for this PR but the method name ProcessGvUpdateDeletePlaceholderResult needs to change at some point.
Changes for #231 and #219
Summary of Changes
PrjFS_DeleteFileso that it can delete files and folders on Mac (Mac: PrjFSLib should provide a way to delete directory placeholders #231)Folder re-expansion logic
TODOs