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
5 changes: 4 additions & 1 deletion .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ jobs:
BASE_BUILT: ${{ steps.build_base.outcome == 'success' }}
run: |
DLL=tests/EncDotNet.Benchmarks/bin/Release/net10.0/EncDotNet.Benchmarks.dll
ARGS=(--filter '*' --exporters json --warmupCount 3 --iterationCount 10 --launchCount 1)
# BenchmarkDotNet's default 500 ms iterations make each case take 10-15 s however
# fast the operation is. Shorter iterations, with more of them, halve the run time
# while keeping the median as precise (standard error about 2%).
ARGS=(--filter '*' --exporters json --warmupCount 3 --iterationCount 15 --iterationTime 200 --launchCount 1)
if [ "$SCOPE" = "core" ]; then
ARGS+=(--anyCategories Core)
fi
Expand Down
49 changes: 43 additions & 6 deletions scripts/DownloadBenchmarkCells.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,17 @@
using EncDotNet.Noaa;

// ============================================================================
// DownloadBenchmarkCells.cs — Downloads a fixed set of real NOAA ENC cells for
// DownloadBenchmarkCells.cs — Downloads a few real NOAA ENC cells for
// the benchmarks in tests/EncDotNet.Benchmarks.
//
// Usage: dotnet run scripts/DownloadBenchmarkCells.cs -- <output-dir> [cell...]
//
// Without cell names, the script picks one cell per usage band (harbour, approach
// and coastal) from the live NOAA catalog: among active cells with update files,
// the one at the 90th percentile of download size, so the set is substantial but
// typical. Picking by rule rather than by name survives NOAA withdrawing or
// renaming cells, which it does as it re-schemes its coverage.
//
// Each cell is extracted to <output-dir>/<cell>/ with its update files. Point
// ENCDOTNET_ENC_ROOT at <output-dir> to include them in a benchmark run. The
// script writes <output-dir>/cells.txt recording each cell's edition, update
Expand All @@ -24,9 +30,10 @@
// Never commit the downloaded cells (see CONTRIBUTING.md).
// ============================================================================

// A harbour, an approach and a coastal cell, all with update files. Together they
// cover the range of record counts and edge lengths in typical NOAA cells.
string[] defaultCells = ["US5WA50M", "US4MD81M", "US3WA01M"];
// Navigational purpose (usage band), the third character of the cell file name
// (S-57 Appendix B.1, 5.6.4).
(char Band, string Purpose)[] bands = [('5', "harbour"), ('4', "approach"), ('3', "coastal")];
const double sizePercentile = 0.9;

if (args.Length == 0)
{
Expand All @@ -35,13 +42,43 @@
}

var outputDirectory = Path.GetFullPath(args[0]);
var cellNames = args.Length > 1 ? args[1..] : defaultCells;
Directory.CreateDirectory(outputDirectory);

using var catalogClient = new EncProductCatalogClient();
var catalog = await catalogClient.GetNoaaCatalogAsync();
var cellsByName = catalog.Cells.ToDictionary(c => c.Name, StringComparer.OrdinalIgnoreCase);

string[] cellNames;
if (args.Length > 1)
{
cellNames = args[1..];
}
else
{
var picked = new List<string>();
foreach (var (band, purpose) in bands)
{
var candidates = catalog.Cells
.Where(c => c.Name.Length == 8 && c.Name[2] == band)
.Where(c => c.UpdateNumber > 0 && c.ZipfileSize > 0)
.Where(c => !c.Status.Contains("cancel", StringComparison.OrdinalIgnoreCase))
.OrderBy(c => c.ZipfileSize)
.ThenBy(c => c.Name, StringComparer.Ordinal)
.ToList();
if (candidates.Count == 0)
{
Console.Error.WriteLine($"warning: no active {purpose} cell with updates in the NOAA catalog.");
continue;
}

var cell = candidates[(int)((candidates.Count - 1) * sizePercentile)];
Console.WriteLine($"Picked {cell.Name} as the {purpose} cell ({candidates.Count} candidates, zip {cell.ZipfileSize:N0} bytes).");
picked.Add(cell.Name);
}

cellNames = [.. picked];
}

using var httpClient = new HttpClient();
var manifest = new List<string>();
var missing = 0;
Expand Down Expand Up @@ -96,4 +133,4 @@
}

File.WriteAllLines(Path.Combine(outputDirectory, "cells.txt"), manifest);
return missing == cellNames.Length ? 1 : 0;
return cellNames.Length == 0 || missing == cellNames.Length ? 1 : 0;
2 changes: 1 addition & 1 deletion tests/EncDotNet.PerformanceTests/PerformanceCells.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ internal static class PerformanceCells
private static readonly Lazy<Inputs> LazyHarbourX4 = new(() => new Inputs(SyntheticCellProfile.Harbour.Scale(4)));

/// <summary>
/// Gets the harbour-scale cell, shaped like NOAA US5WA50M.
/// Gets the harbour-scale cell, shaped like an earlier edition of NOAA US5WA50M.
/// </summary>
public static Inputs Harbour => LazyHarbour.Value;

Expand Down
9 changes: 6 additions & 3 deletions tests/Shared/SyntheticCellProfile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ namespace EncDotNet.Testing;
/// <remarks>
/// The built-in profiles are calibrated against real NOAA cells: record counts, the
/// distribution of edge lengths, attributes per feature and spatial pointers per feature
/// follow the measured averages of the cell named in each profile's remarks.
/// follow the measured averages of the cell named in each profile's summary. Those were
/// earlier editions; NOAA has since re-schemed its coverage into smaller cells (edition 36
/// of US4MD81M is about 320 KB), so the larger profiles now stand for the bigger cells an
/// application may still meet rather than for a typical current one.
/// </remarks>
/// <param name="Name">The profile name, used in the generated data set name and in benchmark output.</param>
/// <param name="Seed">The seed for the generator; the same profile always yields the same bytes.</param>
Expand Down Expand Up @@ -35,7 +38,7 @@ public sealed record SyntheticCellProfile(
int AreaFeatures)
{
/// <summary>
/// A harbour-scale cell shaped like NOAA US5WA50M (about 400 KB).
/// A harbour-scale cell shaped like an earlier edition of NOAA US5WA50M (about 400 KB).
/// </summary>
public static SyntheticCellProfile Harbour { get; } = new(
Name: "Harbour",
Expand All @@ -52,7 +55,7 @@ public sealed record SyntheticCellProfile(
AreaFeatures: 211);

/// <summary>
/// An approach-scale cell shaped like NOAA US4MD81M (about 3.5 MB).
/// An approach-scale cell shaped like an earlier edition of NOAA US4MD81M (about 3.5 MB).
/// </summary>
public static SyntheticCellProfile Approach { get; } = new(
Name: "Approach",
Expand Down
Loading