Skip to content

Repository files navigation

perfcho.pp

A .NET 8 service that calculates osu! performance points and difficulty attributes through the official osu!lazer ruleset packages. Its HTTP contract matches the external calculator interface used by perfcho.py.

Algorithm Scope

  • Pins ppy.osu.Game and the Osu, Taiko, Catch, and Mania ruleset packages to 2026.702.1.
  • Supports osu, taiko, fruits, and mania, including valid cross-ruleset beatmap conversion.
  • Supports the vanilla, relax, and osu!standard autopilot variants.
  • Supports lazer mod JSON and mod settings. Unknown mods, unsupported settings, out-of-range values, and incompatible combinations return 422.
  • Supports lazer and classic through release_configuration.score_system. Classic scores use the official stable-to-standardised score migration path.

This project does not copy or reimplement the PP formulas. Star ratings and PP are produced by the pinned official DifficultyCalculator and PerformanceCalculator implementations.

HTTP API

POST /v1/performance/calculate
Content-Type: multipart/form-data

The request must contain exactly one file part named metadata, with filename metadata.json and content type application/json. The metadata and response schemas follow perfcho.py/.agent-space/docs/performance-calculation.md.

Operational endpoints:

  • GET /healthz
  • GET /v1/capabilities

Caching And Concurrency

Raw beatmaps are cached by SHA-256 in the shared process memory cache. Disk caching is disabled by default; when enabled, entries are stored under CACHE_DIRECTORY/beatmaps. Every downloaded object is verified against beatmap_sha256 before it is decoded or persisted.

The difficulty cache identity includes:

beatmap SHA-256
osu! package version and DifficultyCalculator.Version
difficulty formula, release, and version
target ruleset and variant
resolved mod acronyms and all non-default settings

Difficulty attributes are stored in process memory and optionally in Redis. Concurrent misses for the same key are coalesced into one calculation per process. CPU work is bounded by a SemaphoreSlim; the default concurrency is the logical processor count, and saturation returns 429 when no queue timeout is configured.

The calculator does not cache authoritative score or user PP results. perfcho.py remains responsible for persisting PP by score and release.

Configuration

Application settings use explicit uppercase environment variables with single underscores. ASP.NET Core framework variables such as ASPNETCORE_URLS keep their standard names. Automatic section-style environment binding is disabled for application settings.

Environment variable Description
CALCULATOR_CODE Calculator identity; defaults to perfcho-pp
FORMULA_CODE Performance formula code; defaults to official
RELEASE_VERSION Performance release version; defaults to 2026.07.1
DIFFICULTY_FORMULA_CODE Difficulty formula code; defaults to official-difficulty
DIFFICULTY_RELEASE_VERSION Difficulty release version; defaults to 2026.07.1
MAXIMUM_CONCURRENT_CALCULATIONS CPU calculation limit; 0 uses the logical processor count
CALCULATION_QUEUE_TIMEOUT_MILLISECONDS Time to wait for calculation capacity; 0 returns 429 immediately
CACHE_DIRECTORY Content-addressed beatmap cache directory
CACHE_DISK_ENABLED Persist raw beatmaps on disk; defaults to false
CACHE_MAXIMUM_MEMORY_CACHE_BYTES Shared process memory cache size for beatmaps and difficulty attributes; defaults to 128 MiB
CACHE_MAXIMUM_BEATMAP_BYTES Maximum size of one beatmap
CACHE_MAXIMUM_DISK_BYTES Disk cache limit; LRU entries are removed to 90% after the limit is crossed
CACHE_MAXIMUM_CONCURRENT_DOWNLOADS Maximum concurrent beatmap downloads
BEATMAP_DOWNLOAD_TIMEOUT_SECONDS Timeout covering beatmap headers and response body
DIFFICULTY_CACHE_TTL_HOURS Difficulty cache lifetime
REDIS_CONNECTION_STRING Optional Redis connection string
REDIS_INSTANCE_NAME Redis key prefix

Release identity is validated by calculator, formula, and release version. Release configuration remains part of the calculation input and cache identity.

The service does not follow redirects from beatmap_url. Production deployments should expose the calculator only on an internal network accessible by perfcho workers.

Local Development

dotnet restore Perfcho.Performance.sln --locked-mode
dotnet test Perfcho.Performance.sln --configuration Release --no-restore
dotnet run --project src/Perfcho.Performance

The Development launch profile listens on http://127.0.0.1:6001.

Run with Redis:

REDIS_CONNECTION_STRING=127.0.0.1:6379 \
  dotnet run --project src/Perfcho.Performance

Docker

docker build -t perfcho-pp .
docker run --rm -p 6001:6001 perfcho-pp

About

A .NET 8 service that calculates osu! performance points and difficulty attributes through the official osu!lazer ruleset packages.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages