Use spans to improve performance in StreamExts.

Also avoid ReadBytes calls that allocate a buffer by either updating the stream position (if not interested in the bytes), by reusing an input buffer (if interested in the bytes), or using a stackalloc buffer to avoid the allocation (for small reads).
This commit is contained in:
RoosterDragon
2023-09-19 18:10:09 +01:00
committed by Gustas
parent b3ee3551ca
commit 5d91b678bb
20 changed files with 153 additions and 92 deletions

View File

@@ -150,6 +150,8 @@ namespace OpenRA.Mods.Cnc.FileFormats
{
readonly int outputSize;
int dataSize;
byte[] inputBuffer;
byte[] outputBuffer;
public WestwoodCompressedAudStream(Stream stream, int outputSize, int dataSize)
: base(stream)
@@ -167,8 +169,10 @@ namespace OpenRA.Mods.Cnc.FileFormats
var chunk = AudChunk.Read(baseStream);
var input = baseStream.ReadBytes(chunk.CompressedSize);
var output = new byte[chunk.OutputSize];
var input = EnsureArraySize(ref inputBuffer, chunk.CompressedSize);
var output = EnsureArraySize(ref outputBuffer, chunk.OutputSize);
baseStream.ReadBytes(input);
WestwoodCompressedReader.DecodeWestwoodCompressedSample(input, output);
foreach (var b in output)
@@ -178,6 +182,13 @@ namespace OpenRA.Mods.Cnc.FileFormats
return dataSize <= 0;
}
static Span<byte> EnsureArraySize(ref byte[] array, int desiredSize)
{
if (array == null || array.Length < desiredSize)
array = new byte[desiredSize];
return array.AsSpan(..desiredSize);
}
}
}
}

View File

@@ -45,7 +45,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
Transforms[c + 15] = 1;
for (var k = 0; k < 12; k++)
Transforms[c + ids[k]] = s.ReadFloat();
Transforms[c + ids[k]] = s.ReadSingle();
Array.Copy(Transforms, 16 * (LimbCount * j + i), testMatrix, 0, 16);
if (Util.MatrixInverse(testMatrix) == null)

View File

@@ -199,16 +199,16 @@ namespace OpenRA.Mods.Cnc.FileFormats
else if (AudioChannels == 1)
{
var rawAudio = stream.ReadBytes((int)length);
audio1.WriteArray(rawAudio);
audio1.Write(rawAudio);
}
else
{
var rawAudio = stream.ReadBytes((int)length / 2);
audio1.WriteArray(rawAudio);
audio1.Write(rawAudio);
rawAudio = stream.ReadBytes((int)length / 2);
audio2.WriteArray(rawAudio);
audio2.Write(rawAudio);
if (length % 2 != 0)
stream.ReadBytes(2);
stream.Position += 2;
}
compressed = type == "SND2";
@@ -216,7 +216,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
default:
if (length + stream.Position > stream.Length)
throw new NotSupportedException($"Vqa uses unknown Subtype: {type}");
stream.ReadBytes((int)length);
stream.Position += length;
break;
}
@@ -308,7 +308,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
break;
default:
// Don't parse sound here.
stream.ReadBytes((int)length);
stream.Position += length;
break;
}
@@ -382,8 +382,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
// frame-modifier chunk
case "CBP0":
case "CBPZ":
var bytes = s.ReadBytes(subchunkLength);
bytes.CopyTo(cbp, chunkBufferOffset);
s.ReadBytes(cbp, chunkBufferOffset, subchunkLength);
chunkBufferOffset += subchunkLength;
currentChunkBuffer++;
cbpIsCompressed = type == "CBPZ";

View File

@@ -141,12 +141,12 @@ namespace OpenRA.Mods.Cnc.FileFormats
{
limbDataOffset[i] = s.ReadUInt32();
s.Seek(8, SeekOrigin.Current);
Limbs[i].Scale = s.ReadFloat();
Limbs[i].Scale = s.ReadSingle();
s.Seek(48, SeekOrigin.Current);
Limbs[i].Bounds = new float[6];
for (var j = 0; j < 6; j++)
Limbs[i].Bounds[j] = s.ReadFloat();
Limbs[i].Bounds[j] = s.ReadSingle();
Limbs[i].Size = s.ReadBytes(3);
Limbs[i].Type = (NormalType)s.ReadUInt8();
}