Fix integrity verification performance regression

Integrity verification would always be done on savedata, even when not needed
This commit is contained in:
Alex Barney 2019-03-11 23:26:54 -05:00
parent 06fda75ab9
commit 1110c32cb1

View file

@ -31,7 +31,6 @@ namespace LibHac.IO
BlockValidities = new Validity[SectorCount]; BlockValidities = new Validity[SectorCount];
} }
// todo Take short path when integrity checks are disabled
private void ReadImpl(Span<byte> destination, long offset, IntegrityCheckLevel integrityCheckLevel) private void ReadImpl(Span<byte> destination, long offset, IntegrityCheckLevel integrityCheckLevel)
{ {
int count = destination.Length; int count = destination.Length;
@ -39,8 +38,6 @@ namespace LibHac.IO
if (count < 0 || count > SectorSize) if (count < 0 || count > SectorSize)
throw new ArgumentOutOfRangeException(nameof(destination), "Length is invalid."); throw new ArgumentOutOfRangeException(nameof(destination), "Length is invalid.");
long blockIndex = offset / SectorSize; long blockIndex = offset / SectorSize;
if (BlockValidities[blockIndex] == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid) if (BlockValidities[blockIndex] == Validity.Invalid && integrityCheckLevel == IntegrityCheckLevel.ErrorOnInvalid)
@ -48,13 +45,10 @@ namespace LibHac.IO
throw new InvalidDataException("Hash error!"); throw new InvalidDataException("Hash error!");
} }
if (Type != IntegrityStorageType.Save && integrityCheckLevel == IntegrityCheckLevel.None) bool needsHashCheck = integrityCheckLevel != IntegrityCheckLevel.None &&
{ BlockValidities[blockIndex] == Validity.Unchecked;
BaseStorage.Read(destination, offset);
return;
}
if (BlockValidities[blockIndex] != Validity.Unchecked) if (Type != IntegrityStorageType.Save && !needsHashCheck)
{ {
BaseStorage.Read(destination, offset); BaseStorage.Read(destination, offset);
return; return;
@ -64,11 +58,20 @@ namespace LibHac.IO
long hashPos = blockIndex * DigestSize; long hashPos = blockIndex * DigestSize;
HashStorage.Read(hashBuffer, hashPos); HashStorage.Read(hashBuffer, hashPos);
if (Type == IntegrityStorageType.Save && Util.IsEmpty(hashBuffer)) if (Type == IntegrityStorageType.Save)
{ {
destination.Clear(); if (Util.IsEmpty(hashBuffer))
BlockValidities[blockIndex] = Validity.Valid; {
return; destination.Clear();
BlockValidities[blockIndex] = Validity.Valid;
return;
}
if (!needsHashCheck)
{
BaseStorage.Read(destination, offset);
return;
}
} }
byte[] dataBuffer = ArrayPool<byte>.Shared.Rent(SectorSize); byte[] dataBuffer = ArrayPool<byte>.Shared.Rent(SectorSize);