mirror of
https://github.com/dcronqvist/DotTiled.git
synced 2025-02-05 08:52:50 +02:00
Added Tmj parsing to benchmarking
This commit is contained in:
parent
bb74d3ccee
commit
cc57b172a8
6 changed files with 112 additions and 101 deletions
|
@ -15,68 +15,54 @@ namespace MyBenchmarks
|
|||
[GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)]
|
||||
[CategoriesColumn]
|
||||
[Orderer(SummaryOrderPolicy.FastestToSlowest)]
|
||||
[HideColumns(["StdDev", "Error", "RatioSD"])]
|
||||
public class MapLoading
|
||||
{
|
||||
private string _tmxPath = @"C:\Users\Daniel\winrepos\DotTiled\DotTiled.Tests\Serialization\Tmx\TestData\Map\empty-map-csv.tmx";
|
||||
private string _tmxPath = @"C:\Users\Daniel\winrepos\DotTiled\DotTiled.Tests\Serialization\TestData\Map\empty-map-csv.tmx";
|
||||
private string _tmxContents = "";
|
||||
|
||||
private string _tmjPath = @"C:\Users\Daniel\winrepos\DotTiled\DotTiled.Tests\Serialization\TestData\Map\empty-map-csv.tmj";
|
||||
private string _tmjContents = "";
|
||||
|
||||
public MapLoading()
|
||||
{
|
||||
_tmxContents = System.IO.File.ReadAllText(_tmxPath);
|
||||
_tmjContents = System.IO.File.ReadAllText(_tmjPath);
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromInMemoryTmxString")]
|
||||
[Benchmark(Baseline = true, Description = "DotTiled")]
|
||||
public DotTiled.Map LoadWithDotTiledFromInMemoryString()
|
||||
public DotTiled.Map LoadWithDotTiledFromInMemoryTmxString()
|
||||
{
|
||||
using var stringReader = new StringReader(_tmxContents);
|
||||
using var xmlReader = XmlReader.Create(stringReader);
|
||||
using var mapReader = new DotTiled.TmxMapReader(xmlReader, _ => throw new Exception(), _ => throw new Exception());
|
||||
using var mapReader = new DotTiled.TmxMapReader(xmlReader, _ => throw new Exception(), _ => throw new Exception(), []);
|
||||
return mapReader.ReadMap();
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromTmxFile")]
|
||||
[BenchmarkCategory("MapFromInMemoryTmjString")]
|
||||
[Benchmark(Baseline = true, Description = "DotTiled")]
|
||||
public DotTiled.Map LoadWithDotTiledFromFile()
|
||||
public DotTiled.Map LoadWithDotTiledFromInMemoryTmjString()
|
||||
{
|
||||
using var fileStream = System.IO.File.OpenRead(_tmxPath);
|
||||
using var xmlReader = XmlReader.Create(fileStream);
|
||||
using var mapReader = new DotTiled.TmxMapReader(xmlReader, _ => throw new Exception(), _ => throw new Exception());
|
||||
using var mapReader = new DotTiled.TmjMapReader(_tmjContents, _ => throw new Exception(), _ => throw new Exception(), []);
|
||||
return mapReader.ReadMap();
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromInMemoryTmxString")]
|
||||
[Benchmark(Description = "TiledLib")]
|
||||
public TiledLib.Map LoadWithTiledLibFromInMemoryString()
|
||||
public TiledLib.Map LoadWithTiledLibFromInMemoryTmxString()
|
||||
{
|
||||
using var memStream = new MemoryStream(Encoding.UTF8.GetBytes(_tmxContents));
|
||||
return TiledLib.Map.FromStream(memStream);
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromTmxFile")]
|
||||
[Benchmark(Description = "TiledLib")]
|
||||
public TiledLib.Map LoadWithTiledLibFromFile()
|
||||
{
|
||||
using var fileStream = System.IO.File.OpenRead(_tmxPath);
|
||||
var map = TiledLib.Map.FromStream(fileStream);
|
||||
return map;
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromInMemoryTmxString")]
|
||||
[Benchmark(Description = "TiledCSPlus")]
|
||||
public TiledCSPlus.TiledMap LoadWithTiledCSPlusFromInMemoryString()
|
||||
public TiledCSPlus.TiledMap LoadWithTiledCSPlusFromInMemoryTmxString()
|
||||
{
|
||||
using var memStream = new MemoryStream(Encoding.UTF8.GetBytes(_tmxContents));
|
||||
return new TiledCSPlus.TiledMap(memStream);
|
||||
}
|
||||
|
||||
[BenchmarkCategory("MapFromTmxFile")]
|
||||
[Benchmark(Description = "TiledCSPlus")]
|
||||
public TiledCSPlus.TiledMap LoadWithTiledCSPlusFromFile()
|
||||
{
|
||||
using var fileStream = System.IO.File.OpenRead(_tmxPath);
|
||||
return new TiledCSPlus.TiledMap(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
public class Program
|
||||
|
@ -84,6 +70,7 @@ namespace MyBenchmarks
|
|||
public static void Main(string[] args)
|
||||
{
|
||||
var config = BenchmarkDotNet.Configs.DefaultConfig.Instance
|
||||
.WithArtifactsPath(args[0])
|
||||
.WithOptions(ConfigOptions.DisableOptimizationsValidator)
|
||||
.AddDiagnoser(BenchmarkDotNet.Diagnosers.MemoryDiagnoser.Default);
|
||||
var summary = BenchmarkRunner.Run<MapLoading>(config);
|
||||
|
|
62
DotTiled/Serialization/Helpers.Data.cs
Normal file
62
DotTiled/Serialization/Helpers.Data.cs
Normal file
|
@ -0,0 +1,62 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace DotTiled;
|
||||
|
||||
internal static partial class Helpers
|
||||
{
|
||||
internal static class Data
|
||||
{
|
||||
internal static uint[] ReadMemoryStreamAsInt32Array(Stream stream)
|
||||
{
|
||||
var finalValues = new List<uint>();
|
||||
var int32Bytes = new byte[4];
|
||||
while (stream.Read(int32Bytes, 0, 4) == 4)
|
||||
{
|
||||
var value = BitConverter.ToUInt32(int32Bytes, 0);
|
||||
finalValues.Add(value);
|
||||
}
|
||||
return [.. finalValues];
|
||||
}
|
||||
|
||||
internal static uint[] DecompressGZip(MemoryStream stream)
|
||||
{
|
||||
using var decompressedStream = new GZipStream(stream, CompressionMode.Decompress);
|
||||
return ReadMemoryStreamAsInt32Array(decompressedStream);
|
||||
}
|
||||
|
||||
internal static uint[] DecompressZLib(MemoryStream stream)
|
||||
{
|
||||
using var decompressedStream = new ZLibStream(stream, CompressionMode.Decompress);
|
||||
return ReadMemoryStreamAsInt32Array(decompressedStream);
|
||||
}
|
||||
|
||||
internal static uint[] ReadBytesAsInt32Array(byte[] bytes)
|
||||
{
|
||||
var intArray = new uint[bytes.Length / 4];
|
||||
for (var i = 0; i < intArray.Length; i++)
|
||||
{
|
||||
intArray[i] = BitConverter.ToUInt32(bytes, i * 4);
|
||||
}
|
||||
|
||||
return intArray;
|
||||
}
|
||||
|
||||
internal static (uint[] GlobalTileIDs, FlippingFlags[] FlippingFlags) ReadAndClearFlippingFlagsFromGIDs(uint[] globalTileIDs)
|
||||
{
|
||||
var clearedGlobalTileIDs = new uint[globalTileIDs.Length];
|
||||
var flippingFlags = new FlippingFlags[globalTileIDs.Length];
|
||||
for (var i = 0; i < globalTileIDs.Length; i++)
|
||||
{
|
||||
var gid = globalTileIDs[i];
|
||||
var flags = gid & 0xF0000000u;
|
||||
flippingFlags[i] = (FlippingFlags)flags;
|
||||
clearedGlobalTileIDs[i] = gid & 0x0FFFFFFFu;
|
||||
}
|
||||
|
||||
return (clearedGlobalTileIDs, flippingFlags);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ internal partial class Tmj
|
|||
{
|
||||
// Array of uint
|
||||
var data = element.GetValueAsList<uint>(e => e.GetValueAs<uint>()).ToArray();
|
||||
var (globalTileIDs, flippingFlags) = ReadAndClearFlippingFlagsFromGIDs(data);
|
||||
var (globalTileIDs, flippingFlags) = Helpers.Data.ReadAndClearFlippingFlagsFromGIDs(data);
|
||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
||||
}
|
||||
else if (encoding == DataEncoding.Base64)
|
||||
|
@ -58,75 +58,25 @@ internal partial class Tmj
|
|||
|
||||
if (compression == null)
|
||||
{
|
||||
var data = ReadBytesAsInt32Array(base64Data);
|
||||
var (globalTileIDs, flippingFlags) = ReadAndClearFlippingFlagsFromGIDs(data);
|
||||
var data = Helpers.Data.ReadBytesAsInt32Array(base64Data);
|
||||
var (globalTileIDs, flippingFlags) = Helpers.Data.ReadAndClearFlippingFlagsFromGIDs(data);
|
||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
||||
}
|
||||
|
||||
using var stream = new MemoryStream(base64Data);
|
||||
var decompressed = compression switch
|
||||
{
|
||||
DataCompression.GZip => DecompressGZip(stream),
|
||||
DataCompression.ZLib => DecompressZLib(stream),
|
||||
DataCompression.GZip => Helpers.Data.DecompressGZip(stream),
|
||||
DataCompression.ZLib => Helpers.Data.DecompressZLib(stream),
|
||||
_ => throw new JsonException($"Unsupported compression '{compression}'.")
|
||||
};
|
||||
|
||||
{
|
||||
var (globalTileIDs, flippingFlags) = ReadAndClearFlippingFlagsFromGIDs(decompressed);
|
||||
var (globalTileIDs, flippingFlags) = Helpers.Data.ReadAndClearFlippingFlagsFromGIDs(decompressed);
|
||||
return new Data { Encoding = encoding, Compression = compression, GlobalTileIDs = globalTileIDs, FlippingFlags = flippingFlags, Chunks = null };
|
||||
}
|
||||
}
|
||||
|
||||
throw new JsonException($"Unsupported encoding '{encoding}'.");
|
||||
}
|
||||
|
||||
internal static uint[] ReadMemoryStreamAsInt32Array(Stream stream)
|
||||
{
|
||||
var finalValues = new List<uint>();
|
||||
var int32Bytes = new byte[4];
|
||||
while (stream.Read(int32Bytes, 0, 4) == 4)
|
||||
{
|
||||
var value = BitConverter.ToUInt32(int32Bytes, 0);
|
||||
finalValues.Add(value);
|
||||
}
|
||||
return finalValues.ToArray();
|
||||
}
|
||||
|
||||
internal static uint[] DecompressGZip(MemoryStream stream)
|
||||
{
|
||||
using var decompressedStream = new GZipStream(stream, CompressionMode.Decompress);
|
||||
return ReadMemoryStreamAsInt32Array(decompressedStream);
|
||||
}
|
||||
|
||||
internal static uint[] DecompressZLib(MemoryStream stream)
|
||||
{
|
||||
using var decompressedStream = new ZLibStream(stream, CompressionMode.Decompress);
|
||||
return ReadMemoryStreamAsInt32Array(decompressedStream);
|
||||
}
|
||||
|
||||
internal static uint[] ReadBytesAsInt32Array(byte[] bytes)
|
||||
{
|
||||
var intArray = new uint[bytes.Length / 4];
|
||||
for (var i = 0; i < intArray.Length; i++)
|
||||
{
|
||||
intArray[i] = BitConverter.ToUInt32(bytes, i * 4);
|
||||
}
|
||||
|
||||
return intArray;
|
||||
}
|
||||
|
||||
internal static (uint[] GlobalTileIDs, FlippingFlags[] FlippingFlags) ReadAndClearFlippingFlagsFromGIDs(uint[] globalTileIDs)
|
||||
{
|
||||
var clearedGlobalTileIDs = new uint[globalTileIDs.Length];
|
||||
var flippingFlags = new FlippingFlags[globalTileIDs.Length];
|
||||
for (var i = 0; i < globalTileIDs.Length; i++)
|
||||
{
|
||||
var gid = globalTileIDs[i];
|
||||
var flags = gid & 0xF0000000u;
|
||||
flippingFlags[i] = (FlippingFlags)flags;
|
||||
clearedGlobalTileIDs[i] = gid & 0x0FFFFFFFu;
|
||||
}
|
||||
|
||||
return (clearedGlobalTileIDs, flippingFlags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ internal partial class Tmj
|
|||
"grid" => TileRenderSize.Grid,
|
||||
_ => throw new JsonException($"Unknown tile render size '{s}'")
|
||||
}, TileRenderSize.Tile);
|
||||
var tiles = element.GetOptionalPropertyCustom<List<Tile>>("tiles", el => ReadTiles(el, customTypeDefinitions), []);
|
||||
var tiles = element.GetOptionalPropertyCustom<List<Tile>>("tiles", el => ReadTiles(el, externalTemplateResolver, customTypeDefinitions), []);
|
||||
var tileWidth = element.GetOptionalProperty<uint?>("tilewidth", null);
|
||||
var transparentColor = element.GetOptionalPropertyParseable<Color?>("transparentcolor", s => Color.Parse(s, CultureInfo.InvariantCulture), null);
|
||||
var type = element.GetOptionalProperty<string?>("type", null);
|
||||
|
@ -159,10 +159,11 @@ internal partial class Tmj
|
|||
|
||||
internal static List<Tile> ReadTiles(
|
||||
JsonElement element,
|
||||
Func<string, Template> externalTemplateResolver,
|
||||
IReadOnlyCollection<CustomTypeDefinition> customTypeDefinitions) =>
|
||||
element.GetValueAsList<Tile>(e =>
|
||||
{
|
||||
//var animation = e.GetOptionalPropertyCustom<List<Frame>>("animation", ReadFrames, null);
|
||||
var animation = e.GetOptionalPropertyCustom<List<Frame>>("animation", e => e.GetValueAsList<Frame>(ReadFrame), null);
|
||||
var id = e.GetRequiredProperty<uint>("id");
|
||||
var image = e.GetOptionalProperty<string?>("image", null);
|
||||
var imageHeight = e.GetOptionalProperty<uint?>("imageheight", null);
|
||||
|
@ -171,7 +172,7 @@ internal partial class Tmj
|
|||
var y = e.GetOptionalProperty<uint>("y", 0);
|
||||
var width = e.GetOptionalProperty<uint>("width", imageWidth ?? 0);
|
||||
var height = e.GetOptionalProperty<uint>("height", imageHeight ?? 0);
|
||||
//var objectGroup = e.GetOptionalPropertyCustom<ObjectLayer?>("objectgroup", ReadObjectLayer, null);
|
||||
var objectGroup = e.GetOptionalPropertyCustom<ObjectLayer?>("objectgroup", e => ReadObjectLayer(e, externalTemplateResolver, customTypeDefinitions), null);
|
||||
var probability = e.GetOptionalProperty<float>("probability", 1.0f);
|
||||
var properties = e.GetOptionalPropertyCustom<Dictionary<string, IProperty>?>("properties", el => ReadProperties(el, customTypeDefinitions), null);
|
||||
// var terrain, replaced by wangsets
|
||||
|
@ -187,17 +188,29 @@ internal partial class Tmj
|
|||
|
||||
return new Tile
|
||||
{
|
||||
//Animation = animation,
|
||||
Animation = animation,
|
||||
ID = id,
|
||||
Image = imageModel,
|
||||
X = x,
|
||||
Y = y,
|
||||
Width = width,
|
||||
Height = height,
|
||||
//ObjectLayer = objectGroup,
|
||||
ObjectLayer = objectGroup,
|
||||
Probability = probability,
|
||||
Properties = properties,
|
||||
Type = type
|
||||
};
|
||||
});
|
||||
|
||||
internal static Frame ReadFrame(JsonElement element)
|
||||
{
|
||||
var duration = element.GetRequiredProperty<uint>("duration");
|
||||
var tileID = element.GetRequiredProperty<uint>("tileid");
|
||||
|
||||
return new Frame
|
||||
{
|
||||
Duration = duration,
|
||||
TileID = tileID
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
9
Makefile
9
Makefile
|
@ -1,9 +1,10 @@
|
|||
test:
|
||||
dotnet test
|
||||
|
||||
BENCHMARK_SOURCES = DotTiled.Benchmark/Program.cs DotTiled.Benchmark/DotTiled.Benchmark.csproj
|
||||
BENCHMARK_OUTPUTDIR = DotTiled.Benchmark/BenchmarkDotNet.Artifacts
|
||||
.PHONY: benchmark
|
||||
benchmark: DotTiled.Benchmark/BenchmarkDotNet.Artifacts/results/MyBenchmarks.MapLoading-report-github.md
|
||||
benchmark: $(BENCHMARK_OUTPUTDIR)/results/MyBenchmarks.MapLoading-report-github.md
|
||||
|
||||
BENCHMARK_SOURCES = DotTiled.Benchmark/Program.cs
|
||||
DotTiled.Benchmark/BenchmarkDotNet.Artifacts/results/MyBenchmarks.MapLoading-report-github.md: $(BENCHMARK_SOURCES)
|
||||
dotnet run --project DotTiled.Benchmark/DotTiled.Benchmark.csproj -c Release
|
||||
$(BENCHMARK_OUTPUTDIR)/results/MyBenchmarks.MapLoading-report-github.md: $(BENCHMARK_SOURCES)
|
||||
dotnet run --project DotTiled.Benchmark/DotTiled.Benchmark.csproj -c Release -- $(BENCHMARK_OUTPUTDIR)
|
16
README.md
16
README.md
|
@ -60,15 +60,13 @@ BenchmarkDotNet v0.13.12, Windows 10 (10.0.19045.4651/22H2/2022Update)
|
|||
[Host] : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2
|
||||
DefaultJob : .NET 8.0.3 (8.0.324.11423), X64 RyuJIT AVX2
|
||||
```
|
||||
| Method | Categories | Mean | Error | StdDev | Ratio | RatioSD | Gen0 | Gen1 | Allocated | Alloc Ratio |
|
||||
|------------ |------------------------- |----------:|----------:|----------:|------:|--------:|-------:|-------:|----------:|------------:|
|
||||
| DotTiled | MapFromInMemoryTmxString | 2.991 μs | 0.0266 μs | 0.0236 μs | 1.00 | 0.00 | 1.2817 | 0.0610 | 16.37 KB | 1.00 |
|
||||
| TiledLib | MapFromInMemoryTmxString | 5.405 μs | 0.0466 μs | 0.0413 μs | 1.81 | 0.02 | 1.8158 | 0.1068 | 23.32 KB | 1.42 |
|
||||
| TiledCSPlus | MapFromInMemoryTmxString | 6.354 μs | 0.0703 μs | 0.0587 μs | 2.12 | 0.03 | 2.5940 | 0.1831 | 33.23 KB | 2.03 |
|
||||
| | | | | | | | | | | |
|
||||
| DotTiled | MapFromTmxFile | 28.570 μs | 0.1216 μs | 0.1137 μs | 1.00 | 0.00 | 1.0376 | - | 13.88 KB | 1.00 |
|
||||
| TiledCSPlus | MapFromTmxFile | 33.377 μs | 0.1086 μs | 0.1016 μs | 1.17 | 0.01 | 2.8076 | 0.1221 | 36.93 KB | 2.66 |
|
||||
| TiledLib | MapFromTmxFile | 36.077 μs | 0.1900 μs | 0.1777 μs | 1.26 | 0.01 | 2.0752 | 0.1221 | 27.1 KB | 1.95 |
|
||||
| Method | Categories | Mean | Ratio | Gen0 | Gen1 | Allocated | Alloc Ratio |
|
||||
|------------ |------------------------- |---------:|------:|-------:|-------:|----------:|------------:|
|
||||
| DotTiled | MapFromInMemoryTmjString | 4.292 μs | 1.00 | 0.4349 | - | 5.62 KB | 1.00 |
|
||||
| | | | | | | | |
|
||||
| DotTiled | MapFromInMemoryTmxString | 3.075 μs | 1.00 | 1.2817 | 0.0610 | 16.4 KB | 1.00 |
|
||||
| TiledLib | MapFromInMemoryTmxString | 5.574 μs | 1.81 | 1.8005 | 0.0916 | 23.32 KB | 1.42 |
|
||||
| TiledCSPlus | MapFromInMemoryTmxString | 6.546 μs | 2.13 | 2.5940 | 0.1831 | 33.16 KB | 2.02 |
|
||||
|
||||
</details>
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue