Reduce allocations in RSIResource.LoadRsiMetadata somewhat.

Using stackallocs for the meta.json file.
This commit is contained in:
Pieter-Jan Briers
2021-05-02 00:55:01 +02:00
parent b8cc01d872
commit a9208c0d29
3 changed files with 63 additions and 6 deletions

View File

@@ -224,16 +224,30 @@ namespace Robust.Client.ResourceManagement
private static RsiMetadata LoadRsiMetadata(IResourceCache cache, ResourcePath path)
{
var manifestPath = path / "meta.json";
string manifestContents;
RsiJsonMetadata? manifestJson;
using (var manifestFile = cache.ContentFileRead(manifestPath))
using (var reader = new StreamReader(manifestFile))
{
manifestContents = reader.ReadToEnd();
}
if (manifestFile.Length <= 4096)
{
// Most RSIs are actually tiny so if that's the case just load them into a stackalloc buffer.
// Avoids a ton of allocations with stream reader etc
// because System.Text.Json can process it directly.
Span<byte> buf = stackalloc byte[4096];
var totalRead = manifestFile.ReadToEnd(buf);
buf = buf[..totalRead];
buf = BomUtil.SkipBom(buf);
// Ok schema validated just fine.
var manifestJson = JsonSerializer.Deserialize<RsiJsonMetadata>(manifestContents, SerializerOptions);
manifestJson = JsonSerializer.Deserialize<RsiJsonMetadata>(buf, SerializerOptions);
}
else
{
using var reader = new StreamReader(manifestFile);
string manifestContents = reader.ReadToEnd();
manifestJson = JsonSerializer.Deserialize<RsiJsonMetadata>(manifestContents, SerializerOptions);
}
}
if (manifestJson == null)
throw new RSILoadException("Manifest JSON was null!");

View File

@@ -0,0 +1,17 @@
using System;
namespace Robust.Shared.Utility
{
internal static class BomUtil
{
public static Span<byte> SkipBom(Span<byte> span)
{
return HasBom(span) ? span[3..] : span;
}
public static bool HasBom(Span<byte> span)
{
return span[2] == 0xBF && span[1] == 0xBB && span[0] == 0xEF;
}
}
}

View File

@@ -60,5 +60,31 @@ namespace Robust.Shared.Utility
read += cRead;
}
}
public static int ReadToEnd(this Stream stream, Span<byte> buffer)
{
var totalRead = 0;
while (true)
{
var read = stream.Read(buffer);
totalRead += read;
if (read == 0)
return totalRead;
buffer = buffer[read..];
}
}
public static int ReadToEnd(this Stream stream, byte[] buffer)
{
var totalRead = 0;
while (true)
{
var read = stream.Read(buffer, totalRead, buffer.Length - totalRead);
totalRead += read;
if (read == 0)
return totalRead;
}
}
}
}