mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Improve IndirectStorage allocations
Make sure rented arrays are returned and remove delegate allocations by using lambda functions
This commit is contained in:
parent
40925034e1
commit
921fbab17a
3 changed files with 37 additions and 51 deletions
|
@ -702,7 +702,7 @@ public partial class BucketTree : IDisposable
|
||||||
return ResultFs.OutOfRange.Log();
|
return ResultFs.OutOfRange.Log();
|
||||||
|
|
||||||
// Create a pooled buffer for our scan.
|
// Create a pooled buffer for our scan.
|
||||||
var pool = new PooledBuffer((int)_nodeSize, 1);
|
using var pool = new PooledBuffer((int)_nodeSize, 1);
|
||||||
var buffer = Span<byte>.Empty;
|
var buffer = Span<byte>.Empty;
|
||||||
|
|
||||||
Result rc = _entryStorage.GetSize(out long entryStorageSize);
|
Result rc = _entryStorage.GetSize(out long entryStorageSize);
|
||||||
|
|
|
@ -179,25 +179,21 @@ public class IndirectStorage : IStorage
|
||||||
if (destination.Length == 0)
|
if (destination.Length == 0)
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
|
||||||
var closure = new OperatePerEntryClosure();
|
var closure = new OperatePerEntryClosure { OutBuffer = destination, Offset = offset };
|
||||||
closure.OutBuffer = destination;
|
|
||||||
closure.Offset = offset;
|
Result rc = OperatePerEntry(offset, destination.Length, enableContinuousReading: true, verifyEntryRanges: true, ref closure,
|
||||||
|
static (ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long size, ref OperatePerEntryClosure entryClosure) =>
|
||||||
|
{
|
||||||
|
int bufferPosition = (int)(virtualOffset - entryClosure.Offset);
|
||||||
|
Result rc = storage.Read(physicalOffset, entryClosure.OutBuffer.Slice(bufferPosition, (int)size));
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
});
|
||||||
|
|
||||||
Result rc = OperatePerEntry(offset, destination.Length, ReadImpl, ref closure, enableContinuousReading: true,
|
|
||||||
verifyEntryRanges: true);
|
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
|
||||||
static Result ReadImpl(ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long processSize,
|
|
||||||
ref OperatePerEntryClosure closure)
|
|
||||||
{
|
|
||||||
int bufferPosition = (int)(virtualOffset - closure.Offset);
|
|
||||||
Result rc = storage.Read(physicalOffset, closure.OutBuffer.Slice(bufferPosition, (int)processSize));
|
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
|
||||||
|
|
||||||
return Result.Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
protected override Result DoWrite(long offset, ReadOnlySpan<byte> source)
|
||||||
|
@ -328,24 +324,19 @@ public class IndirectStorage : IStorage
|
||||||
|
|
||||||
if (!_table.IsEmpty())
|
if (!_table.IsEmpty())
|
||||||
{
|
{
|
||||||
var closure = new OperatePerEntryClosure();
|
var closure = new OperatePerEntryClosure { OperationId = operationId, InBuffer = inBuffer };
|
||||||
closure.OperationId = operationId;
|
|
||||||
closure.InBuffer = inBuffer;
|
|
||||||
|
|
||||||
static Result QueryRangeImpl(ref ValueSubStorage storage, long physicalOffset,
|
rc = OperatePerEntry(offset, size, enableContinuousReading: false, verifyEntryRanges: true, ref closure,
|
||||||
long virtualOffset, long processSize, ref OperatePerEntryClosure closure)
|
static (ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long processSize, ref OperatePerEntryClosure closure) =>
|
||||||
{
|
{
|
||||||
Unsafe.SkipInit(out QueryRangeInfo currentInfo);
|
Unsafe.SkipInit(out QueryRangeInfo currentInfo);
|
||||||
Result rc = storage.OperateRange(SpanHelpers.AsByteSpan(ref currentInfo),
|
Result rc = storage.OperateRange(SpanHelpers.AsByteSpan(ref currentInfo),
|
||||||
closure.OperationId, physicalOffset, processSize, closure.InBuffer);
|
closure.OperationId, physicalOffset, processSize, closure.InBuffer);
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
closure.InfoMerged.Merge(in currentInfo);
|
closure.InfoMerged.Merge(in currentInfo);
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
}
|
});
|
||||||
|
|
||||||
rc = OperatePerEntry(offset, size, QueryRangeImpl, ref closure, enableContinuousReading: false,
|
|
||||||
verifyEntryRanges: true);
|
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
SpanHelpers.AsByteSpan(ref closure.InfoMerged).CopyTo(outBuffer);
|
SpanHelpers.AsByteSpan(ref closure.InfoMerged).CopyTo(outBuffer);
|
||||||
|
@ -371,8 +362,8 @@ public class IndirectStorage : IStorage
|
||||||
public QueryRangeInfo InfoMerged;
|
public QueryRangeInfo InfoMerged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Result OperatePerEntry(long offset, long size, OperatePerEntryFunc func,
|
protected Result OperatePerEntry(long offset, long size, bool enableContinuousReading, bool verifyEntryRanges,
|
||||||
ref OperatePerEntryClosure closure, bool enableContinuousReading, bool verifyEntryRanges)
|
ref OperatePerEntryClosure closure, OperatePerEntryFunc func)
|
||||||
{
|
{
|
||||||
// Validate preconditions
|
// Validate preconditions
|
||||||
Assert.SdkRequiresLessEqual(0, offset);
|
Assert.SdkRequiresLessEqual(0, offset);
|
||||||
|
@ -391,9 +382,9 @@ public class IndirectStorage : IStorage
|
||||||
return ResultFs.OutOfRange.Log();
|
return ResultFs.OutOfRange.Log();
|
||||||
|
|
||||||
// Find the offset in our tree
|
// Find the offset in our tree
|
||||||
var visitor = new BucketTree.Visitor();
|
using var visitor = new BucketTree.Visitor();
|
||||||
|
|
||||||
rc = _table.Find(ref visitor, offset);
|
rc = _table.Find(ref visitor.Ref, offset);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
long entryOffset = visitor.Get<Entry>().GetVirtualOffset();
|
long entryOffset = visitor.Get<Entry>().GetVirtualOffset();
|
||||||
|
|
|
@ -108,25 +108,20 @@ public class SparseStorage : IndirectStorage
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var closure = new OperatePerEntryClosure();
|
var closure = new OperatePerEntryClosure { OutBuffer = destination, Offset = offset };
|
||||||
closure.OutBuffer = destination;
|
|
||||||
closure.Offset = offset;
|
|
||||||
|
|
||||||
Result rc = OperatePerEntry(offset, destination.Length, ReadImpl, ref closure,
|
Result rc = OperatePerEntry(offset, destination.Length, enableContinuousReading: false, verifyEntryRanges: true, ref closure,
|
||||||
enableContinuousReading: false, verifyEntryRanges: true);
|
static (ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long size, ref OperatePerEntryClosure closure) =>
|
||||||
|
{
|
||||||
|
int bufferPosition = (int)(virtualOffset - closure.Offset);
|
||||||
|
Result rc = storage.Read(physicalOffset, closure.OutBuffer.Slice(bufferPosition, (int)size));
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
});
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Result.Success;
|
return Result.Success;
|
||||||
|
|
||||||
static Result ReadImpl(ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long processSize,
|
|
||||||
ref OperatePerEntryClosure closure)
|
|
||||||
{
|
|
||||||
int bufferPosition = (int)(virtualOffset - closure.Offset);
|
|
||||||
Result rc = storage.Read(physicalOffset, closure.OutBuffer.Slice(bufferPosition, (int)processSize));
|
|
||||||
if (rc.IsFailure()) return rc.Miss();
|
|
||||||
|
|
||||||
return Result.Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue