Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions benchmark/BooleanAttributesBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using BenchmarkDotNet.Attributes;
using Mapbox.Vector.Tile;
using System;
using System.Collections.Generic;
using System.IO;

namespace mapbox.vector.tile.benchmark;

/// <summary>
/// Benchmarks parsing of a tile with many boolean attributes, to measure
/// the impact of the pre-boxed Boxes.Boolean_True/False optimisation.
/// </summary>
[MemoryDiagnoser]
public class BooleanAttributesBenchmark
{
private MemoryStream _tileStream = null!;

[GlobalSetup]
public void Setup()
{
const int featureCount = 100_000;
const uint extent = 4096;

var attributes = new List<KeyValuePair<string, object>>
{
new("is_active", true),
new("is_visible", true),
new("is_selected", false),
new("has_children", false),
new("is_root", true),
};

var features = new List<VectorTileFeature>(featureCount);
for (var i = 0; i < featureCount; i++)
{
var geometry = new List<ArraySegment<Coordinate>>
{
new([new Coordinate { X = 0, Y = 0 }]),
};
features.Add(new VectorTileFeature(
id: i.ToString(),
geometry: geometry,
attributes: attributes,
geometryType: Tile.GeomType.Point,
extent: extent));
}

var layer = new VectorTileLayer("bool_layer", 2, extent)
{
VectorTileFeatures = features,
};

var buffer = new MemoryStream();
VectorTileEncoder.Encode([layer], buffer);
_tileStream = new MemoryStream(buffer.ToArray());
}

[IterationSetup]
public void ResetStream() => _tileStream.Position = 0;

[Benchmark]
public List<VectorTileLayer> ParseBooleanAttributeTile()
{
_tileStream.Position = 0;
return VectorTileParser.Parse(_tileStream);
}
}
3 changes: 2 additions & 1 deletion benchmark/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ class Program
{
static void Main(string[] args)
{
var summary = BenchmarkRunner.Run<ParsingBenchmark>();
BenchmarkRunner.Run<ParsingBenchmark>();
BenchmarkRunner.Run<BooleanAttributesBenchmark>();
Console.ReadKey();
}
}
12 changes: 12 additions & 0 deletions benchmark/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"profiles": {
"BooleanAttributes": {
"commandName": "Project",
"commandLineArgs": "BooleanAttributes"
},
"Parsing": {
"commandName": "Project",
"commandLineArgs": "Parsing"
}
}
}
87 changes: 50 additions & 37 deletions src/AttributesParser.cs
Original file line number Diff line number Diff line change
@@ -1,60 +1,73 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace Mapbox.Vector.Tile;

public static class AttributesParser
{
public static List<KeyValuePair<string, object>> Parse(List<string> keys, List<Tile.Value> values, List<uint> tags)
{
var result = new List<KeyValuePair<string, object>>();
var odds = tags.GetOdds().ToList();
var evens = tags.GetEvens().ToList();
var result = new List<KeyValuePair<string, object>>(keys.Count);
Comment thread
Artfunkel marked this conversation as resolved.

for (var i = 0; i < evens.Count; i++)
for (var i = 0; i < tags.Count; i += 2)
{
var key = keys[(int)evens[i]];
var val = values[(int)odds[i]];
var valObject = GetAttr(val);
result.Add(new KeyValuePair<string, object>(key, valObject));
var key = keys[(int)tags[i]];
var val = values[(int)tags[i + 1]];
result.Add(new(key, GetAttr(val)));
Comment thread
bertt marked this conversation as resolved.
}
return result;
}

private static object GetAttr(Tile.Value value)
private static object GetAttr(Tile.Value value) => value switch
{
if (value.HasBoolValue)
{ HasStringValue: true } => value.StringValue,
{ HasBoolValue: true } => value.BoolValue ? Boxes.Boolean_True : Boxes.Boolean_False,

{ HasDoubleValue: true } => value.DoubleValue switch
{
return value.BoolValue;
}
else if (value.HasDoubleValue)
{
return value.DoubleValue;
}
else if (value.HasFloatValue)
{
return value.FloatValue;
}
else if (value.HasIntValue)
{
return value.IntValue;
}
else if (value.HasStringValue)
0 => Boxes.Double_0,
1 => Boxes.Double_1,
_ => value.DoubleValue,
},
{ HasFloatValue: true } => value.FloatValue switch
{
return value.StringValue;
}
else if (value.HasSIntValue)
0 => Boxes.Single_0,
1 => Boxes.Single_1,
_ => value.FloatValue,
},
{ HasIntValue: true } => value.IntValue switch
{
return value.SintValue;
}
else if (value.HasUIntValue)
0 => Boxes.Int64_0,
1 => Boxes.Int64_1,
_ => value.IntValue,
},
{ HasSIntValue: true } => value.SintValue switch
{
return value.UintValue;
}
else
0 => Boxes.Int64_0,
1 => Boxes.Int64_1,
_ => value.SintValue,
},
{ HasUIntValue: true } => value.UintValue switch
{
throw new NotImplementedException("Unknown attribute type");
}
0 => Boxes.UInt64_0,
1 => Boxes.UInt64_1,
_ => value.UintValue,
},

_ => throw new NotImplementedException("Unknown attribute type"),
};

private static class Boxes
{
public static readonly object Boolean_True = true;
public static readonly object Boolean_False = false;
public static readonly object Int64_0 = 0L;
public static readonly object Int64_1 = 1L;
public static readonly object Single_0 = 0f;
public static readonly object Single_1 = 1f;
public static readonly object Double_0 = 0d;
public static readonly object Double_1 = 1d;
public static readonly object UInt64_0 = 0ul;
public static readonly object UInt64_1 = 1ul;
}
}
17 changes: 0 additions & 17 deletions src/ExtensionMethods/IEnumerableExtensions.cs

This file was deleted.

3 changes: 2 additions & 1 deletion src/VectorTileParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ public static class VectorTileParser
public static List<VectorTileLayer> Parse(Stream stream)
{
var tile = Serializer.Deserialize<Tile>(stream);
var list = new List<VectorTileLayer>();
var list = new List<VectorTileLayer>(tile.Layers.Count);
foreach (var layer in tile.Layers)
{
var extent = layer.Extent;
var vectorTileLayer = new VectorTileLayer(layer.Name ?? "[Unnamed]", layer.Version, extent);
vectorTileLayer.VectorTileFeatures.Capacity = layer.Features.Count;

foreach (var feature in layer.Features)
{
Expand Down
36 changes: 0 additions & 36 deletions tests/IEnumerableExtensionTests.cs

This file was deleted.

Loading