From 1110c32cb1c027f538bea649106646db9290aaf6 Mon Sep 17 00:00:00 2001 From: Alex Barney Date: Mon, 11 Mar 2019 23:26:54 -0500 Subject: [PATCH] Fix integrity verification performance regression Integrity verification would always be done on savedata, even when not needed --- src/LibHac/IO/IntegrityVerificationStorage.cs | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/LibHac/IO/IntegrityVerificationStorage.cs b/src/LibHac/IO/IntegrityVerificationStorage.cs index 23aefa45..6f8dbffe 100644 --- a/src/LibHac/IO/IntegrityVerificationStorage.cs +++ b/src/LibHac/IO/IntegrityVerificationStorage.cs @@ -31,7 +31,6 @@ namespace LibHac.IO BlockValidities = new Validity[SectorCount]; } - // todo Take short path when integrity checks are disabled private void ReadImpl(Span destination, long offset, IntegrityCheckLevel integrityCheckLevel) { int count = destination.Length; @@ -39,8 +38,6 @@ namespace LibHac.IO if (count < 0 || count > SectorSize) throw new ArgumentOutOfRangeException(nameof(destination), "Length is invalid."); - - long blockIndex = offset / SectorSize; if (BlockValidities[blockIndex] == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid) @@ -48,13 +45,10 @@ namespace LibHac.IO throw new InvalidDataException("Hash error!"); } - if (Type != IntegrityStorageType.Save && integrityCheckLevel == IntegrityCheckLevel.None) - { - BaseStorage.Read(destination, offset); - return; - } + bool needsHashCheck = integrityCheckLevel != IntegrityCheckLevel.None && + BlockValidities[blockIndex] == Validity.Unchecked; - if (BlockValidities[blockIndex] != Validity.Unchecked) + if (Type != IntegrityStorageType.Save && !needsHashCheck) { BaseStorage.Read(destination, offset); return; @@ -64,11 +58,20 @@ namespace LibHac.IO long hashPos = blockIndex * DigestSize; HashStorage.Read(hashBuffer, hashPos); - if (Type == IntegrityStorageType.Save && Util.IsEmpty(hashBuffer)) + if (Type == IntegrityStorageType.Save) { - destination.Clear(); - BlockValidities[blockIndex] = Validity.Valid; - return; + if (Util.IsEmpty(hashBuffer)) + { + destination.Clear(); + BlockValidities[blockIndex] = Validity.Valid; + return; + } + + if (!needsHashCheck) + { + BaseStorage.Read(destination, offset); + return; + } } byte[] dataBuffer = ArrayPool.Shared.Rent(SectorSize);