From 294dbff40a068fed56b6470c77df4aaeaf5ff32c Mon Sep 17 00:00:00 2001 From: Pavel Djundik Date: Tue, 13 Aug 2024 17:48:06 +0300 Subject: [PATCH] Optimize calculating adler hashes to not allocate entire chunk in memory --- DepotDownloader/ContentDownloader.cs | 16 ++++++++--- DepotDownloader/Util.cs | 40 +++++++--------------------- 2 files changed, 21 insertions(+), 35 deletions(-) diff --git a/DepotDownloader/ContentDownloader.cs b/DepotDownloader/ContentDownloader.cs index 65248504..726df929 100644 --- a/DepotDownloader/ContentDownloader.cs +++ b/DepotDownloader/ContentDownloader.cs @@ -1059,10 +1059,18 @@ namespace DepotDownloader { fsOld.Seek((long)match.OldChunk.Offset, SeekOrigin.Begin); - var tmp = new byte[match.OldChunk.UncompressedLength]; - fsOld.Read(tmp, 0, tmp.Length); + uint a = 0, b = 0; - var adler = Util.AdlerHash(tmp); + for (var i = 0; i < match.OldChunk.UncompressedLength; i++) + { + var c = (uint)fsOld.ReadByte(); + + // adler hash + a = (a + c) % 65521; + b = (b + a) % 65521; + } + + var adler = BitConverter.GetBytes(a | (b << 16)); if (!adler.SequenceEqual(match.OldChunk.Checksum)) { neededChunks.Add(match.NewChunk); @@ -1191,7 +1199,7 @@ namespace DepotDownloader var depot = depotFilesData.depotDownloadInfo; var depotDownloadCounter = depotFilesData.depotCounter; - var chunkID = Util.EncodeHexString(chunk.ChunkID); + var chunkID = Convert.ToHexString(chunk.ChunkID).ToLowerInvariant(); var data = new DepotManifest.ChunkData { diff --git a/DepotDownloader/Util.cs b/DepotDownloader/Util.cs index 3cda8dab..5157d92e 100644 --- a/DepotDownloader/Util.cs +++ b/DepotDownloader/Util.cs @@ -78,26 +78,23 @@ namespace DepotDownloader public static List ValidateSteam3FileChecksums(FileStream fs, ProtoManifest.ChunkData[] chunkdata) { var neededChunks = new List(); - int read; foreach (var data in chunkdata) { - var chunk = new byte[data.UncompressedLength]; fs.Seek((long)data.Offset, SeekOrigin.Begin); - read = fs.Read(chunk, 0, (int)data.UncompressedLength); - byte[] tempchunk; - if (read < data.UncompressedLength) - { - tempchunk = new byte[read]; - Array.Copy(chunk, 0, tempchunk, 0, read); - } - else + uint a = 0, b = 0; + + for (var i = 0; i < data.UncompressedLength; i++) { - tempchunk = chunk; + var c = (uint)fs.ReadByte(); + + // adler hash + a = (a + c) % 65521; + b = (b + a) % 65521; } - var adler = AdlerHash(tempchunk); + var adler = BitConverter.GetBytes(a | (b << 16)); if (!adler.SequenceEqual(data.Checksum)) { neededChunks.Add(data); @@ -107,18 +104,6 @@ namespace DepotDownloader return neededChunks; } - public static byte[] AdlerHash(byte[] input) - { - uint a = 0, b = 0; - for (var i = 0; i < input.Length; i++) - { - a = (a + input[i]) % 65521; - b = (b + a) % 65521; - } - - return BitConverter.GetBytes(a | (b << 16)); - } - public static byte[] DecodeHexString(string hex) { if (hex == null) @@ -133,13 +118,6 @@ namespace DepotDownloader return bytes; } - public static string EncodeHexString(byte[] input) - { - return input.Aggregate(new StringBuilder(), - (sb, v) => sb.Append(v.ToString("x2")) - ).ToString(); - } - /// /// Decrypts using AES/ECB/PKCS7 ///