1
- //
2
- // Copyright (c) Petr Šrámek. All rights reserved.
3
- // Licensed under the MIT License. See LICENSE file in the project root for full license information.
4
- //
5
-
6
- namespace DropoutCoder . PolylineAlgorithm . Implementation . Benchmarks
1
+ namespace DropoutCoder . PolylineAlgorithm . Implementation . Benchmarks
7
2
{
8
3
using BenchmarkDotNet . Attributes ;
9
4
using BenchmarkDotNet . Engines ;
5
+ using DropoutCoder . PolylineAlgorithm . Validation ;
10
6
using System ;
11
7
12
8
[ MemoryDiagnoser ]
13
9
public class DecodePerformanceBenchmark
14
10
{
15
11
private Consumer _consumer = new Consumer ( ) ;
16
-
17
- [ Params ( 10_000 ) ]
18
- public int N { get ; set ; }
19
-
20
- public static IEnumerable < ( int , char [ ] ) > Polylines ( )
12
+ public static IEnumerable < ( int , string ) > Polylines ( )
21
13
{
22
- yield return ( 1 , "mz}lHssngJj`gqSnx~lEcovfTnms{Zdy~qQj_deI" . ToCharArray ( ) ) ;
23
- yield return ( 2 , "}vwdGjafcRsvjKi}pxUhsrtCngtcAjjgzEdqvtLrscbKj}nr@wetlUc`nq]}_kfCyrfaK~wluUl`u}|@wa{lUmmuap@va{lU~oihCu||bF`|era@wsnnIjny{DxamaScqxza@dklDf{}kb@mtpeCavfzGqhx`Wyzzkm@jm`d@dba~Pppkg@h}pxU|rtnHp|flA|~xaPuykyN}fhv[h}pxUx~p}Ymx`sZih~iB{edwB" . ToCharArray ( ) ) ;
24
- yield return ( 3 , "}adrJh}}cVazlw@uykyNhaqeE`vfzG_~kY}~`eTsr{~Cwn~aOty_g@thapJvvoqKxt{sStfahDmtvmIfmiqBhjq|HujpgComs{Z}dhdKcidPymnvBqmquE~qrfI`x{lPf|ftGn~}d_@q}saAurjmu@bwr_DxrfaK~{rO~bidPwfduXwlioFlpum@twvfFpmi~VzxcsOqyejYhh|i@pbnr[twvfF_ueUujvbSa_d~ZkcnjZla~f[pmquEebxo[j}nr@xnn|H{gyiKbh{yH`oenn@y{mpIrbd~EmipgH}fuov@hjqtTp|flAttvkFrym_d@|eyCwn~aOfvdNmeawM??{yxdUcidPca{}D_atqGenzcAlra{@trgWhn{aZ??tluqOgu~sH" . ToCharArray ( ) ) ;
14
+ yield return ( 1 , "mz}lHssngJj`gqSnx~lEcovfTnms{Zdy~qQj_deI" ) ;
15
+ yield return ( 2 , "}vwdGjafcRsvjKi}pxUhsrtCngtcAjjgzEdqvtLrscbKj}nr@wetlUc`nq]}_kfCyrfaK~wluUl`u}|@wa{lUmmuap@va{lU~oihCu||bF`|era@wsnnIjny{DxamaScqxza@dklDf{}kb@mtpeCavfzGqhx`Wyzzkm@jm`d@dba~Pppkg@h}pxU|rtnHp|flA|~xaPuykyN}fhv[h}pxUx~p}Ymx`sZih~iB{edwB" ) ;
16
+ yield return ( 3 , "}adrJh}}cVazlw@uykyNhaqeE`vfzG_~kY}~`eTsr{~Cwn~aOty_g@thapJvvoqKxt{sStfahDmtvmIfmiqBhjq|HujpgComs{Z}dhdKcidPymnvBqmquE~qrfI`x{lPf|ftGn~}d_@q}saAurjmu@bwr_DxrfaK~{rO~bidPwfduXwlioFlpum@twvfFpmi~VzxcsOqyejYhh|i@pbnr[twvfF_ueUujvbSa_d~ZkcnjZla~f[pmquEebxo[j}nr@xnn|H{gyiKbh{yH`oenn@y{mpIrbd~EmipgH}fuov@hjqtTp|flAttvkFrym_d@|eyCwn~aOfvdNmeawM??{yxdUcidPca{}D_atqGenzcAlra{@trgWhn{aZ??tluqOgu~sH" ) ;
25
17
}
26
18
27
19
[ Benchmark ( Baseline = true ) ]
28
20
[ ArgumentsSource ( nameof ( Polylines ) ) ]
29
- public void Decode_V1 ( ( int , char [ ] ) arg ) => V1 . Decode ( arg . Item2 ) . Consume ( _consumer ) ;
21
+ public void Decode_V1 ( ( int , string ) arg ) => For . Loop ( 1001 , ( ) => V1 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
22
+
23
+ [ Benchmark ]
24
+ [ ArgumentsSource ( nameof ( Polylines ) ) ]
25
+ public void Decode_V2 ( ( int , string ) arg ) => For . Loop ( 1001 , ( ) => V2 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
26
+
27
+ [ Benchmark ]
28
+ [ ArgumentsSource ( nameof ( Polylines ) ) ]
29
+ public void Decode_V3 ( ( int , string ) arg ) => For . Loop ( 1001 , ( ) => V3 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
30
30
31
31
[ Benchmark ]
32
32
[ ArgumentsSource ( nameof ( Polylines ) ) ]
33
- public void Decode_V2 ( ( int , char [ ] ) arg ) => V2 . Decode ( arg . Item2 ) . Consume ( _consumer ) ;
33
+ public void Decode_V1_Parallel ( ( int , string ) arg ) => Parallel . For ( 0 , 1001 , new ParallelOptions { MaxDegreeOfParallelism = 10 } , ( i ) => V1 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
34
34
35
35
[ Benchmark ]
36
36
[ ArgumentsSource ( nameof ( Polylines ) ) ]
37
- public void Decode_V3 ( ( int , char [ ] ) arg ) => V3 . Decode ( arg . Item2 ) . Consume ( _consumer ) ;
37
+ public void Decode_V2_Parallel ( ( int , string ) arg ) => Parallel . For ( 0 , 1001 , new ParallelOptions { MaxDegreeOfParallelism = 10 } , ( i ) => V2 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
38
+
39
+ [ Benchmark ]
40
+ [ ArgumentsSource ( nameof ( Polylines ) ) ]
41
+ public void Decode_V3_Parallel ( ( int , string ) arg ) => Parallel . For ( 0 , 1001 , new ParallelOptions { MaxDegreeOfParallelism = 10 } , ( i ) => V3 . Decode ( arg . Item2 ) . Consume ( _consumer ) ) ;
42
+
38
43
39
44
private class V1
40
45
{
41
- public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( char [ ] polyline )
46
+ public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( string polyline )
42
47
{
43
48
if ( polyline is null || polyline . Length == 0 )
44
49
{
@@ -76,7 +81,7 @@ private class V1
76
81
return result ;
77
82
}
78
83
79
- private static bool TryCalculateNext ( ref char [ ] polyline , ref int index , ref int value )
84
+ private static bool TryCalculateNext ( ref string polyline , ref int index , ref int value )
80
85
{
81
86
int chunk ;
82
87
int sum = 0 ;
@@ -123,7 +128,7 @@ public static bool IsValidLongitude(double longitude)
123
128
124
129
private class V2
125
130
{
126
- public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( char [ ] polyline )
131
+ public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( string polyline )
127
132
{
128
133
if ( polyline is null || polyline . Length == 0 )
129
134
{
@@ -157,7 +162,7 @@ private class V2
157
162
}
158
163
}
159
164
160
- private static bool TryCalculateNext ( ref char [ ] polyline , ref int offset , ref int value )
165
+ private static bool TryCalculateNext ( ref string polyline , ref int offset , ref int value )
161
166
{
162
167
int chunk ;
163
168
int sum = 0 ;
@@ -204,12 +209,12 @@ public static bool IsValidLongitude(double longitude)
204
209
205
210
private class V3
206
211
{
207
- public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( char [ ] polyline )
212
+ public static IEnumerable < ( double Latitude , double Longitude ) > Decode ( string polyline )
208
213
{
209
214
// Checking null and at least one character
210
215
if ( polyline == null || polyline . Length == 0 )
211
216
{
212
- throw new ArgumentException ( nameof ( polyline ) ) ;
217
+ throw new ArgumentException ( String . Empty , nameof ( polyline ) ) ;
213
218
}
214
219
215
220
// Initialize local variables
@@ -223,28 +228,28 @@ private class V3
223
228
// Attempting to calculate next latitude value. If failed exception is thrown
224
229
if ( ! TryCalculateNext ( polyline , ref index , ref latitude ) )
225
230
{
226
- throw new InvalidOperationException ( ) ;
231
+ throw new InvalidOperationException ( String . Empty ) ;
227
232
}
228
233
229
234
// Attempting to calculate next longitude value. If failed exception is thrown
230
235
if ( ! TryCalculateNext ( polyline , ref index , ref longitude ) )
231
236
{
232
- throw new InvalidOperationException ( ) ;
237
+ throw new InvalidOperationException ( String . Empty ) ;
233
238
}
234
239
235
- var coordinate = CreateResult ( GetCoordinate ( latitude ) , GetCoordinate ( longitude ) ) ;
240
+ var coordinate = ( GetCoordinate ( latitude ) , GetCoordinate ( longitude ) ) ;
236
241
237
- if ( ! Validator . IsValid ( coordinate ) )
242
+ // Validating decoded coordinate. If not valid exception is thrown
243
+ if ( ! CoordinateValidator . IsValid ( coordinate ) )
238
244
{
239
- throw new InvalidOperationException ( ) ;
245
+ throw new InvalidOperationException ( String . Empty ) ;
240
246
}
241
247
242
248
yield return coordinate ;
243
249
244
-
245
250
#region Local functions
246
251
247
- bool TryCalculateNext ( char [ ] polyline , ref int index , ref int value )
252
+ bool TryCalculateNext ( string polyline , ref int index , ref int value )
248
253
{
249
254
// Local variable initialization
250
255
int chunk ;
@@ -274,47 +279,16 @@ double GetCoordinate(int value)
274
279
#endregion
275
280
}
276
281
}
282
+ }
277
283
278
- protected static ( double Latitude , double Longitude ) CreateResult ( double latitude , double longitude )
279
- {
280
- return ( latitude , longitude ) ;
281
- }
282
-
283
- public static class Validator
284
+ internal class For
285
+ {
286
+ public static void Loop ( int count , Action action )
284
287
{
285
- #region Methods
286
-
287
- /// <summary>
288
- /// Performs coordinate validation
289
- /// </summary>
290
- /// <param name="coordinate">Coordinate to validate</param>
291
- /// <returns>Returns validation result. If valid then true, otherwise false.</returns>
292
- public static bool IsValid ( ( double Latitude , double Longitude ) coordinate )
288
+ for ( int i = 0 ; i < count ; i ++ )
293
289
{
294
- return IsValidLatitude ( ref coordinate . Latitude ) && IsValidLongitude ( ref coordinate . Longitude ) ;
290
+ action . Invoke ( ) ;
295
291
}
296
-
297
- /// <summary>
298
- /// Performs latitude validation
299
- /// </summary>
300
- /// <param name="latitude">Latitude value to validate</param>
301
- /// <returns>Returns validation result. If valid then true, otherwise false.</returns>
302
- private static bool IsValidLatitude ( ref readonly double latitude )
303
- {
304
- return latitude >= Constants . Coordinate . MinLatitude && latitude <= Constants . Coordinate . MaxLatitude ;
305
- }
306
-
307
- /// <summary>
308
- /// Performs longitude validation
309
- /// </summary>
310
- /// <param name="longitude">Longitude value to validate</param>
311
- /// <returns>Returns validation result. If valid then true, otherwise false.</returns>
312
- private static bool IsValidLongitude ( ref readonly double longitude )
313
- {
314
- return longitude >= Constants . Coordinate . MinLongitude && longitude <= Constants . Coordinate . MaxLongitude ;
315
- }
316
-
317
- #endregion
318
292
}
319
293
}
320
294
}
0 commit comments