From 12dec18f396bb996d5db09cc67b1774ae55629e8 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Tue, 15 Feb 2022 19:17:33 +0000 Subject: [PATCH] Reduce allocations for Spir-v serialization Passes BinaryWriter instead of the stream to Write and WriteOperand - Removes creation of BinaryWriter for each instruction - Removes allocations for literal string --- Spv.Generator/Instruction.cs | 12 +++++------- Spv.Generator/LiteralInteger.cs | 4 ++-- Spv.Generator/LiteralString.cs | 10 +++++----- Spv.Generator/Module.cs | 24 ++++++++++++------------ Spv.Generator/Operand.cs | 2 +- 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/Spv.Generator/Instruction.cs b/Spv.Generator/Instruction.cs index a7fb162c9..dfe28484d 100644 --- a/Spv.Generator/Instruction.cs +++ b/Spv.Generator/Instruction.cs @@ -111,15 +111,13 @@ namespace Spv.Generator AddOperand(LiteralInteger.CreateForEnum(value)); } - public void Write(Stream stream) + public void Write(BinaryWriter writer) { - BinaryWriter writer = new BinaryWriter(stream); - // Word 0 writer.Write((ushort)Opcode); writer.Write(GetTotalWordCount()); - _resultType?.WriteOperand(stream); + _resultType?.WriteOperand(writer); if (Id != InvalidId) { @@ -128,11 +126,11 @@ namespace Spv.Generator foreach (Operand operand in _operands) { - operand.WriteOperand(stream); + operand.WriteOperand(writer); } } - public void WriteOperand(Stream stream) + public void WriteOperand(BinaryWriter writer) { Debug.Assert(Id != InvalidId); @@ -156,7 +154,7 @@ namespace Spv.Generator throw new InvalidOperationException($"Id wasn't bound to the module, please make sure to call {methodToCall}"); } - stream.Write(BitConverter.GetBytes(Id)); + writer.Write(Id); } public override bool Equals(object obj) diff --git a/Spv.Generator/LiteralInteger.cs b/Spv.Generator/LiteralInteger.cs index 7568cc1bc..b9afa0055 100644 --- a/Spv.Generator/LiteralInteger.cs +++ b/Spv.Generator/LiteralInteger.cs @@ -53,9 +53,9 @@ namespace Spv.Generator public ushort WordCount => (ushort)(_data.Length / 4); - public void WriteOperand(Stream stream) + public void WriteOperand(BinaryWriter writer) { - stream.Write(_data); + writer.Write(_data); } public override bool Equals(object obj) diff --git a/Spv.Generator/LiteralString.cs b/Spv.Generator/LiteralString.cs index 8d27e407e..259b946ac 100644 --- a/Spv.Generator/LiteralString.cs +++ b/Spv.Generator/LiteralString.cs @@ -17,15 +17,15 @@ namespace Spv.Generator public ushort WordCount => (ushort)(_value.Length / 4 + 1); - public void WriteOperand(Stream stream) + public void WriteOperand(BinaryWriter writer) { - byte[] rawValue = Encoding.ASCII.GetBytes(_value); + writer.Write(_value.AsSpan()); - stream.Write(rawValue); + int paddingSize = 4 - (Encoding.ASCII.GetByteCount(_value) % 4); - int paddingSize = 4 - (rawValue.Length % 4); + Span padding = stackalloc byte[paddingSize]; - stream.Write(new byte[paddingSize]); + writer.Write(padding); } public override bool Equals(object obj) diff --git a/Spv.Generator/Module.cs b/Spv.Generator/Module.cs index b16b859b6..03d649680 100644 --- a/Spv.Generator/Module.cs +++ b/Spv.Generator/Module.cs @@ -247,7 +247,7 @@ namespace Spv.Generator { using (MemoryStream stream = new MemoryStream()) { - BinaryWriter writer = new BinaryWriter(stream); + BinaryWriter writer = new BinaryWriter(stream, System.Text.Encoding.ASCII); // Header writer.Write(MagicNumber); @@ -262,7 +262,7 @@ namespace Spv.Generator Instruction capabilityInstruction = new Instruction(Op.OpCapability); capabilityInstruction.AddOperand(capability); - capabilityInstruction.Write(stream); + capabilityInstruction.Write(writer); } // 2. @@ -271,44 +271,44 @@ namespace Spv.Generator Instruction extensionInstruction = new Instruction(Op.OpExtension); extensionInstruction.AddOperand(extension); - extensionInstruction.Write(stream); + extensionInstruction.Write(writer); } // 3. foreach (Instruction extInstImport in _extInstImports) { - extInstImport.Write(stream); + extInstImport.Write(writer); } // 4. Instruction memoryModelInstruction = new Instruction(Op.OpMemoryModel); memoryModelInstruction.AddOperand(_addressingModel); memoryModelInstruction.AddOperand(_memoryModel); - memoryModelInstruction.Write(stream); + memoryModelInstruction.Write(writer); // 5. foreach (Instruction entrypoint in _entrypoints) { - entrypoint.Write(stream); + entrypoint.Write(writer); } // 6. foreach (Instruction executionMode in _executionModes) { - executionMode.Write(stream); + executionMode.Write(writer); } // 7. // TODO: order debug information correclty. foreach (Instruction debug in _debug) { - debug.Write(stream); + debug.Write(writer); } // 8. foreach (Instruction annotation in _annotations) { - annotation.Write(stream); + annotation.Write(writer); } // Ensure that everything is in the right order in the declarations section @@ -320,19 +320,19 @@ namespace Spv.Generator // 9. foreach (Instruction declaration in declarations) { - declaration.Write(stream); + declaration.Write(writer); } // 10. foreach (Instruction functionDeclaration in _functionsDeclarations) { - functionDeclaration.Write(stream); + functionDeclaration.Write(writer); } // 11. foreach (Instruction functionDefinition in _functionsDefinitions) { - functionDefinition.Write(stream); + functionDefinition.Write(writer); } return stream.ToArray(); diff --git a/Spv.Generator/Operand.cs b/Spv.Generator/Operand.cs index b180105a0..eaa2e13e0 100644 --- a/Spv.Generator/Operand.cs +++ b/Spv.Generator/Operand.cs @@ -9,6 +9,6 @@ namespace Spv.Generator ushort WordCount { get; } - void WriteOperand(Stream stream); + void WriteOperand(BinaryWriter writer); } }