Conversation
CalculateTopRanks: - Fix lastRank tracking: populate lastRank[i] so duplicate detection works across level caps - Fix Capped mutation: use index-based tracking (lastRankIdx) to modify rankings directly instead of local copies - Pass comparator to calculateRanksCompact; pass stats as pointer - Replace O(n²) Capped propagation with O(n) index lookup Optimizations: - Simplify RankingComparatorPreferHigherCp/PreferLowerCp with early return - Replace reflect.DeepEqual with sha256 hash comparison in WatchPokemonData Cleanup: - Remove "Current State" section from README - Remove commented-out CalculateAllRanks test/benchmark
|
Do the masterfile changes align with the PR for golbat to combine the masterfiles? |
- security/concurrency: add HTTP timeout + LimitReader + status check on fetchMasterFile; reuse package-level http.Client; add sync.RWMutex on Ohbem; swap compactRankCache to atomic.Pointer[sync.Map]; restartable watcher (nil channel after Stop, double-stop returns ErrNilChannel); watcher saves to tmp+rename before in-memory swap - correctness: fix FindBaseStats else-clobber, FilterLevelCaps value-copy mutate, CalculateTopRanks master-league stamina<=15; add IV/level validation to CalculateCp; rename IsMegaUnreleased arg to tempEvolution; bound recursion depth in QueryPvPRank - perf: bit-pack cacheKey; sync.Pool for the 16 KiB rank arena; slices.SortFunc replaces sort.Sort interface; iterate LevelCaps directly in QueryPvPRank (no per-call sort+alloc); roundFloat fast path for precision=5; hoist RankingComparator default into Load/Fetch - cleanup: extract resolveStats helper; replace parallel slices in CalculateTopRanks with single struct slice; drop dead commented calculateRanks blocks; regroup errors.go; remove unused Ranking.Index - api: add Ohbem.MasterFileURL override; bump VERSION to 0.13.0 - tests/CI: re-enable master-league CalculateTopRanks cases; add TestFilterLevelCapsMerge, TestWatchPokemonDataRestart, FetchPokemonData error paths via httptest, atomic Save round-trip, FuzzQueryPvPRankBounds and FuzzCalculateCpBounds; CI now runs go test -race - docs: drop "broken" tag on CalculateTopRanks; document MasterFileURL; add DETAIL_REVIEW.md status table; add Makefile
- Revert slices.SortFunc back to sort.Sort over a sort.Interface adapter:
the closure form forced &a/&b to escape per comparison, ballooning
calculateRanksCompact from 3 to 110k allocs/call. With the adapter the
4096-entry sort runs in-place with no per-comparison allocs.
- Add an atomic.Bool initialized flag mirrored under the write lock by
Load/Fetch/Watch. safetyCheck now reads it lock-free instead of taking
the RWMutex, and Leagues / LevelCaps are read lock-free (immutable
post-init), cutting one RLock round-trip per call from FindBaseStats,
IsMegaUnreleased, CalculateCp, and the QueryPvPRank entry guard.
Bench (Apple M2 Pro, vs broken commit / vs original HEAD~1):
- CalculateRanksCompact: 2.06 ms / 110k allocs -> 608 us / 3 allocs
(matches original 595 us / 3 allocs)
- CalculateTopRanks: 3.98 ms / 165k allocs -> 1.09 ms / 48 allocs
(vs original 1.10 ms / 68 allocs; -29% allocs)
- QueryPvPRank cold: 10.1 ms / 427k allocs -> 2.59 ms / 21 allocs
(vs original 2.53 ms / 25 allocs; -16% allocs)
- QueryPvPRankCached: 697 ns -> 690 ns (-12% vs original 784 ns)
- FindBaseStats: 40 ns -> 29 ns (vs 17 ns; residual = 1 RLock)
- IsMegaUnreleased: 25 ns -> 15 ns (vs 8 ns; residual = 1 RLock)
go test -race ./... still passes.
|
@jfberry point me to it please |
|
We already merged something (by mygod) that causes golbat to own the masterfile |
|
In this case I don't expect any issues. haven't touched this flow except ability to override mastefile url. |
|
@lenisko — looking for your guidance on an overlap. Golbat hit the §1.6 races in production ( On the concurrency designs specifically:
The difference only matters at scanner-scale query concurrency — but that's gohbem's main audience, so I'd lean toward the pointer-swap read path whichever PR carries it. One more thing worth merging regardless of direction: #19 has a dedicated How would you like to proceed? Options as I see them:
No strong attachment to my code landing — the goal is reload safety merged for consumers. Whatever's easiest for you. |
|
Follow-up with numbers, to make the concurrency-design discussion concrete. I ran the same benchmark file (public API only, so it compiles unmodified) against three heads:
Two observations, offered neutrally:
Offer: if you like the direction, I'm happy to do the merge work mechanically — #19's bundle as the concurrency layer, with everything else in this PR (CalculateTopRanks, perf work, HTTP hardening, CI) rebased on top, under whichever PR number you prefer. Equally fine to hand you the bundle + the Benchmark source (drop into the repo root as
|
CalculateTopRanks:
Optimizations:
Cleanup: