mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Tons of compiler optimziations
This commit is contained in:
parent
ea9cd20c67
commit
8affe018bf
@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
using System.Reactive.Disposables;
|
using System.Reactive.Disposables;
|
||||||
|
using System.Reactive.Linq;
|
||||||
using System.Reactive.Subjects;
|
using System.Reactive.Subjects;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
@ -31,6 +32,7 @@ public class LogStream : TargetWithLayout
|
|||||||
{
|
{
|
||||||
_disposables = new CompositeDisposable();
|
_disposables = new CompositeDisposable();
|
||||||
_messageLog.Connect()
|
_messageLog.Connect()
|
||||||
|
.LimitSizeTo(200)
|
||||||
.Bind(out _messagesFiltered)
|
.Bind(out _messagesFiltered)
|
||||||
.Subscribe()
|
.Subscribe()
|
||||||
.DisposeWith(_disposables);
|
.DisposeWith(_disposables);
|
||||||
|
@ -21,12 +21,12 @@ namespace Wabbajack
|
|||||||
public double PosY { get; set; }
|
public double PosY { get; set; }
|
||||||
public double Height { get; set; }
|
public double Height { get; set; }
|
||||||
public double Width { get; set; }
|
public double Width { get; set; }
|
||||||
public InstallerSettings Installer { get; set; } = new InstallerSettings();
|
public InstallerSettings Installer { get; set; } = new();
|
||||||
public FiltersSettings Filters { get; set; } = new FiltersSettings();
|
public FiltersSettings Filters { get; set; } = new();
|
||||||
public CompilerSettings Compiler { get; set; } = new CompilerSettings();
|
public CompilerSettings Compiler { get; set; } = new();
|
||||||
public PerformanceSettings Performance { get; set; } = new PerformanceSettings();
|
public PerformanceSettings Performance { get; set; } = new();
|
||||||
|
|
||||||
private Subject<Unit> _saveSignal = new Subject<Unit>();
|
private Subject<Unit> _saveSignal = new();
|
||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public IObservable<Unit> SaveSignal => _saveSignal;
|
public IObservable<Unit> SaveSignal => _saveSignal;
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ using System.Text.Json;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using System.Windows.Threading;
|
|
||||||
using DynamicData;
|
using DynamicData;
|
||||||
using Microsoft.WindowsAPICodePack.Dialogs;
|
using Microsoft.WindowsAPICodePack.Dialogs;
|
||||||
using ReactiveUI.Fody.Helpers;
|
using ReactiveUI.Fody.Helpers;
|
||||||
|
@ -1,17 +1,5 @@
|
|||||||
using System;
|
using System.Windows;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Windows;
|
|
||||||
using System.Windows.Controls;
|
using System.Windows.Controls;
|
||||||
using System.Windows.Data;
|
|
||||||
using System.Windows.Documents;
|
|
||||||
using System.Windows.Input;
|
|
||||||
using System.Windows.Media;
|
|
||||||
using System.Windows.Media.Imaging;
|
|
||||||
using System.Windows.Navigation;
|
|
||||||
using System.Windows.Shapes;
|
|
||||||
|
|
||||||
namespace Wabbajack
|
namespace Wabbajack
|
||||||
{
|
{
|
||||||
|
@ -103,6 +103,38 @@ public static class AsyncParallelExtensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Faster version of PMapAll for when the function invocation will take a very small amount of time
|
||||||
|
/// batches all the inputs into N groups and executes them all on one task, where N is the number of
|
||||||
|
/// threads supported by the limiter
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="coll"></param>
|
||||||
|
/// <param name="limiter"></param>
|
||||||
|
/// <param name="mapFn"></param>
|
||||||
|
/// <typeparam name="TIn"></typeparam>
|
||||||
|
/// <typeparam name="TJob"></typeparam>
|
||||||
|
/// <typeparam name="TOut"></typeparam>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task PDoAllBatched<TIn, TJob, TOut>(this IEnumerable<TIn> coll,
|
||||||
|
IResource<TJob> limiter, Func<TIn, Task> mapFn)
|
||||||
|
{
|
||||||
|
var asList = coll.ToList();
|
||||||
|
|
||||||
|
var tasks = new List<Task>();
|
||||||
|
|
||||||
|
tasks.AddRange(Enumerable.Range(0, limiter.MaxTasks).Select(i => Task.Run(async () =>
|
||||||
|
{
|
||||||
|
using var job = await limiter.Begin(limiter.Name, asList.Count / limiter.MaxTasks, CancellationToken.None);
|
||||||
|
for (var idx = i; idx < asList.Count; idx += limiter.MaxTasks)
|
||||||
|
{
|
||||||
|
job.ReportNoWait(1);
|
||||||
|
await mapFn(asList[idx]);
|
||||||
|
}
|
||||||
|
})));
|
||||||
|
|
||||||
|
await Task.WhenAll(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
public static async IAsyncEnumerable<TOut> PKeepAll<TIn, TJob, TOut>(this IEnumerable<TIn> coll,
|
public static async IAsyncEnumerable<TOut> PKeepAll<TIn, TJob, TOut>(this IEnumerable<TIn> coll,
|
||||||
IResource<TJob> limiter, Func<TIn, Task<TOut>> mapFn)
|
IResource<TJob> limiter, Func<TIn, Task<TOut>> mapFn)
|
||||||
where TOut : class
|
where TOut : class
|
||||||
|
@ -476,7 +476,7 @@ public abstract class ACompiler
|
|||||||
|
|
||||||
NextStep("Compiling", "Generating Patches", toBuild.Length);
|
NextStep("Compiling", "Generating Patches", toBuild.Length);
|
||||||
|
|
||||||
var allFiles = toBuild.SelectMany(f =>
|
var allFiles = (await toBuild.PMapAllBatched(CompilerLimiter, async f =>
|
||||||
{
|
{
|
||||||
UpdateProgress(1);
|
UpdateProgress(1);
|
||||||
return new[]
|
return new[]
|
||||||
@ -484,7 +484,8 @@ public abstract class ACompiler
|
|||||||
_vfs.Index.FileForArchiveHashPath(f.ArchiveHashPath),
|
_vfs.Index.FileForArchiveHashPath(f.ArchiveHashPath),
|
||||||
FindDestFile(f.To)
|
FindDestFile(f.To)
|
||||||
};
|
};
|
||||||
})
|
}).ToList())
|
||||||
|
.SelectMany(x => x)
|
||||||
.DistinctBy(f => f.Hash)
|
.DistinctBy(f => f.Hash)
|
||||||
.ToHashSet();
|
.ToHashSet();
|
||||||
|
|
||||||
|
@ -20,6 +20,11 @@ public class DeconstructBSAs : ACompilationStep
|
|||||||
private readonly Func<VirtualFile, List<ICompilationStep>> _microstack;
|
private readonly Func<VirtualFile, List<ICompilationStep>> _microstack;
|
||||||
private readonly Func<VirtualFile, List<ICompilationStep>> _microstackWithInclude;
|
private readonly Func<VirtualFile, List<ICompilationStep>> _microstackWithInclude;
|
||||||
private readonly MO2Compiler _mo2Compiler;
|
private readonly MO2Compiler _mo2Compiler;
|
||||||
|
private readonly DirectMatch _directMatch;
|
||||||
|
private readonly MatchSimilarTextures _matchSimilar;
|
||||||
|
private readonly IncludePatches _includePatches;
|
||||||
|
private readonly DropAll _dropAll;
|
||||||
|
private readonly IncludeAll _includeAll;
|
||||||
|
|
||||||
public DeconstructBSAs(ACompiler compiler) : base(compiler)
|
public DeconstructBSAs(ACompiler compiler) : base(compiler)
|
||||||
{
|
{
|
||||||
@ -38,20 +43,27 @@ public class DeconstructBSAs : ACompilationStep
|
|||||||
.Select(kv => kv.Key.RelativeTo(_mo2Compiler._settings.Source))
|
.Select(kv => kv.Key.RelativeTo(_mo2Compiler._settings.Source))
|
||||||
.ToList();
|
.ToList();
|
||||||
|
|
||||||
|
// Cache these so their internal caches aren't recreated on every use
|
||||||
|
_directMatch = new DirectMatch(_mo2Compiler);
|
||||||
|
_matchSimilar = new MatchSimilarTextures(_mo2Compiler);
|
||||||
|
_includePatches = new IncludePatches(_mo2Compiler);
|
||||||
|
_dropAll = new DropAll(_mo2Compiler);
|
||||||
|
_includeAll = new IncludeAll(_mo2Compiler);
|
||||||
|
|
||||||
_microstack = bsa => new List<ICompilationStep>
|
_microstack = bsa => new List<ICompilationStep>
|
||||||
{
|
{
|
||||||
new DirectMatch(_mo2Compiler),
|
_directMatch,
|
||||||
new MatchSimilarTextures(_mo2Compiler),
|
_matchSimilar,
|
||||||
new IncludePatches(_mo2Compiler, bsa),
|
_includePatches.WithBSA(bsa),
|
||||||
new DropAll(_mo2Compiler)
|
_dropAll
|
||||||
};
|
};
|
||||||
|
|
||||||
_microstackWithInclude = bsa => new List<ICompilationStep>
|
_microstackWithInclude = bsa => new List<ICompilationStep>
|
||||||
{
|
{
|
||||||
new DirectMatch(_mo2Compiler),
|
_directMatch,
|
||||||
new MatchSimilarTextures(_mo2Compiler),
|
_matchSimilar,
|
||||||
new IncludePatches(_mo2Compiler, bsa),
|
_includePatches.WithBSA(bsa),
|
||||||
new IncludeAll(_mo2Compiler)
|
_includeAll
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,6 +37,21 @@ public class IncludePatches : ACompilationStep
|
|||||||
_isGenericGame = _compiler._settings.Game.MetaData().IsGenericMO2Plugin;
|
_isGenericGame = _compiler._settings.Game.MetaData().IsGenericMO2Plugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IncludePatches(ACompiler compiler,
|
||||||
|
VirtualFile bsa,
|
||||||
|
Dictionary<RelativePath, IEnumerable<VirtualFile>> indexedByName,
|
||||||
|
Dictionary<RelativePath, IGrouping<RelativePath, VirtualFile>> indexed) : base(compiler)
|
||||||
|
{
|
||||||
|
_bsa = bsa;
|
||||||
|
_indexedByName = indexedByName;
|
||||||
|
_indexed = indexed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IncludePatches WithBSA(VirtualFile constructingFromBSA)
|
||||||
|
{
|
||||||
|
return new IncludePatches(_compiler, constructingFromBSA, _indexedByName, _indexed);
|
||||||
|
}
|
||||||
|
|
||||||
public override async ValueTask<Directive?> Run(RawSourceFile source)
|
public override async ValueTask<Directive?> Run(RawSourceFile source)
|
||||||
{
|
{
|
||||||
if (_isGenericGame)
|
if (_isGenericGame)
|
||||||
|
@ -151,6 +151,7 @@ public class MO2Compiler : ACompiler
|
|||||||
// Add the extra files that were generated by the stack
|
// Add the extra files that were generated by the stack
|
||||||
results = results.Concat(ExtraFiles).ToList();
|
results = results.Concat(ExtraFiles).ToList();
|
||||||
|
|
||||||
|
NextStep("Compiling", "Finding Errors");
|
||||||
var noMatch = results.OfType<NoMatch>().ToArray();
|
var noMatch = results.OfType<NoMatch>().ToArray();
|
||||||
PrintNoMatches(noMatch);
|
PrintNoMatches(noMatch);
|
||||||
if (CheckForNoMatchExit(noMatch)) return false;
|
if (CheckForNoMatchExit(noMatch)) return false;
|
||||||
|
@ -42,18 +42,17 @@ public class BinaryPatchCache : IBinaryPatchCache
|
|||||||
|
|
||||||
await using var sigStream = new MemoryStream();
|
await using var sigStream = new MemoryStream();
|
||||||
var tempName = _location.Combine(Guid.NewGuid().ToString()).WithExtension(Ext.Temp);
|
var tempName = _location.Combine(Guid.NewGuid().ToString()).WithExtension(Ext.Temp);
|
||||||
await using var patchStream = tempName.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
||||||
OctoDiff.Create(srcStream, destStream, sigStream, patchStream, job);
|
{
|
||||||
|
await using var patchStream = tempName.Open(FileMode.Create, FileAccess.ReadWrite, FileShare.None);
|
||||||
patchStream.Close();
|
OctoDiff.Create(srcStream, destStream, sigStream, patchStream, job);
|
||||||
|
}
|
||||||
await tempName.MoveToAsync(location, true, CancellationToken.None);
|
await tempName.MoveToAsync(location, true, CancellationToken.None);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
await patchStream.DisposeAsync();
|
|
||||||
if (tempName.FileExists())
|
if (tempName.FileExists())
|
||||||
tempName.Delete();
|
tempName.Delete();
|
||||||
}
|
}
|
||||||
|
@ -184,15 +184,21 @@ public static class AbsolutePathExtensions
|
|||||||
fid.IsReadOnly = false;
|
fid.IsReadOnly = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var retries = 0;
|
||||||
|
while (true)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
File.Move(srcStr, destStr, overwrite);
|
try
|
||||||
}
|
{
|
||||||
catch (Exception)
|
File.Move(srcStr, destStr, overwrite);
|
||||||
{
|
return;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (retries > 10)
|
||||||
|
throw;
|
||||||
|
retries++;
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(1), token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user