mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-08-28 03:04:25 +00:00
## Summary Fixes #354 Replaces the O(n²) selection sort in `sortedCopy()` with Go's built-in `sort.Float64s()` (O(n log n)). ## Changes - **`cmd/server/routes.go`**: Replaced manual nested-loop selection sort with `sort.Float64s(cp)` - **`cmd/server/helpers_test.go`**: Added regression test with 1000-element random input + benchmark ## Benchmark Results (ARM64) ``` BenchmarkSortedCopy/n=256 ~16μs/op 1 alloc BenchmarkSortedCopy/n=1000 ~95μs/op 1 alloc BenchmarkSortedCopy/n=10000 ~1.3ms/op 1 alloc ``` With the old O(n²) sort, n=10000 would take ~50ms+. The new implementation scales as O(n log n). ## Testing - All existing `TestSortedCopy` tests pass (unchanged behavior) - New `TestSortedCopyLarge` validates correctness on 1000 random elements - `go test ./...` passes in `cmd/server` Co-authored-by: you <you@example.com>
This commit is contained in:
@@ -2,6 +2,8 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
@@ -220,6 +222,44 @@ func TestSortedCopy(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSortedCopyLarge(t *testing.T) {
|
||||
// Regression: verify correct sort on larger input
|
||||
rng := rand.New(rand.NewSource(42))
|
||||
n := 1000
|
||||
input := make([]float64, n)
|
||||
for i := range input {
|
||||
input[i] = rng.Float64() * 1000
|
||||
}
|
||||
result := sortedCopy(input)
|
||||
if len(result) != n {
|
||||
t.Fatalf("expected %d elements, got %d", n, len(result))
|
||||
}
|
||||
for i := 1; i < len(result); i++ {
|
||||
if result[i] < result[i-1] {
|
||||
t.Fatalf("not sorted at index %d: %v > %v", i, result[i-1], result[i])
|
||||
}
|
||||
}
|
||||
// Original unchanged
|
||||
if input[0] == result[0] && input[1] == result[1] && input[2] == result[2] {
|
||||
// Could be coincidence but very unlikely with random data
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSortedCopy(b *testing.B) {
|
||||
rng := rand.New(rand.NewSource(42))
|
||||
for _, size := range []int{256, 1000, 10000} {
|
||||
data := make([]float64, size)
|
||||
for i := range data {
|
||||
data[i] = rng.Float64() * 1000
|
||||
}
|
||||
b.Run(fmt.Sprintf("n=%d", size), func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
sortedCopy(data)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLastN(t *testing.T) {
|
||||
arr := []map[string]interface{}{
|
||||
{"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5},
|
||||
|
||||
@@ -1958,13 +1958,7 @@ func percentile(sorted []float64, p float64) float64 {
|
||||
func sortedCopy(arr []float64) []float64 {
|
||||
cp := make([]float64, len(arr))
|
||||
copy(cp, arr)
|
||||
for i := 0; i < len(cp); i++ {
|
||||
for j := i + 1; j < len(cp); j++ {
|
||||
if cp[j] < cp[i] {
|
||||
cp[i], cp[j] = cp[j], cp[i]
|
||||
}
|
||||
}
|
||||
}
|
||||
sort.Float64s(cp)
|
||||
return cp
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user