Skip to content

Commit

Permalink
Hilariously improve select all speed by using a one-liner instead of …
Browse files Browse the repository at this point in the history
…46 lines of code
  • Loading branch information
bagusnl committed Dec 19, 2024
1 parent a3ca990 commit 442fcf4
Showing 1 changed file with 19 additions and 55 deletions.
74 changes: 19 additions & 55 deletions CollapseLauncher/XAMLs/MainApp/Pages/FileCleanupPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Threading;
using System.Threading.Tasks;

// ReSharper disable CheckNamespace
Expand Down Expand Up @@ -175,58 +177,11 @@ private async void CheckAll()
await ToggleCheckAllInnerAsync(true);
}

private ObservableCollection<LocalFileInfo> _fileInfoSourceCopy;

private async Task ToggleCheckAllInnerAsync(bool selectAll)
{
if (selectAll)
{
int batchSize = Math.Clamp(FileInfoSource.Count / (Environment.ProcessorCount * 4), 50, 1000);
var tasks = new List<Task>();
_fileInfoSourceCopy = new ObservableCollection<LocalFileInfo>(FileInfoSource);
int b = 0;
await Task.Run(() =>
{
var batches = FileInfoSource
.Select((file, index) => new { File = file, Index = index })
.GroupBy(x => x.Index / batchSize)
.Select(group => group.Select(x => x.File).ToList());

foreach (var batch in batches)
{
tasks.Add(EnqueueOnDispatcherQueueAsync(() =>
{
var s = new Stopwatch();
s.Start();
foreach (var fileInfo in batch)
{
ListViewTable.SelectedItems.Add(fileInfo);
_fileInfoSourceCopy.Remove(fileInfo);
}
s.Stop();
Logger.LogWriteLine($"[FileCleanupPage::ToggleCheckAllInnerAsync] Finished batch #{b} with {batch.Count} items after {s.ElapsedMilliseconds} ms", LogType.Scheme);

b++;
}));
}
});

await Task.WhenAll(tasks);

await EnqueueOnDispatcherQueueAsync(() =>
{
var i = 0;
while (_fileInfoSourceCopy.Count > 0)
{
ListViewTable.SelectedItems.Add(_fileInfoSourceCopy[0]);
_fileInfoSourceCopy.RemoveAt(0);
i++;
}

Logger
.LogWriteLine($"[FileCleanupPage::ToggleCheckAllInnerAsync] Finished last batch at #{b} after {i} items",
LogType.Scheme);
});
await EnqueueOnDispatcherQueueAsync(() => ListViewTable.SelectAll());
}
else
{
Expand Down Expand Up @@ -382,6 +337,9 @@ private async Task PerformRemoval(ICollection<LocalFileInfo>? deletionSource, lo
return;
}

LoadingMessageHelper.SetMessage(Locale.Lang._FileCleanupPage.LoadingTitle, "TODO: Translate - Deleting files...");
LoadingMessageHelper.ShowLoadingFrame();

if (isToRecycleBin)
{
IList<string> toBeDeleted = new List<string>();
Expand Down Expand Up @@ -421,8 +379,14 @@ private async Task PerformRemoval(ICollection<LocalFileInfo>? deletionSource, lo
}
else
{
foreach (LocalFileInfo fileInfo in deletionSource)
ConcurrentDictionary<LocalFileInfo, byte> processedFiles = new();

var options = new ParallelOptions { MaxDegreeOfParallelism = Environment.ProcessorCount };
await Parallel.ForEachAsync(deletionSource, options, async (fileInfo, _) =>
{
if (!processedFiles.TryAdd(fileInfo, 0))
return;

try
{
FileInfo fileInfoN = fileInfo.ToFileInfo();
Expand All @@ -432,16 +396,16 @@ private async Task PerformRemoval(ICollection<LocalFileInfo>? deletionSource, lo
fileInfoN.Delete();
}

FileInfoSource.Remove(fileInfo);
++deleteSuccess;
await EnqueueOnDispatcherQueueAsync(() => FileInfoSource.Remove(fileInfo));
Interlocked.Increment(ref deleteSuccess);
}
catch (Exception ex)
{
++deleteFailed;
Logger.LogWriteLine($"Failed while deleting this file: {fileInfo.FullPath}\r\n{ex}",
LogType.Error, true);
Interlocked.Increment(ref deleteFailed);
Logger.LogWriteLine($"Failed while deleting this file: {fileInfo.FullPath}\r\n{ex}",
LogType.Error, true);
}
}
});
}

string diagTitle = dialogResult == ContentDialogResult.Primary
Expand Down

0 comments on commit 442fcf4

Please sign in to comment.