Files
astro/internal/occultationgeo/perf_bench_test.go
T

163 lines
4.9 KiB
Go
Raw Normal View History

package occultationgeo
import (
"math"
"sync"
"testing"
"time"
"b612.me/astro/basic"
"b612.me/astro/internal/geodata"
)
var (
saturn20250105Once sync.Once
saturn20250105Paths []basic.PlanetOccultationPath
)
func saturn20250105Path(tb testing.TB) basic.PlanetOccultationPath {
tb.Helper()
saturn20250105Once.Do(func() {
zone := time.FixedZone("UTC+8", 8*60*60)
start := time.Date(2025, time.January, 5, 0, 0, 0, 0, zone)
paths, err := basic.FindPlanetOccultationPaths(
start, start.Add(24*time.Hour), basic.OccultationSaturn,
basic.OccultationPathOptions{
Step: 20 * time.Minute, TargetSpacingKM: 900,
DisableFootprints: true, IncludeFootprintTimeline: true,
FootprintTimelineStep: 5 * time.Minute, RiseSetStep: time.Minute,
},
)
if err != nil || len(paths) != 1 {
tb.Fatalf("FindPlanetOccultationPaths() paths=%d err=%v", len(paths), err)
}
saturn20250105Paths = paths
})
return saturn20250105Paths[0]
}
func BenchmarkVisibleBandPolygonsSaturn20250105(b *testing.B) {
path := saturn20250105Path(b)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if _, _, err := VisibleBandPolygonsFromContours(
path.PartialBandFootprints, path.PartialBandContours,
path.NorthernLimit, path.SouthernLimit, path.RiseSetCurves,
); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkVisibleBandPolygonsAnalyticSaturn20250105(b *testing.B) {
path := saturn20250105Path(b)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if _, _, err := VisibleBandPolygonsFromAnalyticContours(
path.PartialBandFootprints, path.PartialBandContours, path.PartialVisibilityContours,
path.NorthernLimit, path.SouthernLimit, path.RiseSetCurves,
); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkFootprintSweepPolygonsSaturn20250105(b *testing.B) {
path := saturn20250105Path(b)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if _, err := footprintSweepPolygons(
path.PartialBandFootprints, path.NorthernLimit, path.SouthernLimit,
); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkFootprintOpenSweepSaturn20250105(b *testing.B) {
path := saturn20250105Path(b)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if _, err := footprintOpenSweepPolygons(path.PartialBandFootprints); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkFootprintVisibleUnionSaturn20250105(b *testing.B) {
path := saturn20250105Path(b)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if polygons := footprintVisibleUnionPolygons(path.PartialBandFootprints); len(polygons) == 0 {
b.Fatal("empty visible union")
}
}
}
func occultationBenchChainPolygons(count, points int) [][]geodata.GeoPoint {
polygons := make([][]geodata.GeoPoint, 0, count)
for index := 0; index < count; index++ {
center := geodata.GeoPoint{
Longitude: -0.5 + float64(index)*1.5,
Latitude: 40,
}
ring := make([]geodata.GeoPoint, 0, points+1)
for step := 0; step <= points; step++ {
angle := 2 * math.Pi * float64(step) / float64(points)
ring = append(ring, geodata.GeoPoint{
Longitude: center.Longitude + 0.5*math.Cos(angle),
Latitude: center.Latitude + 0.5*math.Sin(angle),
})
}
polygons = append(polygons, ring)
}
return polygons
}
func BenchmarkMergeTouchingVisiblePolygonsChain(b *testing.B) {
b.Run("count=12/points=16", func(b *testing.B) {
for iteration := 0; iteration < b.N; iteration++ {
polygons := occultationBenchChainPolygons(12, 16)
if merged := mergeTouchingVisiblePolygons(polygons); len(merged) != 1 {
b.Fatalf("merged=%d, want one face", len(merged))
}
}
})
b.Run("count=24/points=16", func(b *testing.B) {
for iteration := 0; iteration < b.N; iteration++ {
polygons := occultationBenchChainPolygons(24, 16)
if merged := mergeTouchingVisiblePolygons(polygons); len(merged) != 1 {
b.Fatalf("merged=%d, want one face", len(merged))
}
}
})
}
func occultationBenchConstrainInput(points int) (parent, child [][]geodata.GeoPoint) {
ring := make([]geodata.GeoPoint, 0, points+1)
childRing := make([]geodata.GeoPoint, 0, points+1)
for step := 0; step <= points; step++ {
angle := 2 * math.Pi * float64(step) / float64(points)
longitude := -70 + 20*math.Cos(angle)
latitude := -40 + 8*math.Sin(angle)
ring = append(ring, geodata.GeoPoint{Longitude: longitude, Latitude: latitude})
childRing = append(childRing, geodata.GeoPoint{
Longitude: longitude + 0.02*math.Cos(angle),
Latitude: latitude + 0.02*math.Sin(angle),
})
}
return [][]geodata.GeoPoint{ring}, [][]geodata.GeoPoint{childRing}
}
func BenchmarkConstrainPolygonsWithinSmallBreach(b *testing.B) {
b.Run("points=512", func(b *testing.B) {
parent, child := occultationBenchConstrainInput(512)
b.ResetTimer()
for iteration := 0; iteration < b.N; iteration++ {
if repaired := ConstrainPolygonsWithin(parent, child); len(repaired) == 0 {
b.Fatal("empty repair")
}
}
})
}