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();
|
||||
|
||||
// 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;
|
||||
|
||||
Result rc = _entryStorage.GetSize(out long entryStorageSize);
|
||||
|
|
|
@ -179,25 +179,21 @@ public class IndirectStorage : IStorage
|
|||
if (destination.Length == 0)
|
||||
return Result.Success;
|
||||
|
||||
var closure = new OperatePerEntryClosure();
|
||||
closure.OutBuffer = destination;
|
||||
closure.Offset = offset;
|
||||
var closure = new OperatePerEntryClosure { OutBuffer = destination, 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();
|
||||
|
||||
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)
|
||||
|
@ -328,24 +324,19 @@ public class IndirectStorage : IStorage
|
|||
|
||||
if (!_table.IsEmpty())
|
||||
{
|
||||
var closure = new OperatePerEntryClosure();
|
||||
closure.OperationId = operationId;
|
||||
closure.InBuffer = inBuffer;
|
||||
var closure = new OperatePerEntryClosure { OperationId = operationId, InBuffer = inBuffer };
|
||||
|
||||
static Result QueryRangeImpl(ref ValueSubStorage storage, long physicalOffset,
|
||||
long virtualOffset, long processSize, ref OperatePerEntryClosure closure)
|
||||
{
|
||||
Unsafe.SkipInit(out QueryRangeInfo currentInfo);
|
||||
Result rc = storage.OperateRange(SpanHelpers.AsByteSpan(ref currentInfo),
|
||||
closure.OperationId, physicalOffset, processSize, closure.InBuffer);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
rc = OperatePerEntry(offset, size, enableContinuousReading: false, verifyEntryRanges: true, ref closure,
|
||||
static (ref ValueSubStorage storage, long physicalOffset, long virtualOffset, long processSize, ref OperatePerEntryClosure closure) =>
|
||||
{
|
||||
Unsafe.SkipInit(out QueryRangeInfo currentInfo);
|
||||
Result rc = storage.OperateRange(SpanHelpers.AsByteSpan(ref currentInfo),
|
||||
closure.OperationId, physicalOffset, processSize, closure.InBuffer);
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
closure.InfoMerged.Merge(in currentInfo);
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
rc = OperatePerEntry(offset, size, QueryRangeImpl, ref closure, enableContinuousReading: false,
|
||||
verifyEntryRanges: true);
|
||||
closure.InfoMerged.Merge(in currentInfo);
|
||||
return Result.Success;
|
||||
});
|
||||
if (rc.IsFailure()) return rc.Miss();
|
||||
|
||||
SpanHelpers.AsByteSpan(ref closure.InfoMerged).CopyTo(outBuffer);
|
||||
|
@ -371,8 +362,8 @@ public class IndirectStorage : IStorage
|
|||
public QueryRangeInfo InfoMerged;
|
||||
}
|
||||
|
||||
protected Result OperatePerEntry(long offset, long size, OperatePerEntryFunc func,
|
||||
ref OperatePerEntryClosure closure, bool enableContinuousReading, bool verifyEntryRanges)
|
||||
protected Result OperatePerEntry(long offset, long size, bool enableContinuousReading, bool verifyEntryRanges,
|
||||
ref OperatePerEntryClosure closure, OperatePerEntryFunc func)
|
||||
{
|
||||
// Validate preconditions
|
||||
Assert.SdkRequiresLessEqual(0, offset);
|
||||
|
@ -391,9 +382,9 @@ public class IndirectStorage : IStorage
|
|||
return ResultFs.OutOfRange.Log();
|
||||
|
||||
// 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;
|
||||
|
||||
long entryOffset = visitor.Get<Entry>().GetVirtualOffset();
|
||||
|
|
|
@ -108,25 +108,20 @@ public class SparseStorage : IndirectStorage
|
|||
}
|
||||
else
|
||||
{
|
||||
var closure = new OperatePerEntryClosure();
|
||||
closure.OutBuffer = destination;
|
||||
closure.Offset = offset;
|
||||
var closure = new OperatePerEntryClosure { OutBuffer = destination, Offset = offset };
|
||||
|
||||
Result rc = OperatePerEntry(offset, destination.Length, ReadImpl, ref closure,
|
||||
enableContinuousReading: false, verifyEntryRanges: true);
|
||||
Result rc = OperatePerEntry(offset, destination.Length, enableContinuousReading: false, verifyEntryRanges: true, ref closure,
|
||||
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();
|
||||
}
|
||||
|
||||
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