Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

<ItemGroup>
<Compile Remove="C:\Users\petesramek\.nuget\packages\microsoft.visualstudio.diagnosticshub.benchmarkdotnetdiagnosers\18.3.36812.1\contentFiles\cs\any\BenchmarkProfilerAgentConfig.g.cs" />
<Compile Remove="C:\Users\petesramek\.nuget\packages\microsoft.visualstudio.diagnosticshub.benchmarkdotnetdiagnosers\18.6.37110.2\contentFiles\cs\any\BenchmarkProfilerAgentConfig.g.cs" />
</ItemGroup>

<ItemGroup>
Expand Down
195 changes: 92 additions & 103 deletions benchmarks/PolylineAlgorithm.Benchmarks/PolylineEncoderBenchmark.cs
Original file line number Diff line number Diff line change
@@ -1,103 +1,92 @@
////
//// Copyright © Pete Sramek. All rights reserved.
//// Licensed under the MIT License. See LICENSE file in the project root for full license information.
////

//namespace PolylineAlgorithm.Benchmarks;

//using BenchmarkDotNet.Attributes;
//using BenchmarkDotNet.Engines;
//using PolylineAlgorithm.Utility;
//using System.Collections.Generic;

///// <summary>
///// Benchmarks for <see cref="PolylineEncoder"/>.
///// </summary>
//public class PolylineEncoderBenchmark {
// private readonly Consumer _consumer = new();

// /// <summary>
// /// Number of coordinates for benchmarks.
// /// </summary>
// [Params(1, 100, 1_000)]
// public int CoordinatesCount { get; set; }

//#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
// /// <summary>
// /// Coordinates as list.
// /// </summary>
// public List<(double Latitude, double Longitude)> List { get; private set; }

// /// <summary>
// /// Coordinates as array.
// /// </summary>
// public (double Latitude, double Longitude)[] Array { get; private set; }

// /// <summary>
// /// Coordinates as read-only memory.
// /// </summary>
// public ReadOnlyMemory<(double Latitude, double Longitude)> Memory { get; private set; }

//#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.

// /// <summary>
// /// Polyline encoder instance.
// /// </summary>
// private readonly StringPolylineEncoder _stringEncoder = new();

// /// <summary>
// /// Polyline encoder instance.
// /// </summary>
// private readonly CharArrayPolylineEncoder _charArrayEncoder = new();

// /// <summary>
// /// Polyline encoder instance.
// /// </summary>
// private readonly MemoryPolylineEncoder _memoryEncoder = new();

// /// <summary>
// /// Sets up benchmark data.
// /// </summary>
// [GlobalSetup]
// public void SetupData() {
// List = [.. RandomValueProvider.GetCoordinates(CoordinatesCount).Select(c => (c.Latitude, c.Longitude))];
// Array = [.. List];
// Memory = Array.AsMemory();
// }

// /// <summary>
// /// Benchmark: encode coordinates from span.
// /// </summary>
// /// <returns>Encoded polyline.</returns>
// [Benchmark]
// public void PolylineEncoder_Encode_Span() {
// var polyline = _encoder
// .Encode(Memory.Span!);

// _consumer.Consume(polyline);
// }

// /// <summary>
// /// Benchmark: encode coordinates from array.
// /// </summary>
// /// <returns>Encoded polyline.</returns>
// [Benchmark]
// public void PolylineEncoder_Encode_Array() {
// var polyline = _encoder
// .Encode(Array!);

// _consumer.Consume(polyline);
// }

// /// <summary>
// /// Benchmark: encode coordinates from list.
// /// </summary>
// /// <returns>Encoded polyline.</returns>
// [Benchmark]
// public void PolylineEncoder_Encode_List() {
// var polyline = _encoder
// .Encode(List!);

// _consumer.Consume(polyline);
// }
//}
//
// Copyright © Pete Sramek. All rights reserved.
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//

namespace PolylineAlgorithm.Benchmarks;

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Engines;
using PolylineAlgorithm.Abstraction;
using PolylineAlgorithm.Extensions;
using PolylineAlgorithm.Utility;
using System.Collections.Generic;

/// <summary>
/// Benchmarks for <see cref="AbstractPolylineEncoder{TCoordinate, TPolyline}"/>.
/// </summary>
public class PolylineEncoderBenchmark {
private readonly Consumer _consumer = new();

/// <summary>
/// Number of coordinates for benchmarks.
/// </summary>
[Params(1, 100, 1_000)]
public int CoordinatesCount { get; set; }

#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.
/// <summary>
/// Coordinates as list.
/// </summary>
public List<(double Latitude, double Longitude)> List { get; private set; }

/// <summary>
/// Coordinates as array.
/// </summary>
public (double Latitude, double Longitude)[] Array { get; private set; }

/// <summary>
/// Coordinates as read-only memory.
/// </summary>
public ReadOnlyMemory<(double Latitude, double Longitude)> Memory { get; private set; }

#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring as nullable.

/// <summary>
/// Polyline encoder instance.
/// </summary>
private readonly StringPolylineEncoder _encoder = new();

/// <summary>
/// Sets up benchmark data.
/// </summary>
[GlobalSetup]
public void SetupData() {
List = [.. RandomValueProvider.GetCoordinates(CoordinatesCount)];
Array = [.. List];
Memory = Array.AsMemory();
}

/// <summary>
/// Benchmark: encode coordinates from span.
/// </summary>
[Benchmark]
public void PolylineEncoder_Encode_Span() {
var polyline = _encoder.Encode(Memory.Span);
_consumer.Consume(polyline);
}

/// <summary>
/// Benchmark: encode coordinates from array.
/// </summary>
[Benchmark]
public void PolylineEncoder_Encode_Array() {
var polyline = _encoder.Encode(Array);
_consumer.Consume(polyline);
}

/// <summary>
/// Benchmark: encode coordinates from list.
/// </summary>
[Benchmark]
public void PolylineEncoder_Encode_List() {
var polyline = _encoder.Encode(List);
_consumer.Consume(polyline);
}

private sealed class StringPolylineEncoder : AbstractPolylineEncoder<(double Latitude, double Longitude), string> {
protected override string CreatePolyline(ReadOnlyMemory<char> polyline) => polyline.ToString();
protected override double GetLatitude((double Latitude, double Longitude) current) => current.Latitude;
protected override double GetLongitude((double Latitude, double Longitude) current) => current.Longitude;
}
}
25 changes: 1 addition & 24 deletions src/PolylineAlgorithm/Abstraction/AbstractPolylineDecoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@
//

using Microsoft.Extensions.Logging;
using PolylineAlgorithm.Diagnostics;
using PolylineAlgorithm.Internal;
using PolylineAlgorithm.Internal.Diagnostics;
using PolylineAlgorithm.Internal.Diagnostics;
using System.Runtime.CompilerServices;

namespace PolylineAlgorithm.Abstraction {
Expand Down Expand Up @@ -54,27 +52,6 @@ protected AbstractPolylineDecoder(PolylineEncodingOptions options) {
/// </summary>
public PolylineEncodingOptions Options { get; }

/// <summary>
/// Decodes an encoded <typeparamref name="TPolyline"/> into a sequence of <typeparamref name="TCoordinate"/> instances.
/// </summary>
/// <param name="polyline">
/// The <typeparamref name="TPolyline"/> instance containing the encoded polyline string to decode.
/// </param>
/// <returns>
/// An <see cref="IEnumerable{T}"/> of <typeparamref name="TCoordinate"/> representing the decoded latitude and longitude pairs.
/// </returns>
/// <exception cref="ArgumentNullException">
/// Thrown when <paramref name="polyline"/> is <see langword="null"/>.
/// </exception>
/// <exception cref="ArgumentException">
/// Thrown when <paramref name="polyline"/> is empty.
/// </exception>
/// <exception cref="InvalidPolylineException">
/// Thrown when the polyline format is invalid or malformed at a specific position.
/// </exception>
public IEnumerable<TCoordinate> Decode(TPolyline polyline)
=> Decode(polyline, CancellationToken.None);

/// <summary>
/// Decodes an encoded <typeparamref name="TPolyline"/> into a sequence of <typeparamref name="TCoordinate"/> instances,
/// with support for cancellation.
Expand All @@ -100,7 +77,7 @@ public IEnumerable<TCoordinate> Decode(TPolyline polyline)
/// <exception cref="OperationCanceledException">
/// Thrown when <paramref name="cancellationToken"/> is canceled during decoding.
/// </exception>
public IEnumerable<TCoordinate> Decode(TPolyline polyline, CancellationToken cancellationToken) {
public IEnumerable<TCoordinate> Decode(TPolyline polyline, CancellationToken cancellationToken = default) {
const string OperationName = nameof(Decode);

_logger?.LogOperationStartedDebug(OperationName);
Expand Down
10 changes: 7 additions & 3 deletions src/PolylineAlgorithm/Abstraction/AbstractPolylineEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ namespace PolylineAlgorithm.Abstraction;
using PolylineAlgorithm;
using PolylineAlgorithm.Internal;
using PolylineAlgorithm.Internal.Diagnostics;
using PolylineAlgorithm.Internal.Diagnostics;
using System;
using System.Buffers;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Threading;

/// <summary>
/// Provides a base implementation for encoding sequences of geographic coordinates into encoded polyline strings.
Expand Down Expand Up @@ -61,6 +61,9 @@ protected AbstractPolylineEncoder(PolylineEncodingOptions options) {
/// <param name="coordinates">
/// The collection of <typeparamref name="TCoordinate"/> objects to encode.
/// </param>
/// <param name="cancellationToken">
/// A <see cref="CancellationToken"/> that can be used to cancel the encoding operation.
/// </param>
/// <returns>
/// An instance of <typeparamref name="TPolyline"/> representing the encoded coordinates.
/// </returns>
Expand All @@ -74,7 +77,7 @@ protected AbstractPolylineEncoder(PolylineEncodingOptions options) {
/// Thrown when the internal encoding buffer cannot accommodate the encoded value.
/// </exception>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Design", "MA0051:Method is too long", Justification = "Method contains local methods. Actual method only 55 lines.")]
public TPolyline Encode(ReadOnlySpan<TCoordinate> coordinates) {
public TPolyline Encode(ReadOnlySpan<TCoordinate> coordinates, CancellationToken cancellationToken = default) {
const string OperationName = nameof(Encode);

_logger
Expand All @@ -98,6 +101,7 @@ public TPolyline Encode(ReadOnlySpan<TCoordinate> coordinates) {

try {
for (var i = 0; i < coordinates.Length; i++) {
cancellationToken.ThrowIfCancellationRequested();

delta
.Next(
Expand Down Expand Up @@ -150,7 +154,7 @@ static void ValidateEmptyCoordinates(ref ReadOnlySpan<TCoordinate> coordinates,
logger
.LogEmptyArgumentWarning(nameof(coordinates));

ExceptionGuard.ThrwoArgumentCannotBeEmptyEnumerationMessage(nameof(coordinates));
ExceptionGuard.ThrowArgumentCannotBeEmptyEnumerationMessage(nameof(coordinates));
}
}
}
Expand Down
86 changes: 0 additions & 86 deletions src/PolylineAlgorithm/Extensions/PolylineDecoderExtensions.cs

This file was deleted.

Loading
Loading