Open themoritz opened 8 years ago
Version 1.4.4 - I'm having the same issue. file size is around 130mb Adding the error from SquirrelSetup.log:
DeltaPackageBuilder: We couldn't create a delta for sharedassets0.assets.resS, attempting to create bsdiff DeltaPackageBuilder: We really couldn't create a delta for sharedassets0.assets.resS: System.OutOfMemoryException: Exception of type 'System.OutOfMemoryException' was thrown. at Squirrel.Bsdiff.BinaryPatchUtility.Create(Byte[] oldData, Byte[] newData, Stream output) at Squirrel.DeltaPackageBuilder.createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirectory, Dictionary`2 baseFileListing)
Instead of ReadAllByte here: https://github.com/Squirrel/Squirrel.Windows/blob/de5baa93a134ac24fd5bf9172d3e457ac27e0b7a/src/Squirrel/DeltaPackage.cs#L182
We should compare files in streams like this: https://stackoverflow.com/questions/968935/compare-binary-files-in-c-sharp
@Thieum I think this is worth exploring, so I've marked this as help wanted
to see if we can make this more efficient.
I've reproduced this in latest, Squirrel.Windows v1.9.1 via electron-winstaller v3.0.4.
My environment was 8GB of RAM, package sizes ~780MB.
Does this actually stop packaging? afaik even though the error message is unfortunate, the end result is correct - it's probably Unlikely that we'll be able to generate a usable diff for super gigantic files given our current algorithms (mspatch and bsdiff).
Proper support for giant files probably requires a block-based approach - i.e. diffing sections of a file instead of the whole thing en masse. While this is a Worthwhile Endeavor, it's also not a quick fix.
My call to electron-winstaller's createWindowsInstaller
rejects its promise with the System.OutOfMemoryException
. On disk, it has successfully created the full nupkg and updated RELEASES file with the additional new entry, just no delta.
Although not quick to fix, larger apps have the most to benefit from delta packages.
Surprisingly, when I went to reproduce this again, 2 of my tests actually produced a delta package. It was ~150MB instead of ~780MB. However, attempting the upgrade, squirrel was unable to apply the delta package and fell back to the full package.
DeltaPackageBuilder: Applying MSDiff to lib\net45\<app-name>_ExecutionStub.exe.diff
2019-10-29 15:13:05> Program: Failed to apply updates, falling back to full updates: System.Exception: Invalid release entry: 96695A3C969EB5669ABA99E03B99DE5AFECB78C5 <app-name>_ExecutionStub.exe.shasum 278528
at Squirrel.ReleaseEntry.ParseReleaseEntry(String entry)
at Squirrel.DeltaPackageBuilder.verifyPatchedFile(String relativeFilePath, String inputFile, String tempTargetFile)
at Squirrel.DeltaPackageBuilder.applyDiffToFile(String deltaPath, String relativeFilePath, String workingDirectory)
at Squirrel.DeltaPackageBuilder.<>c__DisplayClass3_1.<ApplyDeltaPackage>b__4(String file)
at Squirrel.EnumerableExtensions.ForEach[TSource](IEnumerable`1 source, Action`1 onNext)
at Squirrel.DeltaPackageBuilder.ApplyDeltaPackage(ReleasePackage basePackage, ReleasePackage deltaPackage, String outputFile)
at Squirrel.UpdateManager.ApplyReleasesImpl.<>c__DisplayClass8_0.<createFullPackagesFromDeltas>b__3()
at System.Threading.Tasks.Task`1.InnerInvoke()
at System.Threading.Tasks.Task.Execute()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Squirrel.UpdateManager.ApplyReleasesImpl.<createFullPackagesFromDeltas>d__8.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Squirrel.UpdateManager.ApplyReleasesImpl.<ApplyReleases>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Squirrel.UpdateManager.<ApplyReleases>d__9.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Squirrel.Update.Program.<Update>d__5.MoveNext()
I just fixed this by replacing the file compare function and updating bsdiff to vcdiff in my branch
https://github.com/Goxiaoy/Squirrel.Windows/tree/vcdiff
see the difference https://github.com/Squirrel/Squirrel.Windows/compare/develop...Goxiaoy:vcdiff
@Goxiaoy, thanks for that. I tried using your changes with vcdiff and deltas are generated much faster than with bsdiff and without memory exceptions or other issues, awesome work!
When I was testing it, I found that there's a boolean expression that should have &&
rather than ||
https://github.com/AurorNZ/Squirrel.Windows/commit/9712eac4540573a63f1a83d64685402dfca8291b#diff-b5814727b039661ec2313bdca28cd202b8a2e931133ed2f01f01b5ae12fc6844L132-R132
- !deltaPathRelativePaths.Contains(x.Replace(".diff", ".bsdiff")) || deltaPathRelativePaths.Contains(x.Replace(".diff", ".vcdiff"))
+ !deltaPathRelativePaths.Contains(x.Replace(".diff", ".bsdiff")) && deltaPathRelativePaths.Contains(x.Replace(".diff", ".vcdiff"))
The following happens with version 1.2.5 (via https://github.com/electron/windows-installer version 2.0.5) during diffing:
Note that there is still enough physical memory when this happens (about 4gb). The files are about 160mb. Works without problems for files that are around 50mb.