Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5bb7be3765 | ||
|
|
bad95e4f6a | ||
|
|
b03d1411d1 | ||
|
|
a24a6fa26c | ||
|
|
6d9bb375c5 | ||
|
|
10c9d8440c | ||
|
|
7f6d556e68 | ||
|
|
d33f547bf7 | ||
|
|
2e7283d01c | ||
|
|
9a7f955a77 | ||
|
|
6b7617c277 | ||
|
|
7c5efff307 | ||
|
|
1f6e498238 | ||
|
|
32f6079134 | ||
|
|
ce1db1b0c3 | ||
|
|
ad3ddeb43f | ||
|
|
34f4d3b451 | ||
|
|
27de895fdb |
No files matched your search
@@ -1,76 +0,0 @@
|
||||
---
|
||||
name: vanilla-parity
|
||||
description: Fix a Horizon bug or gap so it behaves 1:1 like vanilla 26.3, starting from the port ledger (tools/port_ledger.py) instead of grepping. Use for any issue, Discord report or PR that makes Horizon match vanilla: "X doesn't work like in Java", a missing sound, particle, animation, mob behaviour, block rule, screen or packet.
|
||||
---
|
||||
|
||||
# Vanilla parity with the port ledger
|
||||
|
||||
The port ledger pairs every vanilla method with the Rust fn that ports it (or says it is missing, or needs
|
||||
no port) and lists where a port isn't wired like vanilla. Ask it first; grep only for what it can't answer.
|
||||
Full reference: `docs/port-ledger.md`.
|
||||
|
||||
## 0. Have a fresh ledger
|
||||
|
||||
```sh
|
||||
python3 tools/port_ledger.py build # ~20 s; again after pulling main
|
||||
```
|
||||
|
||||
It needs the vanilla jar (the launcher's `versions/26.3/26.3.jar`, or `--jar`) and/or the lab's decompiled
|
||||
sources (`python3 tools/lab.py decompile`, or `--sources DIR`). If `build` says it has no vanilla code, run
|
||||
the lab first; don't guess vanilla from memory.
|
||||
|
||||
## 1. From the report to the code
|
||||
|
||||
```sh
|
||||
python3 tools/port_ledger.py issue 3236 # a GitHub issue number
|
||||
python3 tools/port_ledger.py issue "mooshroom stays red after lightning" # or the report's text
|
||||
```
|
||||
|
||||
It ranks the vanilla classes the report names and lists, per class, its Rust home files, where each method is
|
||||
ported, and the known gaps (`missing` rows from the verdict map, seam/client/drift gaps). Often the cause is
|
||||
already written there ("Type is not saved"). Then drill in:
|
||||
|
||||
```sh
|
||||
python3 tools/port_ledger.py where MushroomCow.readAdditionalSaveData # ports, callers, callees, gaps
|
||||
python3 tools/port_ledger.py class MushroomCow # every method: where, or missing
|
||||
python3 tools/port_ledger.py what crates/horizon-client/src/mobs/farm.rs:120 # which vanilla method a fn ports
|
||||
```
|
||||
|
||||
A ledger answer is a lead, not a verdict: about 1 in 12 map rows is wrong. Read the vanilla method (path and
|
||||
line are in the output) and the Rust fn before changing anything.
|
||||
|
||||
## 2. Port it the vanilla way
|
||||
|
||||
- Translate the vanilla method, don't reinvent it: same order of operations, same constants, the same random
|
||||
draws in the same order (`horizon_core::random`), Java `Math` through `horizon_core::jmath`.
|
||||
- Open the fn's doc with the vanilla method it ports: `` /// `MushroomCow.readAdditionalSaveData`: ... ``.
|
||||
That one line is what makes the next agent find it.
|
||||
- Fix the path players run: single player is a client of the integrated server, so server logic lives in
|
||||
`game/lan*.rs` and `src/lan/`, and what only the client's copy shows (particles, local sounds, hand
|
||||
animation) must be reached from `game/remote*.rs`.
|
||||
- Look at the neighbours the ledger lists for the same class: a `client` or `seam` gap next to your fix is
|
||||
usually the same bug on the other path.
|
||||
|
||||
## 3. Before the PR
|
||||
|
||||
```sh
|
||||
python3 tools/port_ledger.py check --base origin/main
|
||||
```
|
||||
|
||||
It lists the ports your branch touches with their open gaps, citations to add, stale citations, and (against
|
||||
the base) the gaps the branch closes and opens. Close what belongs to your fix, cite what you ported, leave
|
||||
no new stale citation. If you ported a method the verdict map called `missing`, change its row in
|
||||
`tools/port_map/*.tsv` to `port` with the fn (`file.rs::Owner::fn`) and run
|
||||
`python3 tools/port_ledger.py map-check tools/port_map/<file>.tsv`.
|
||||
|
||||
Then the usual: the harness for the area (`docs/architecture.md`), `cargo check`/tests per `AGENTS.md`, and
|
||||
a small PR that says which vanilla method it now matches.
|
||||
|
||||
## Finding work
|
||||
|
||||
```sh
|
||||
python3 tools/port_ledger.py gaps --kind seam # ported on two paths, wired on one: the best leads
|
||||
python3 tools/port_ledger.py gaps --kind client # client-only effects the server path never reaches
|
||||
python3 tools/port_ledger.py gaps --kind drift # a port missing a sound, particle, item or constant
|
||||
rg -n "player:" tools/port_map/*.tsv # missing behaviour a player would see
|
||||
```
|
||||
@@ -1,11 +1,2 @@
|
||||
#!/bin/sh
|
||||
# Git for Windows puts a `python3` on PATH that is only the Microsoft Store
|
||||
# stub: it prints "Python" and exits non-zero, so the hook fails with no other
|
||||
# output. Use the first name that actually runs Python 3.
|
||||
for py in python3 python py; do
|
||||
if "$py" -c "import sys; sys.exit(sys.version_info < (3,))" >/dev/null 2>&1; then
|
||||
exec "$py" tools/check_public_tree.py
|
||||
fi
|
||||
done
|
||||
echo "check_public_tree: no working Python 3 found" >&2
|
||||
exit 1
|
||||
exec python3 tools/check_public_tree.py
|
||||
@@ -1,11 +1,2 @@
|
||||
#!/bin/sh
|
||||
# Git for Windows puts a `python3` on PATH that is only the Microsoft Store
|
||||
# stub: it prints "Python" and exits non-zero, so the hook fails with no other
|
||||
# output. Use the first name that actually runs Python 3.
|
||||
for py in python3 python py; do
|
||||
if "$py" -c "import sys; sys.exit(sys.version_info < (3,))" >/dev/null 2>&1; then
|
||||
exec "$py" tools/check_public_tree.py --pre-push
|
||||
fi
|
||||
done
|
||||
echo "check_public_tree: no working Python 3 found" >&2
|
||||
exit 1
|
||||
exec python3 tools/check_public_tree.py --pre-push
|
||||
@@ -1,4 +1,3 @@
|
||||
self-hosted-runner:
|
||||
# The Mac mini's runner (ludovics-mac-mini), which holds the maintainer's own Minecraft files.
|
||||
# windows-11-vs2026-arm is GitHub's Windows ARM64 image (2026-08), newer than actionlint's label list.
|
||||
labels: [horizon-game, ludovics-mac-mini, windows-11-vs2026-arm]
|
||||
labels: [horizon-game, ludovics-mac-mini]
|
||||
@@ -1,44 +1,12 @@
|
||||
<!-- Opened by an AI agent? First line: "> 🤖 Opened by <your GitHub login>'s AI agent (<tool, model>), not by <your GitHub login> personally." Use your own login, not someone else's. -->
|
||||
|
||||
## What and why
|
||||
|
||||
<!-- What this changes, and why. Link the issue it fixes ("Fixes #123"). Over about 500 lines: link the issue with its
|
||||
approved spec too ("Spec: #123"), CONTRIBUTING.md "Large pull requests". -->
|
||||
|
||||
## Kind
|
||||
|
||||
<!-- Tick one: it sets the pull request's label (CONTRIBUTING.md "Pull requests"). -->
|
||||
|
||||
- [ ] parity: Horizon now does what vanilla 26.3 does
|
||||
- [ ] bug: a crash or a breakage
|
||||
- [ ] perf: faster, or less memory
|
||||
- [ ] feature: something new for players (listed under New in the release notes)
|
||||
- [ ] extra: Horizon-only, off by default
|
||||
- [ ] tooling: tools, CI, tests, harnesses
|
||||
- [ ] docs
|
||||
|
||||
## Layer
|
||||
|
||||
<!-- engine, platform or Horizon (docs/layers.md, "Where a new feature goes"). Reviewers check:
|
||||
- the new code sits in a crate or module of that layer;
|
||||
- no new dependency its layer may not use (CI's layer check): no engine code calling platform or Horizon code,
|
||||
and Horizon code using the platform's public API only, never the engine directly;
|
||||
- Horizon features in the game are behind `horizon-extras`, and platform features that change the vanilla
|
||||
look are off by default;
|
||||
- no new built-in server address outside the Horizon layer. -->
|
||||
<!-- What this changes, and why. Link the issue it fixes ("Fixes #123"). -->
|
||||
|
||||
## Vanilla reference
|
||||
|
||||
<!-- The vanilla classes and methods this follows (tools/rea_vanilla.py), and the harness that checks it.
|
||||
"Horizon-only" for a feature vanilla doesn't have; "none" for tooling or docs. -->
|
||||
|
||||
## Other projects' code
|
||||
|
||||
<!-- "none", or for each project you read or copied from: its link at the commit, its license (only MIT,
|
||||
BSD-2-Clause, BSD-3-Clause, Apache-2.0, ISC, zlib, 0BSD, MIT-0, Unlicense or CC0-1.0), and what you took.
|
||||
CONTRIBUTING.md "Only original code". Shader packs: also the sections of docs/cleanroom/shader-packs-spec.md,
|
||||
the documentation pages and the packs you used. -->
|
||||
|
||||
## Self-check
|
||||
|
||||
<!-- Paste the block `python3 tools/pr_ready.py` prints (`--base upstream/main` from a fork). -->
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
# Trusted reviewers: one list for three things (docs/release-flow.md "Trusted reviewers").
|
||||
# - `/nightly 2640 2642` picks the pull requests the Nightly holds (tools/ci/nightly_set.py);
|
||||
# - `/close`, `/reopen`, `/label`, `/unlabel` triage issues and pull requests (tools/ci/triage_command.py);
|
||||
# - `/unclaim @login` releases someone else's claim, and listed reviewers have no claim limit (tools/ci/claim_command.py).
|
||||
# One reviewer per line: `<numeric GitHub ID> <login>`, with who added it and when. The ID decides; the login is only
|
||||
# for people reading this file and for messages. A login is a name anyone can claim once its owner renames or deletes
|
||||
# the account; an ID is never reused. Get it with `gh api users/<login> --jq .id`, or run
|
||||
# `python3 tools/ci/resolve_reviewer_ids.py` to fill in the IDs and `--check` to catch renames.
|
||||
# A line in any other form (a bare login included) grants nothing. Ludovic is always allowed (OWNER_ID in
|
||||
# tools/ci/nightly_set.py) and isn't listed. Removing a line revokes that account at once. A line with only `paused`
|
||||
# stops all three for every reviewer (Ludovic's still work).
|
||||
54669067 kacpherek # added by Ludovic, 2026-10-27
|
||||
87152661 rdbtCVS # added by Ludovic, 2026-10-27
|
||||
84875247 Online5277 # added by Ludovic, 2026-10-27 (his top three by merged pull requests)
|
||||
86072227 levzzz5154 # added by Ludovic, 2026-10-28 (Horizon Team; author of horizon-mixins)
|
||||
169198624 itarqos5 # added by Ludovic, 2026-11-08 (Discord Literal; Horizon Team)
|
||||
@@ -9,23 +9,19 @@ permissions:
|
||||
actions: write
|
||||
jobs:
|
||||
cancel:
|
||||
# One of our small runners (horizon-light), out of GitHub's pool: no checkout, no code of the pull request
|
||||
# (docs/ci-runners.md). SELF_HOSTED_CI=off: GitHub's runners.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cancel the pull request's unfinished runs
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
|
||||
SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
# Every head the pull request had, not only its last: a run-parity label added on an older head left that
|
||||
# run queued after the merge (#3104, 2026-10-29). Its branch in its own repository names its runs (another
|
||||
# fork can have a branch of the same name).
|
||||
for status in queued in_progress waiting pending requested; do
|
||||
gh api -X GET "repos/$REPO/actions/runs" -f branch="$BRANCH" -f event=pull_request -f status="$status" \
|
||||
-f per_page=100 --jq ".workflow_runs[] | select(.head_repository.full_name == \"$HEAD_REPO\") | .id"
|
||||
gh run list -R "$REPO" --branch "$BRANCH" --status "$status" --limit 100 \
|
||||
--json databaseId,event,headSha \
|
||||
-q ".[] | select(.event == \"pull_request\" and .headSha == \"$SHA\") | .databaseId"
|
||||
done | sort -u | while read -r id; do
|
||||
gh run cancel -R "$REPO" "$id" || true
|
||||
done
|
||||
@@ -1,107 +0,0 @@
|
||||
name: cargo-horizon-mod
|
||||
# `cargo binstall --git https://github.com/horizon-rust/horizon cargo-horizon-mod` (#2120): binstall reads
|
||||
# [package.metadata.binstall] from crates/cargo-horizon-mod/Cargo.toml and downloads the archive this workflow
|
||||
# attaches to the tag `cargo-horizon-mod-v<version>`, whose version must be the manifest's. The targets come from
|
||||
# tools/horizon_mod_binstall.py, the same file the manifest's template is checked against, so a platform added there
|
||||
# is built here and one nobody publishes is caught before it ships. A pull request builds the archives and publishes
|
||||
# nothing.
|
||||
on:
|
||||
push:
|
||||
tags: ['cargo-horizon-mod-v*']
|
||||
pull_request:
|
||||
paths:
|
||||
- 'crates/cargo-horizon-mod/**'
|
||||
- 'tools/horizon_mod_binstall.py'
|
||||
- '.github/workflows/cargo-horizon-mod.yml'
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
plan:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
outputs:
|
||||
platforms: ${{ steps.platforms.outputs.platforms }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- id: platforms
|
||||
run: echo "platforms=$(python3 -c 'import json, tools.horizon_mod_binstall as m; print(json.dumps(m.PLATFORMS))')" >> "$GITHUB_OUTPUT"
|
||||
build:
|
||||
needs: plan
|
||||
name: build ${{ matrix.target }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include: ${{ fromJSON(needs.plan.outputs.platforms) }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
- name: The aarch64 Linux linker
|
||||
if: matrix.target == 'aarch64-unknown-linux-gnu'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y gcc-aarch64-linux-gnu
|
||||
echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> "$GITHUB_ENV"
|
||||
- name: Build
|
||||
run: cargo build --release --locked -p cargo-horizon-mod --target ${{ matrix.target }}
|
||||
- name: It starts
|
||||
if: matrix.run
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
binary="target/${{ matrix.target }}/release/cargo-horizon-mod"
|
||||
[ -f "$binary.exe" ] && binary="$binary.exe"
|
||||
out=$("$binary" 2>&1 || true)
|
||||
case "$out" in
|
||||
*"usage: cargo horizon-mod"*) ;;
|
||||
*) echo "$out"; echo "::error::$binary does not start"; exit 1 ;;
|
||||
esac
|
||||
- name: Package
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
binary="target/${{ matrix.target }}/release/cargo-horizon-mod"
|
||||
[ -f "$binary.exe" ] && binary="$binary.exe"
|
||||
mkdir -p dist
|
||||
tar -czf "dist/$(basename "$binary" | sed 's/\.exe$//')-${{ matrix.target }}.tar.gz" -C "$(dirname "$binary")" "$(basename "$binary")"
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: cargo-horizon-mod-${{ matrix.target }}
|
||||
path: dist/*.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
publish:
|
||||
needs: build
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
pattern: cargo-horizon-mod-*
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
- name: The tag and the manifest name the same release and archives
|
||||
run: python3 tools/horizon_mod_binstall.py dist "$GITHUB_REF_NAME"
|
||||
- name: Checksums
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cd dist
|
||||
for file in *.tar.gz; do sha256sum "$file" | cut -d' ' -f1 > "$file.sha256"; done
|
||||
- name: Publish
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
notes="\`cargo binstall --git https://github.com/horizon-rust/horizon cargo-horizon-mod\`"
|
||||
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
|
||||
gh release upload "$GITHUB_REF_NAME" dist/* --clobber
|
||||
else
|
||||
gh release create "$GITHUB_REF_NAME" dist/* --latest=false --title "cargo-horizon-mod ${GITHUB_REF_NAME#cargo-horizon-mod-v}" --notes "$notes"
|
||||
fi
|
||||
@@ -16,38 +16,22 @@ on:
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
# A new push to a pull request replaces its running checks. On main, the running check finishes and only the
|
||||
# newest push waits behind it: GitHub cancels a waiting run when a newer one joins the group. A burst of merges
|
||||
# queued ~100 main runs on 2026-11-09; the release follows the newest finished main run (docs/release-flow.md).
|
||||
group: checks-${{ github.event.pull_request.number || (github.event_name == 'push' && 'main') || github.sha }}
|
||||
# A new push to a pull request replaces its running checks; main's runs all finish (releases follow them).
|
||||
group: checks-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
env:
|
||||
# Test runs never reach the telemetry server: no live-count ping, no uploads (docs/telemetry.md).
|
||||
HORIZON_TELEMETRY_URL: "off"
|
||||
|
||||
jobs:
|
||||
# One job, not one per check: each job takes a runner from the organisation's shared pool, and with every pull request
|
||||
# and every merge to main starting this workflow, three jobs a run left the pool's queue tens of minutes deep.
|
||||
#
|
||||
# Where (docs/ci-runners.md): our checks runners (label horizon-checks: the desktop's, an isolated user, so a fork's
|
||||
# pull request runs there too) take the pull requests whose number ends in 0 or 1, about what their three runners
|
||||
# can do; GitHub's runners take the others and main's pushes (which also save the Rust cache GitHub's pull request
|
||||
# runs read), so both pools work at once. The repository variable SELF_HOSTED_CI moves them: `all` every job to
|
||||
# ours, `light` (the desktop paused) or `off` every job to GitHub's. On ours the build folder persists
|
||||
# (CARGO_TARGET_DIR, outside the checkout), so the apt packages, Python and the Rust cache steps are GitHub's only.
|
||||
verify:
|
||||
runs-on: >-
|
||||
${{ vars.SELF_HOSTED_CI != 'off' && vars.SELF_HOSTED_CI != 'light' && (vars.SELF_HOSTED_CI == 'all' ||
|
||||
github.event_name == 'pull_request' && (endsWith(format('{0}', github.event.pull_request.number), '0') ||
|
||||
endsWith(format('{0}', github.event.pull_request.number), '1'))) &&
|
||||
fromJSON('["self-hosted", "linux", "horizon-checks"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 45
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-python@v7
|
||||
if: runner.environment == 'github-hosted'
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Does this pull request need Rust checks?
|
||||
@@ -57,61 +41,20 @@ jobs:
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: python3 tools/ci/rust_changes.py "$BASE_SHA" "$HEAD_SHA" >> "$GITHUB_OUTPUT"
|
||||
# A pull request adds only its own commits to main, so it reads those; main's pushes read every ref's history.
|
||||
- name: Keep game artifacts out of Git
|
||||
env:
|
||||
EVENT: ${{ github.event_name }}
|
||||
BASE_SHA: ${{ github.event.pull_request.base.sha }}
|
||||
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||
run: |
|
||||
python tools/check_public_tree.py
|
||||
if [ "$EVENT" = pull_request ]; then
|
||||
python tools/check_public_tree.py --range "$BASE_SHA..$HEAD_SHA"
|
||||
else
|
||||
python tools/check_public_tree.py --history
|
||||
fi
|
||||
# Our runners as GitHub's: some Python tests compile Rust with a bare `rustc` (GitHub's image has a default
|
||||
# toolchain, our runners' own rustup homes may not), and the GPU tests find no adapter there, so they return
|
||||
# early. Ours have Mesa's software Vulkan for parity; a backend Linux lacks keeps the tests from it, so a pull
|
||||
# request's verify doesn't depend on which pool took it (#8627: a GPU test that flakes on lavapipe).
|
||||
- name: Our runners as GitHub's (a default Rust toolchain, no GPU)
|
||||
if: runner.environment != 'github-hosted'
|
||||
run: |
|
||||
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
rustup default stable
|
||||
echo "WGPU_BACKEND=dx12" >> "$GITHUB_ENV"
|
||||
# On a pull request, the next three checks compare with HEAD^1: the main that GitHub's merge commit puts the pull
|
||||
# request on. pull_request.base.sha is main at the pull request's last push and falls behind, so main's own
|
||||
# changes since then would count as the pull request's (#13874).
|
||||
# docs/layers.md: a crate depends only on its own layer or a lower one; today's exceptions only shrink.
|
||||
- name: Crates follow the layers
|
||||
env:
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_layers.py ${BASE:+--base "$BASE"}
|
||||
# docs/layers.md#built-in-addresses: every built-in outside address in the Horizon layer's home; the rest only shrinks.
|
||||
- name: Built-in addresses stay in their home
|
||||
env:
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_addresses.py ${BASE:+--base "$BASE"}
|
||||
# docs/layers.md#file-size: a Rust file over 3000 lines may not grow (pull requests; main has no base to compare).
|
||||
- name: Big files don't grow
|
||||
env:
|
||||
BASE: ${{ github.event_name == 'pull_request' && 'HEAD^1' || '' }}
|
||||
run: python3 tools/check_file_size.py ${BASE:+--base "$BASE"}
|
||||
python tools/check_public_tree.py --history
|
||||
- name: Test offline research tooling
|
||||
run: python -m unittest discover -s tests -v
|
||||
- name: Install Rust toolchain and the ALSA and udev headers the client links against
|
||||
if: steps.rust.outputs.required != 'false'
|
||||
env:
|
||||
HOSTED: ${{ runner.environment == 'github-hosted' }}
|
||||
run: |
|
||||
if [ "$HOSTED" = true ]; then
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
|
||||
fi
|
||||
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
|
||||
rustup toolchain install stable --profile minimal --component rustfmt --component clippy --target wasm32-unknown-unknown
|
||||
# Dependencies and the workspace's own build, saved from main's runs (pull requests read main's cache).
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: steps.rust.outputs.required != 'false' && runner.environment == 'github-hosted'
|
||||
if: steps.rust.outputs.required != 'false'
|
||||
with:
|
||||
shared-key: verify
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
@@ -119,34 +62,28 @@ jobs:
|
||||
if: steps.rust.outputs.required != 'false'
|
||||
run: |
|
||||
cargo +stable fmt --all -- --check
|
||||
cargo +stable clippy --workspace --all-targets -- -D warnings
|
||||
# With the game's code mods (on in every release build, off by default).
|
||||
cargo +stable clippy --workspace --all-targets --features horizon-client/mods -- -D warnings
|
||||
# The server build (released as horizon-engine): the game without sound or controllers.
|
||||
cargo +stable clippy -p horizon-client --all-targets --no-default-features -- -D warnings
|
||||
# Libraries, binaries and integration tests, then doc tests: not the ~275 examples, which clippy above already
|
||||
# type-checks and the parity job builds and runs (they were most of this step's build and link time).
|
||||
# cargo test, not nextest: nextest's process per test reloads each binary's shared tables for every test, and on
|
||||
# these 4-core runners it was no faster (#4978).
|
||||
- name: Test Rust core and voxel kernel correctness
|
||||
if: steps.rust.outputs.required != 'false'
|
||||
run: |
|
||||
cargo +stable test --workspace --lib --bins --tests
|
||||
cargo +stable test --workspace --lib --bins --tests --features horizon-client/mods,horizon-mods/pack
|
||||
# The full content-root tests (#[ignore]d: minutes each on a laptop). The same build as above; they need the
|
||||
# prepared vanilla data, so without it they pass at once. Keep the target selection identical to avoid
|
||||
# recompiling the workspace with a different dependency graph.
|
||||
cargo +stable test --workspace --lib --bins --tests mod_content::tests:: -- --ignored
|
||||
cargo +stable test --workspace --doc
|
||||
# prepared vanilla data, so without it they pass at once.
|
||||
cargo +stable test --workspace --lib --features horizon-client/mods,horizon-mods/pack mod_content::tests:: -- --ignored
|
||||
cargo +stable test --workspace --doc --features horizon-client/mods,horizon-mods/pack
|
||||
# The launcher is its own workspace (launcher/Cargo.toml), so verify's cargo runs never build it. A pull request that
|
||||
# changes it or a crate it builds is checked here, and so is every push to main: two pull requests can each pass
|
||||
# alone and break it together (#2059 and the registry ratings did, 2026-10-26).
|
||||
launcher:
|
||||
runs-on: >-
|
||||
${{ vars.SELF_HOSTED_CI != 'off' && vars.SELF_HOSTED_CI != 'light' && (vars.SELF_HOSTED_CI == 'all' ||
|
||||
github.event_name == 'pull_request' && (endsWith(format('{0}', github.event.pull_request.number), '0') ||
|
||||
endsWith(format('{0}', github.event.pull_request.number), '1'))) &&
|
||||
fromJSON('["self-hosted", "linux", "horizon-checks"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 45
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Does this pull request change the launcher or a crate it builds?
|
||||
@@ -158,16 +95,12 @@ jobs:
|
||||
run: python3 tools/ci/rust_changes.py --launcher "$BASE_SHA" "$HEAD_SHA" >> "$GITHUB_OUTPUT"
|
||||
- name: Install Rust and the headers GPUI links against
|
||||
if: steps.launcher.outputs.required != 'false'
|
||||
env:
|
||||
HOSTED: ${{ runner.environment == 'github-hosted' }}
|
||||
run: |
|
||||
if [ "$HOSTED" = true ]; then
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends libxkbcommon-x11-dev libwayland-dev \
|
||||
libx11-xcb-dev libfontconfig-dev libvulkan-dev libasound2-dev libudev-dev
|
||||
fi
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends libxkbcommon-x11-dev libwayland-dev \
|
||||
libx11-xcb-dev libfontconfig-dev libvulkan-dev libasound2-dev libudev-dev
|
||||
rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: steps.launcher.outputs.required != 'false' && runner.environment == 'github-hosted'
|
||||
if: steps.launcher.outputs.required != 'false'
|
||||
with:
|
||||
workspaces: launcher
|
||||
shared-key: launcher
|
||||
@@ -178,114 +111,17 @@ jobs:
|
||||
run: |
|
||||
cargo +stable fmt --check
|
||||
cargo +stable clippy --all-targets --locked -- -D warnings
|
||||
cargo +stable test --locked --lib --bins
|
||||
# Compile and test Windows ARM64 on an actual ARM64 host, and inspect the resulting PE headers. By hand only
|
||||
# (`gh workflow run checks --ref <branch>`): GitHub's runner queue is the bottleneck, and main's runs gate the
|
||||
# releases (tools/release_train.py waits for them), so neither pull requests nor main's pushes start this
|
||||
# 90-minute job. The Nightly and launcher releases build and check these binaries on every run.
|
||||
windows-arm64:
|
||||
name: Windows ARM64 game and launcher
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: windows-11-vs2026-arm
|
||||
timeout-minutes: 90
|
||||
env:
|
||||
RUSTFLAGS: -C target-feature=+crt-static
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Use every runner core for Cargo
|
||||
shell: pwsh
|
||||
run: |
|
||||
$cores = (Get-CimInstance Win32_Processor | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum
|
||||
"CARGO_BUILD_JOBS=$cores" >> $env:GITHUB_ENV
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: aarch64-pc-windows-msvc
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
shared-key: windows-arm64-game
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
with:
|
||||
workspaces: launcher
|
||||
shared-key: windows-arm64-launcher
|
||||
- name: Check LLVM assembler used by ring
|
||||
shell: pwsh
|
||||
run: |
|
||||
$llvmBin = Join-Path $env:ProgramFiles 'LLVM\bin'
|
||||
if (-not (Get-Command clang -ErrorAction SilentlyContinue) -and (Test-Path (Join-Path $llvmBin 'clang.exe'))) {
|
||||
$env:PATH = "$llvmBin;$env:PATH"
|
||||
"PATH=$env:PATH" >> $env:GITHUB_ENV
|
||||
}
|
||||
$clang = Get-Command clang -ErrorAction Stop
|
||||
Write-Output "Using $($clang.Source)"
|
||||
& $clang.Source --version
|
||||
- name: Build the game for native Windows ARM64 (the official game, as game-build.yml ships it)
|
||||
run: cargo build --release --locked --target aarch64-pc-windows-msvc -p horizon-official --bin horizon-official -p horizon-client-lib --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
|
||||
- name: Check the game's PE machine
|
||||
run: python tools/check_pe_arch.py arm64 target/aarch64-pc-windows-msvc/release/horizon-official.exe target/aarch64-pc-windows-msvc/release/horizon-ctl.exe target/aarch64-pc-windows-msvc/release/horizon-prepare.exe target/aarch64-pc-windows-msvc/release/horizon-server.exe
|
||||
- name: Check game DLL imports
|
||||
run: python tools/check_imports.py target/aarch64-pc-windows-msvc/release/horizon-official.exe target/aarch64-pc-windows-msvc/release/horizon-ctl.exe target/aarch64-pc-windows-msvc/release/horizon-prepare.exe target/aarch64-pc-windows-msvc/release/horizon-server.exe
|
||||
- name: Start every game executable
|
||||
shell: pwsh
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$client = 'target/aarch64-pc-windows-msvc/release/horizon-official.exe'
|
||||
$output = & $client --help 2>&1
|
||||
if ($LASTEXITCODE -ne 0 -or ($output -join "`n") -notmatch '--resources') { throw 'horizon-client --help failed' }
|
||||
foreach ($binary in @('horizon-ctl.exe', 'horizon-prepare.exe', 'horizon-server.exe')) {
|
||||
$path = "target/aarch64-pc-windows-msvc/release/$binary"
|
||||
$output = & $path --help 2>&1
|
||||
if ($LASTEXITCODE -ne 0 -or -not $output) { throw "$binary --help failed" }
|
||||
}
|
||||
foreach ($binary in @('horizon-prepare.exe', 'horizon-server.exe')) {
|
||||
$path = "target/aarch64-pc-windows-msvc/release/$binary"
|
||||
$output = & $path --version 2>&1
|
||||
if ($LASTEXITCODE -ne 0 -or -not $output) { throw "$binary --version failed" }
|
||||
Write-Output ($output -join "`n")
|
||||
}
|
||||
- name: Test and build the native Windows ARM64 launcher
|
||||
working-directory: launcher
|
||||
run: |
|
||||
cargo test --release --locked --target aarch64-pc-windows-msvc --lib
|
||||
cargo build --release --locked --target aarch64-pc-windows-msvc
|
||||
- name: Check the launcher's PE machine
|
||||
working-directory: launcher
|
||||
run: python ../tools/check_pe_arch.py arm64 target/aarch64-pc-windows-msvc/release/horizon-launcher.exe
|
||||
- name: Check launcher DLL imports and command-line startup
|
||||
working-directory: launcher
|
||||
# bash, as launcher.yml's check on the same runner: the launcher is a GUI-subsystem program, and a pwsh
|
||||
# `$output = & launcher --version` read no output from it (run 42217014588).
|
||||
shell: bash
|
||||
run: |
|
||||
launcher=target/aarch64-pc-windows-msvc/release/horizon-launcher.exe
|
||||
python ../tools/check_imports.py "$launcher"
|
||||
out=$("$launcher" --version)
|
||||
echo "$out"
|
||||
[[ "$out" == "horizon-launcher "* ]] || { echo "::error::horizon-launcher --version printed '$out'"; exit 1; }
|
||||
- name: Build a native-mod game with the launcher's managed toolchain
|
||||
working-directory: launcher
|
||||
shell: pwsh
|
||||
env:
|
||||
HORIZON_LAUNCHER_HOME: ${{ runner.temp }}\horizon-native-arm64-toolchain
|
||||
HORIZON_NATIVE_TARGET_DIR: ${{ runner.temp }}\horizon-native-arm64-toolchain\target
|
||||
run: |
|
||||
$ErrorActionPreference = 'Stop'
|
||||
cargo test --release --locked --target aarch64-pc-windows-msvc --lib rust_toolchain::tests::managed_arm64_toolchain_builds_the_game -- --ignored --exact --nocapture
|
||||
$client = Join-Path $env:HORIZON_NATIVE_TARGET_DIR 'fast/horizon-client.exe'
|
||||
python ../tools/check_pe_arch.py arm64 $client
|
||||
python ../tools/check_imports.py $client
|
||||
cargo +stable test --locked --lib
|
||||
# Most pull requests leave the harnesses to parity-main, which runs them on main a batch of merges at a time
|
||||
# (.github/workflows/parity-main.yml; releases wait for it). A pull request still runs them itself when it changes
|
||||
# a harness, an oracle, a probe or the runner, or carries the run-parity label (run-parity.yml, when it is added).
|
||||
parity-scope:
|
||||
if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository
|
||||
# A git diff of this repository's own branch: one of our small runners (horizon-light, docs/ci-runners.md).
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
run: ${{ steps.scope.outputs.run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
fetch-depth: 0
|
||||
@@ -297,7 +133,7 @@ jobs:
|
||||
run: |
|
||||
changed=$(git diff --name-only "$(git merge-base "$BASE_SHA" HEAD)" HEAD)
|
||||
harness=$(grep -E '^(tools/test_[a-z0-9_]+_parity\.py|tools/(parity[a-z_]*|lab)\.py|tools/parity_hosts\.json|mods/horizon/src/test/|crates/[^/]+/examples/|crates/horizon-client/src/game/[a-z_]*(fixture|harness)\.rs|\.github/workflows/parity[a-z-]*\.yml)' <<< "$changed" || true)
|
||||
if [ -n "$harness" ] || [[ " $LABELS " == *" run-parity "* ]] || [[ " $LABELS " == *" frame-identity "* ]]; then
|
||||
if [ -n "$harness" ] || [[ " $LABELS " == *" run-parity "* ]]; then
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
echo "The pull request runs its harnesses: ${harness:-label run-parity}"
|
||||
else
|
||||
@@ -312,7 +148,6 @@ jobs:
|
||||
base: ${{ github.event.pull_request.base.sha }}
|
||||
head: ${{ github.event.pull_request.head.sha }}
|
||||
full: ${{ contains(github.event.pull_request.labels.*.name, 'full-parity') }}
|
||||
frame_identity: ${{ contains(github.event.pull_request.labels.*.name, 'frame-identity') }}
|
||||
# Horizon never downloads the game. These jobs need a self-hosted Linux runner
|
||||
# (label horizon-game) holding the maintainer's own copy: the official launcher's
|
||||
# game directory in HORIZON_MINECRAFT_DIR and the pinned server jar in
|
||||
@@ -321,13 +156,13 @@ jobs:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: [self-hosted, linux, horizon-game]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-python@v7
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- name: Install Rust toolchain
|
||||
run: rustup toolchain install stable --profile minimal
|
||||
- uses: actions/setup-java@v6
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
@@ -669,11 +504,11 @@ jobs:
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
runs-on: [self-hosted, linux, horizon-game]
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/setup-python@v7
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.12'
|
||||
- uses: actions/setup-java@v6
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: temurin
|
||||
java-version: '25'
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
name: claim command
|
||||
# `/claim` and `/unclaim` comments: anyone takes an issue before working on it, and a daily run releases the claims
|
||||
# older than 5 days that no open pull request links (CONTRIBUTING.md "Claim before you start",
|
||||
# tools/ci/claim_command.py).
|
||||
#
|
||||
# Why no pull request's code runs here, though the token can write:
|
||||
# - `issue_comment` and `schedule` always run this file from main, whoever comments and wherever.
|
||||
# - It checks out main's script and list only, never a pull request; it reads threads through the API.
|
||||
# - The comment's text and author reach the script as env vars, never in a shell line. The token stays in the step
|
||||
# and can only write issues (assignees, comments, reactions).
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
schedule:
|
||||
- cron: "23 5 * * *"
|
||||
workflow_dispatch:
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
command:
|
||||
# Every other comment skips here, before a runner starts. Pull requests are answered by the script.
|
||||
if: >-
|
||||
github.event_name == 'issue_comment' && github.event.comment.user.type != 'Bot' && (
|
||||
startsWith(github.event.comment.body, '/claim') ||
|
||||
startsWith(github.event.comment.body, '/unclaim') ||
|
||||
startsWith(github.event.comment.body, '🤖 Agent: /claim') ||
|
||||
startsWith(github.event.comment.body, '🤖 Agent: /unclaim'))
|
||||
# One command per issue at a time, so two `/claim`s can't both find it free. On the job, not the workflow:
|
||||
# the skipped runs of ordinary comments must not cancel a waiting one.
|
||||
concurrency:
|
||||
group: claim-${{ github.event.issue.number }}
|
||||
# One of our small runners (horizon-light), out of GitHub's pool: main's script only (docs/ci-runners.md).
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
.github/trusted-reviewers.txt
|
||||
tools/ci/nightly_set.py
|
||||
tools/ci/claim_command.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Run the command
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BODY: ${{ github.event.comment.body }}
|
||||
AUTHOR: ${{ github.event.comment.user.login }}
|
||||
# Who may act is decided by this numeric ID: a login can be claimed by someone else after a rename.
|
||||
AUTHOR_ID: ${{ github.event.comment.user.id }}
|
||||
ISSUE: ${{ github.event.issue.number }}
|
||||
COMMENT_ID: ${{ github.event.comment.id }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: python3 tools/ci/claim_command.py command
|
||||
release:
|
||||
if: github.event_name != 'issue_comment' && github.repository == 'horizon-rust/horizon'
|
||||
# One of our small runners (horizon-light), out of GitHub's pool: main's script only (docs/ci-runners.md).
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
tools/ci/nightly_set.py
|
||||
tools/ci/claim_command.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Release stale claims
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: python3 tools/ci/claim_command.py release
|
||||
@@ -1,359 +0,0 @@
|
||||
name: game build
|
||||
# Builds the game for every platform from `ref`: the Java exporters, then Linux and the Linux server, Windows x64
|
||||
# and ARM64 on GitHub, and macOS on the Mac mini's runner with a 1500-frame offscreen run of a new world (smoke-test.json): Apple
|
||||
# Silicon, and Intel cross-built there for x86_64-apple-darwin and checked under Rosetta 2 (#1161). Called by
|
||||
# release.yml (the releases) and nightly-build.yml (the opt-in Nightly), always from main's copy of this file: the
|
||||
# caller's commit, never the one being built. It holds no secrets: signing the checksums is the callers' own job,
|
||||
# which never runs what this one built. See docs/release-flow.md.
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
ref:
|
||||
description: The commit to build
|
||||
type: string
|
||||
required: true
|
||||
version:
|
||||
description: The version built in (HORIZON_VERSION), e.g. 0.2.81 or nightly-2026-10-28
|
||||
type: string
|
||||
required: true
|
||||
nightly:
|
||||
description: A nightly's "<date> <short sha>" (HORIZON_NIGHTLY), shown by the game; empty for a release
|
||||
type: string
|
||||
default: ''
|
||||
trusted:
|
||||
# Only release.yml says true: it builds main. A nightly can hold pull requests nobody reviewed yet, whose
|
||||
# build scripts and tests run here and could rewrite target/, the cargo home or a compiler cache. So an
|
||||
# untrusted build never runs on the release runner, never saves the Rust cache (its key is its own anyway),
|
||||
# and a trusted one never reads the machine's shared sccache, which pull requests' jobs write
|
||||
# (tests/test_nightly.py pins all of it).
|
||||
description: The source is main (a release); false for anything else (a nightly)
|
||||
type: boolean
|
||||
default: false
|
||||
developer_id:
|
||||
description: Sign the macOS programs with Developer ID and notarize the zip (the runner's keychain)
|
||||
type: boolean
|
||||
default: true
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
exporters:
|
||||
# This runner holds the maintainer's own pinned Minecraft jars. Only our classes leave it. An untrusted build
|
||||
# goes to the Mac mini's nightly runner (macOS + horizon-nightly: ludovics-mac-mini-nightly, beside the one that
|
||||
# runs pull requests' parity jobs, so a nightly never waits behind their queue), never the release runner
|
||||
# (MAC_RUNNER: ludovics-mac-mini-release) nor parity-main's.
|
||||
runs-on: ${{ inputs.trusted && vars.MAC_RUNNER || fromJSON('["self-hosted", "macOS", "horizon-nightly"]') }}
|
||||
# Three full preparations (two isolated, one batched) besides the compile.
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
persist-credentials: false
|
||||
clean: true
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: bash tools/ci/runner-env.sh
|
||||
env:
|
||||
HORIZON_NO_SCCACHE: ${{ inputs.trusted && '1' || '' }}
|
||||
- run: bash tools/ci/vanilla-data.sh
|
||||
- name: Compile and validate original exporters against the pinned jars
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# target/ is gone after the clean checkout, and vanilla-data.sh builds the preparer only when it
|
||||
# prepares afresh.
|
||||
cargo build --release --locked -p horizon-prepare
|
||||
# Compiled here, never taken from the runner's shared preparations: pull requests' parity jobs
|
||||
# write those (vanilla-data.sh links .local/exporters to them).
|
||||
rm -rf .local/exporters
|
||||
bundle=$(target/release/horizon-prepare compile-exporters --root "$PWD" | tail -1)
|
||||
mkdir -p exporters
|
||||
cp -R "$bundle/server" "$bundle/client" "$bundle/manifest.json" exporters/
|
||||
# Only our classes and their manifest leave this runner.
|
||||
stray=$(find exporters -type f ! -path exporters/manifest.json \
|
||||
! \( -name '*.class' \( -path 'exporters/server/dev/horizonlab/parity/*' -o -path 'exporters/client/dev/horizonlab/parity/*' \) \))
|
||||
[ -z "$stray" ] || { echo "::error::not one of our classes: $stray"; exit 1; }
|
||||
python3 tools/check_prepare_exporters.py --binary target/release/horizon-prepare
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: original-exporters
|
||||
path: exporters/
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
|
||||
build:
|
||||
needs: exporters
|
||||
name: build ${{ matrix.name }}
|
||||
# Windows ARM64 and musl are new: a failure never holds the other platforms' release (the signing job
|
||||
# needs this job, and a failed entry of it would fail it). The release steps leave the missing
|
||||
# optional archives out with a warning.
|
||||
continue-on-error: ${{ matrix.name == 'windows-arm64' || matrix.name == 'linux-musl' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: linux
|
||||
os: ubuntu-22.04
|
||||
dir: horizon-linux-x86_64
|
||||
asset: horizon-linux-x86_64.tar.gz
|
||||
# The server build too: packaging/server/install.sh installs it on Linux.
|
||||
server_dir: horizon-server-linux-x86_64
|
||||
server_asset: horizon-server-linux-x86_64.tar.gz
|
||||
- name: linux-musl
|
||||
os: ubuntu-22.04
|
||||
musl: true
|
||||
dir: horizon-linux-musl-x86_64
|
||||
asset: horizon-linux-musl-x86_64.tar.gz
|
||||
- name: windows
|
||||
os: windows-latest
|
||||
dir: horizon-windows-x64
|
||||
asset: horizon-windows-x64.zip
|
||||
exe: .exe
|
||||
pe_arch: x64
|
||||
# The C runtime linked in, so the game runs without the Visual C++ redistributable.
|
||||
rustflags: -C target-feature=+crt-static
|
||||
- name: windows-arm64
|
||||
os: windows-11-vs2026-arm
|
||||
target: aarch64-pc-windows-msvc
|
||||
dir: horizon-windows-arm64
|
||||
asset: horizon-windows-arm64.zip
|
||||
exe: .exe
|
||||
pe_arch: arm64
|
||||
# The ARM64 runner builds and runs native ARM64 executables; keep the C runtime in the archive.
|
||||
rustflags: -C target-feature=+crt-static
|
||||
- name: macos
|
||||
mac: true
|
||||
dir: horizon-macos-arm64
|
||||
asset: horizon-macos-arm64.zip
|
||||
# Intel Macs: built on the same runner for another target; its checks and smoke test run the x86_64
|
||||
# programs under Rosetta 2.
|
||||
- name: macos-x64
|
||||
mac: true
|
||||
target: x86_64-apple-darwin
|
||||
dir: horizon-macos-x64
|
||||
asset: horizon-macos-x64.zip
|
||||
runs-on: ${{ matrix.mac && (inputs.trusted && vars.MAC_RUNNER || fromJSON('["self-hosted", "macOS", "horizon-nightly"]')) || matrix.os }}
|
||||
# Notarizing the zip can take a few minutes.
|
||||
timeout-minutes: ${{ matrix.mac && 60 || 40 }}
|
||||
env:
|
||||
RUSTFLAGS: ${{ matrix.rustflags }}
|
||||
# The release's version, built in (horizon_core::release): --version, user agents, crash reports and
|
||||
# telemetry say it. No version-bump commits.
|
||||
HORIZON_VERSION: ${{ inputs.version }}
|
||||
# A nightly's date and commit ("2026-10-28 0c02067"), which the game shows; empty for a release.
|
||||
HORIZON_NIGHTLY: ${{ inputs.nightly }}
|
||||
# Where cargo puts the programs: target/release, or target/<target>/release for another target.
|
||||
BIN: ${{ matrix.target && format('target/{0}/release', matrix.target) || 'target/release' }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: ${{ inputs.ref }}
|
||||
persist-credentials: false
|
||||
# Always from a clean checkout, the Mac mini's runner too: its work folder is shared with pull requests'
|
||||
# parity jobs, and nothing they leave (target/, an untracked .cargo/config.toml, a build script's output)
|
||||
# may end up in a release. target/ is rebuilt from scratch; .local/ is relinked by vanilla-data.sh, which
|
||||
# keeps its preparations outside the checkout.
|
||||
clean: true
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted' && !matrix.musl
|
||||
with:
|
||||
# A release restores only what a release saved: an untrusted build has its own key and saves nothing.
|
||||
shared-key: ${{ inputs.trusted && 'release' || 'nightly' }}-${{ matrix.name }}
|
||||
save-if: ${{ inputs.trusted }}
|
||||
- name: ALSA and udev headers
|
||||
if: runner.os == 'Linux' && !matrix.musl
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
|
||||
- name: Build the official game, horizon-ctl, horizon-prepare and horizon-server
|
||||
if: ${{ !matrix.musl }}
|
||||
run: cargo build --release --locked ${{ matrix.target && format('--target {0}', matrix.target) || '' }} -p horizon-official --bin horizon-official -p horizon-client-lib --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
|
||||
- name: The official game is the game players get, under its name
|
||||
# horizon-official: horizon-client's game with Horizon's own parts plugged in (docs/layers.md, "How a
|
||||
# Horizon crate plugs in"). Everything below, the launcher and players know it as horizon-client.
|
||||
if: ${{ !matrix.musl }}
|
||||
run: cp -f "$BIN/horizon-official${{ matrix.exe }}" "$BIN/horizon-client${{ matrix.exe }}"
|
||||
- name: Every program the release folder takes was built
|
||||
if: ${{ !matrix.musl }}
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
test -f "$BIN/$binary${{ matrix.exe }}" || { echo "::error::$BIN/$binary${{ matrix.exe }} is missing"; exit 1; }
|
||||
done
|
||||
- name: Verify Windows executable architecture
|
||||
if: runner.os == 'Windows'
|
||||
run: |
|
||||
python tools/check_pe_arch.py "${{ matrix.pe_arch }}" \
|
||||
"$BIN/horizon-client${{ matrix.exe }}" "$BIN/horizon-ctl${{ matrix.exe }}" \
|
||||
"$BIN/horizon-prepare${{ matrix.exe }}" "$BIN/horizon-server${{ matrix.exe }}"
|
||||
- name: The signing keychain, unlocked
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != '' && inputs.developer_id
|
||||
env:
|
||||
MACOS_SIGN_IDENTITY: ${{ vars.MACOS_SIGN_IDENTITY }}
|
||||
run: packaging/macos/keychain.sh unlock
|
||||
- name: Signed with Developer ID and the hardened runtime
|
||||
# Before the checks below, so they run the programs as players will.
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != '' && inputs.developer_id
|
||||
env:
|
||||
MACOS_SIGN_IDENTITY: ${{ vars.MACOS_SIGN_IDENTITY }}
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
codesign --force --options runtime --timestamp --keychain "$MACOS_SIGN_KEYCHAIN" \
|
||||
--identifier "dev.horizon.${binary#horizon-}" --sign "$MACOS_SIGN_IDENTITY" "$BIN/$binary"
|
||||
codesign --verify --strict --verbose=2 "$BIN/$binary"
|
||||
done
|
||||
- name: Only system libraries
|
||||
if: ${{ !matrix.musl }}
|
||||
# Windows: no non-system DLL (a "DLL not found" dialog on some players' machines). Linux: the standard
|
||||
# loader and libraries every desktop distribution has. macOS: only the system's own libraries.
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
file="$BIN/$binary${{ matrix.exe }}"
|
||||
if [[ "$RUNNER_OS" == macOS ]]; then
|
||||
others=$(otool -L "$file" | tail -n +2 | awk '{print $1}' | grep -v -E '^(/usr/lib/|/System/Library/)' || true)
|
||||
[[ -z "$others" ]] || { echo "::error::$binary links $others"; exit 1; }
|
||||
else
|
||||
${{ runner.os == 'Windows' && 'python' || 'python3' }} tools/check_imports.py "$file"
|
||||
fi
|
||||
done
|
||||
- name: Baseline x86-64 CPUs only
|
||||
# No POPCNT or LZCNT at all (the script says why only those): a C library's count intrinsic killed the
|
||||
# game before main on a Core 2 (#7264). Not the Mac builds: every Intel Mac that runs macOS 11 has both.
|
||||
if: runner.os != 'macOS' && matrix.pe_arch != 'arm64' && !matrix.musl
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rustup component add llvm-tools
|
||||
${{ runner.os == 'Windows' && 'python' || 'python3' }} tools/check_cpu_baseline.py \
|
||||
$(for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do echo "$BIN/$binary${{ matrix.exe }}"; done)
|
||||
- name: Every program starts
|
||||
if: ${{ !matrix.musl }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bin=$BIN
|
||||
"$bin/horizon-client${{ matrix.exe }}" --help | grep -q -- '--resources'
|
||||
"$bin/horizon-ctl${{ matrix.exe }}" --help > /dev/null
|
||||
"$bin/horizon-prepare${{ matrix.exe }}" --help | grep -q -- '--minecraft-dir'
|
||||
# The version is the release's.
|
||||
for binary in horizon-prepare horizon-server; do
|
||||
out=$("$bin/$binary${{ matrix.exe }}" --version | tr -d '\r')
|
||||
echo "$out"
|
||||
[[ "$out" == "$binary $HORIZON_VERSION" ]] || { echo "::error::expected $binary $HORIZON_VERSION"; exit 1; }
|
||||
done
|
||||
- name: Tools from the runner
|
||||
if: runner.environment == 'self-hosted'
|
||||
env:
|
||||
HORIZON_NO_SCCACHE: ${{ inputs.trusted && '1' || '' }}
|
||||
run: bash tools/ci/runner-env.sh
|
||||
- name: Resources prepared from the runner's own Minecraft
|
||||
if: runner.environment == 'self-hosted'
|
||||
run: bash tools/ci/vanilla-data.sh
|
||||
- name: The game runs (offscreen, a new world, 1500 frames)
|
||||
if: runner.environment == 'self-hosted'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# From a scratch folder: the game keeps its saves and options in the folder it starts in.
|
||||
home="$RUNNER_TEMP/horizon-smoke"
|
||||
rm -rf "$home" && mkdir -p "$home"
|
||||
version=$(sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' research-lock.json | head -1)
|
||||
client="$PWD/$BIN/horizon-client"
|
||||
resources="$PWD/.local/horizon-client/$version"
|
||||
(cd "$home" && HORIZON_HOME="$home" HORIZON_NO_AUDIO=1 "$client" --resources "$resources" --offscreen \
|
||||
--world smoke --seed 1 --render-distance 4 --world-frames 1500 --timeout-seconds 180 \
|
||||
--smoke-report "$home/smoke.json" > "$home/client.log" 2>&1) || { tail -40 "$home/client.log"; exit 1; }
|
||||
python3 - "$home/smoke.json" <<'EOF'
|
||||
import json, sys
|
||||
report = json.load(open(sys.argv[1]))
|
||||
print(json.dumps(report))
|
||||
if report.get("error") is not None or report.get("frames", 0) < 1500 or not report.get("chunks") \
|
||||
or not report.get("meshed_sections") or not report.get("player"):
|
||||
sys.exit("the smoke run did not draw a world")
|
||||
EOF
|
||||
# Published with the release; the publish job checks it again before it publishes anything.
|
||||
cp "$home/smoke.json" "$RUNNER_TEMP/smoke-test.json"
|
||||
# One smoke-test.json per build, the Apple Silicon one's; the Intel build must pass its own run too.
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: runner.environment == 'self-hosted' && !matrix.target
|
||||
with:
|
||||
name: smoke-test.json
|
||||
path: ${{ runner.temp }}/smoke-test.json
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
name: original-exporters
|
||||
path: exporters
|
||||
- name: Build, check and package for musl in Alpine
|
||||
if: matrix.musl
|
||||
# Run Docker on the Ubuntu host: JavaScript actions themselves require glibc.
|
||||
run: |
|
||||
docker run --rm -v "$PWD:/work" -w /work \
|
||||
-e HORIZON_VERSION -e HORIZON_NIGHTLY \
|
||||
rust:alpine3.22 sh tools/ci/build-musl.sh
|
||||
- name: Package
|
||||
if: ${{ !matrix.musl }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo run --locked -p xtask -- package "$BIN/horizon-client${{ matrix.exe }}" "dist/${{ matrix.dir }}"
|
||||
# Windows x64: Microsoft's DXC, pinned and checksummed, which DirectX 12 uses on integrated GPUs
|
||||
# (gfx/dx12_compiler.rs), with its licence. ARM64 keeps FXC (THIRD_PARTY_NOTICES.md says why).
|
||||
if [[ "${{ matrix.name }}" == windows ]]; then
|
||||
python tools/ci/fetch_dxc.py "dist/${{ matrix.dir }}"
|
||||
fi
|
||||
cd dist
|
||||
rm -f "${{ matrix.asset }}"
|
||||
case "${{ matrix.asset }}" in
|
||||
*.tar.gz) tar czf "${{ matrix.asset }}" "${{ matrix.dir }}" ;;
|
||||
*) if [[ "$RUNNER_OS" == Windows ]]; then 7z a -tzip "${{ matrix.asset }}" "${{ matrix.dir }}" > /dev/null
|
||||
else
|
||||
# Without resource forks and extended attributes: plain ditto adds an
|
||||
# AppleDouble `._` file beside every file that has any.
|
||||
ditto -c -k --norsrc --noextattr --noqtn --keepParent "${{ matrix.dir }}" "${{ matrix.asset }}"
|
||||
if unzip -Z1 "${{ matrix.asset }}" | grep -E '(^|/)(\._|__MACOSX/)'; then
|
||||
echo "::error::macOS metadata files in ${{ matrix.asset }}"; exit 1
|
||||
fi
|
||||
fi ;;
|
||||
esac
|
||||
ls -l "${{ matrix.asset }}"
|
||||
- name: Notarized
|
||||
# A zip of programs can't be stapled: Gatekeeper asks Apple the first time each one runs.
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != '' && inputs.developer_id
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
codesign --verify --strict "dist/${{ matrix.dir }}/$binary"
|
||||
done
|
||||
packaging/macos/notarize.sh "dist/${{ matrix.asset }}"
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: dist/${{ matrix.asset }}
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- name: The server build (the game without sound or controllers, as horizon-engine)
|
||||
if: matrix.server_asset
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# After the client is packaged: target/release/horizon-client is rebuilt without the audio and
|
||||
# controllers features, so it needs neither libasound nor libudev (minimal server images lack them).
|
||||
cargo build --release --locked -p horizon-client --no-default-features --bin horizon-client
|
||||
cargo run --locked -p xtask -- package-server target/release/horizon-client "dist/${{ matrix.server_dir }}"
|
||||
folder="dist/${{ matrix.server_dir }}"
|
||||
python3 tools/check_imports.py --server "$folder/horizon-engine" "$folder/horizon-server" "$folder/horizon-prepare"
|
||||
"$folder/horizon-engine" --help | grep -q -- '--resources'
|
||||
[[ "$("$folder/horizon-server" --version)" == "horizon-server $HORIZON_VERSION" ]]
|
||||
cd dist
|
||||
rm -f "${{ matrix.server_asset }}"
|
||||
tar czf "${{ matrix.server_asset }}" "${{ matrix.server_dir }}"
|
||||
ls -l "${{ matrix.server_asset }}"
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: matrix.server_asset
|
||||
with:
|
||||
name: ${{ matrix.server_asset }}
|
||||
path: dist/${{ matrix.server_asset }}
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- name: The signing keychain, locked again
|
||||
if: always() && runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != '' && inputs.developer_id
|
||||
run: packaging/macos/keychain.sh lock
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: launcher
|
||||
# Builds the launcher on Linux, macOS, Windows x64 and ARM64, and releases it by itself (docs/release-flow.md): after a
|
||||
# Builds the launcher on Linux, macOS and Windows, and releases it by itself (docs/release-flow.md): after a
|
||||
# push to main that changes the launcher or a crate it builds in (the paths below),
|
||||
# every 10 minutes (a release waiting for merges to settle goes out) and by hand, tools/release_train.py decides as
|
||||
# for the game.
|
||||
@@ -8,16 +8,9 @@ name: launcher
|
||||
# feature. The version and the tag are given to the build (HORIZON_LAUNCHER_VERSION, HORIZON_LAUNCHER_TAG): no bump
|
||||
# commits.
|
||||
# Never marked latest. Pushes to launcher branches only build. RELEASES_PAUSED=1 stops releases.
|
||||
# Linux ships two archives of one binary: the .tar.gz the launcher updates itself from, and an
|
||||
# AppImage (packaging/linux/appimage.sh) for players without a distribution package, which replaces
|
||||
# itself instead (launcher/src/backend.rs).
|
||||
# macOS: Apple Silicon, and Intel cross-built for x86_64-apple-darwin on the same runner, its tests and smoke test
|
||||
# under Rosetta 2 (#1161). With the repository variable MACOS_SIGN_IDENTITY set, Horizon.app and the .dmg are signed with
|
||||
# macOS: with the repository variable MACOS_SIGN_IDENTITY set, Horizon.app and the .dmg are signed with
|
||||
# Developer ID, notarized and stapled, from the runner's signing keychain (packaging/macos/README.md);
|
||||
# unset (forks), they are signed ad hoc.
|
||||
# Windows ships each architecture's launcher in its ZIP (what a launcher updates itself from) and as
|
||||
# horizon-launcher-setup.exe or horizon-launcher-setup-arm64.exe, which opens the per-user installer instead of Home
|
||||
# (launcher/src/installer.rs).
|
||||
# gh workflow run launcher --ref <branch> # dry run: builds everything, publishes nothing
|
||||
# gh workflow run launcher --ref main -f dry_run=false -f force=true
|
||||
|
||||
@@ -25,19 +18,16 @@ on:
|
||||
push:
|
||||
branches: [main, launcher, 'launcher-*']
|
||||
paths:
|
||||
# Everything the launcher is built and packaged from, as tools/release_train.py's LAUNCHER_PATHS.
|
||||
# Every crate the launcher builds in, as tools/release_train.py's LAUNCHER_PATHS.
|
||||
- 'launcher/**'
|
||||
- 'crates/horizon-bench/**'
|
||||
- 'crates/horizon-friends/**'
|
||||
- 'crates/horizon-mcp/**'
|
||||
- 'crates/horizon-mods/**'
|
||||
- 'crates/horizon-port-pack/**'
|
||||
- 'crates/horizon-prepare/**'
|
||||
- 'crates/horizon-release-sign/**'
|
||||
- 'crates/horizon-telemetry/**'
|
||||
- 'crates/horizon-theme/**'
|
||||
- 'packaging/linux/**'
|
||||
- 'packaging/icons/**'
|
||||
- '.github/workflows/launcher.yml'
|
||||
schedule:
|
||||
- cron: '7-59/10 * * * *'
|
||||
@@ -74,7 +64,7 @@ jobs:
|
||||
version: ${{ steps.decide.outputs.version }}
|
||||
dry_run: ${{ steps.mode.outputs.dry_run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: mode
|
||||
@@ -103,10 +93,6 @@ jobs:
|
||||
needs: decide
|
||||
if: needs.decide.outputs.release == 'true'
|
||||
name: build ${{ matrix.name }}
|
||||
# Windows ARM64 is new: its failure never holds the other platforms' release (the signing job
|
||||
# needs this job, and a failed entry of it would fail it). The release steps leave the missing
|
||||
# ARM64 files out with a warning.
|
||||
continue-on-error: ${{ matrix.name == 'windows-arm64' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -119,38 +105,18 @@ jobs:
|
||||
mac: true
|
||||
asset: horizon-launcher-macos-arm64.zip
|
||||
binary: horizon-launcher
|
||||
mac_arch: arm64
|
||||
- name: macos-x64
|
||||
mac: true
|
||||
target: x86_64-apple-darwin
|
||||
asset: horizon-launcher-macos-x64.zip
|
||||
binary: horizon-launcher
|
||||
mac_arch: x64
|
||||
- name: windows
|
||||
os: windows-latest
|
||||
asset: horizon-launcher-windows-x64.zip
|
||||
binary: horizon-launcher.exe
|
||||
pe_arch: x64
|
||||
setup_asset: horizon-launcher-setup.exe
|
||||
# The C runtime linked in: without it the launcher asks for VCRUNTIME140.dll,
|
||||
# which only the Visual C++ redistributable installs.
|
||||
rustflags: -C target-feature=+crt-static
|
||||
- name: windows-arm64
|
||||
os: windows-11-vs2026-arm
|
||||
target: aarch64-pc-windows-msvc
|
||||
asset: horizon-launcher-windows-arm64.zip
|
||||
binary: horizon-launcher.exe
|
||||
pe_arch: arm64
|
||||
setup_asset: horizon-launcher-setup-arm64.exe
|
||||
# The C runtime linked in, so the standalone ARM64 launcher needs no redistributable.
|
||||
rustflags: -C target-feature=+crt-static
|
||||
runs-on: ${{ matrix.mac && (vars.MAC_RUNNER || 'ludovics-mac-mini') || matrix.os }}
|
||||
# Notarizing the app and then the .dmg can take a few minutes each.
|
||||
timeout-minutes: ${{ matrix.mac && 60 || 40 }}
|
||||
env:
|
||||
RUSTFLAGS: ${{ matrix.rustflags }}
|
||||
# Where cargo puts the launcher: target/release, or target/<target>/release for another target.
|
||||
BIN: ${{ matrix.target && format('target/{0}/release', matrix.target) || 'target/release' }}
|
||||
# Horizon's Azure app for Microsoft sign-in (docs/microsoft-account.md): a repository
|
||||
# variable, not a secret. Unset, the launcher says sign-in is not configured.
|
||||
HORIZON_MSA_CLIENT_ID: ${{ vars.HORIZON_MSA_CLIENT_ID }}
|
||||
@@ -166,7 +132,7 @@ jobs:
|
||||
working-directory: launcher
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide.outputs.head }}
|
||||
persist-credentials: false
|
||||
@@ -174,8 +140,6 @@ jobs:
|
||||
# parity jobs, and nothing they leave may end up in a launcher release (target/ is rebuilt from scratch).
|
||||
clean: true
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
targets: ${{ matrix.target }}
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted'
|
||||
with:
|
||||
@@ -185,7 +149,7 @@ jobs:
|
||||
if: runner.os == 'Linux'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libxkbcommon-x11-dev libwayland-dev libx11-xcb-dev libfontconfig-dev libvulkan-dev libasound2-dev patchelf
|
||||
sudo apt-get install -y libxkbcommon-x11-dev libwayland-dev libx11-xcb-dev libfontconfig-dev libvulkan-dev libasound2-dev
|
||||
- name: Metal shaders compiled now, or at run time without the Metal toolchain
|
||||
# GPUI compiles its Metal shaders when it builds; the Mac mini has Xcode without the Metal toolchain
|
||||
# (xcodebuild -downloadComponent MetalToolchain), so there they are compiled when the launcher starts.
|
||||
@@ -193,26 +157,20 @@ jobs:
|
||||
run: |
|
||||
if ! xcrun metal --version > /dev/null 2>&1; then
|
||||
echo "::notice::No Metal toolchain on this runner: GPUI compiles its shaders at run time"
|
||||
echo "LAUNCHER_FEATURES=gpui_platform/runtime_shaders" >> "$GITHUB_ENV"
|
||||
echo "LAUNCHER_FEATURES=gpui/runtime_shaders" >> "$GITHUB_ENV"
|
||||
fi
|
||||
# Every test target (the library, the binary, tests/), on each system the launcher ships for.
|
||||
- run: cargo test --release --locked ${{ matrix.target && format('--target {0}', matrix.target) || '' }} ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
|
||||
- run: cargo build --release --locked ${{ matrix.target && format('--target {0}', matrix.target) || '' }} ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
|
||||
- name: Verify Windows executable architecture
|
||||
if: runner.os == 'Windows'
|
||||
run: python ../tools/check_pe_arch.py "${{ matrix.pe_arch }}" "$BIN/${{ matrix.binary }}"
|
||||
- name: Unrelated DLLs cannot intercept launcher or setup startup
|
||||
if: runner.os == 'Windows'
|
||||
run: python ../tools/test_launcher_dll_search.py "$BIN/${{ matrix.binary }}"
|
||||
- run: cargo test --release --locked ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
|
||||
- run: cargo build --release --locked ${LAUNCHER_FEATURES:+--features "$LAUNCHER_FEATURES"}
|
||||
- name: The version is the release's
|
||||
run: |
|
||||
out=$("$BIN/${{ matrix.binary }}" --version)
|
||||
out=$(target/release/${{ matrix.binary }} --version)
|
||||
echo "$out"
|
||||
expected="${HORIZON_LAUNCHER_VERSION:-$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)}"
|
||||
[[ "$out" == "horizon-launcher $expected" ]] || { echo "::error::expected horizon-launcher $expected"; exit 1; }
|
||||
- name: Only system libraries
|
||||
run: |
|
||||
file="$BIN/${{ matrix.binary }}"
|
||||
file=target/release/${{ matrix.binary }}
|
||||
case "$RUNNER_OS" in
|
||||
Windows) python ../tools/check_imports.py "$file" ;;
|
||||
macOS) others=$(otool -L "$file" | tail -n +2 | awk '{print $1}' | grep -v -E '^(/usr/lib/|/System/Library/)' || true)
|
||||
@@ -227,43 +185,20 @@ jobs:
|
||||
export HORIZON_LAUNCHER_HOME="${RUNNER_TEMP//\\//}/horizon-launcher-smoke"
|
||||
export HORIZON_HOME="$HORIZON_LAUNCHER_HOME/game"
|
||||
rm -rf "$HORIZON_LAUNCHER_HOME"
|
||||
launcher="$PWD/$BIN/${{ matrix.binary }}"
|
||||
launcher="$PWD/target/release/${{ matrix.binary }}"
|
||||
# GitHub's API rate-limits shared runner addresses now and then: try a few times.
|
||||
retry() { for i in 1 2 3 4; do "$@" && return 0; sleep $((i * 15)); done; return 1; }
|
||||
retry "$launcher" versions
|
||||
"$launcher" links --json
|
||||
# The Intel Mac launcher can come out before any game build has its asset (#1161): then there is nothing
|
||||
# to install yet. Only that entry skips, and only on a version list that parsed and had no build here
|
||||
# (exit 3); a launcher or a script that fails still fails the step. The Windows ARM64 launcher always has
|
||||
# one: it installs the x64 build where a release has no ARM64 one (backend.rs, GAME_FALLBACK).
|
||||
if [[ "${{ matrix.name }}" == macos-x64 ]]; then
|
||||
versions=$(retry "$launcher" --json versions)
|
||||
no_build='import json, sys; sys.exit(3 if not any(r["available_here"] for r in json.load(sys.stdin)) else 0)'
|
||||
status=0
|
||||
python3 -c "$no_build" <<<"$versions" || status=$?
|
||||
if [[ $status == 3 ]]; then
|
||||
echo "::warning::No game build has an asset for ${{ matrix.name }} yet: install not tested"
|
||||
rm -rf "$HORIZON_LAUNCHER_HOME"
|
||||
exit 0
|
||||
fi
|
||||
[[ $status == 0 ]] || exit $status
|
||||
fi
|
||||
retry "$launcher" install latest
|
||||
"$launcher" versions --installed
|
||||
# `install latest` is the Nightly since #3342 (versions/nightly-<date>-<commit>), a vX.Y.Z before.
|
||||
clients=("$HORIZON_LAUNCHER_HOME"/versions/*/horizon-client*)
|
||||
"$launcher" links --json
|
||||
clients=("$HORIZON_LAUNCHER_HOME"/versions/v*/horizon-client*)
|
||||
client="${clients[0]}"
|
||||
echo "installed client: $client"
|
||||
[[ -f "$client" ]] || { echo "::error::no game installed under versions/"; exit 1; }
|
||||
# The game's Linux build is the game's to keep portable (release.yml checks it): a
|
||||
# release linked to a Nix store is a warning here, not a broken launcher.
|
||||
soft() { if [[ "$RUNNER_OS" == "Linux" ]]; then "$@" || echo "::warning::$* failed"; else "$@"; fi; }
|
||||
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||
if ! python ../tools/check_pe_arch.py "${{ matrix.pe_arch }}" "$client"; then
|
||||
# A Nightly without an ARM64 build: the ARM64 launcher installs the x64 one (backend.rs, GAME_FALLBACK).
|
||||
[[ "${{ matrix.pe_arch }}" == arm64 ]] && python ../tools/check_pe_arch.py x64 "$client" || exit 1
|
||||
echo "::warning::the latest game has no ARM64 build: the launcher installed the x64 one"
|
||||
fi
|
||||
python ../tools/check_imports.py "$client"
|
||||
elif [[ "$RUNNER_OS" == "Linux" ]]; then
|
||||
soft python3 ../tools/check_imports.py "$client"
|
||||
@@ -271,18 +206,6 @@ jobs:
|
||||
# The client starts: --help prints before any window or GPU is needed.
|
||||
help() { "$client" --help > "$RUNNER_TEMP/help.txt" 2>&1 && head -3 "$RUNNER_TEMP/help.txt" && grep -q -- '--resources' "$RUNNER_TEMP/help.txt"; }
|
||||
soft help
|
||||
# The per-user Windows setup: the same binary under the setup's name installs into a scratch
|
||||
# folder, and the copy it installs uninstalls itself. HKCU of the runner only.
|
||||
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||
setup="$RUNNER_TEMP/setup-smoke"
|
||||
cp "$launcher" "$RUNNER_TEMP/horizon-launcher-setup.exe"
|
||||
"$RUNNER_TEMP/horizon-launcher-setup.exe" setup --quiet --dir "$setup"
|
||||
installed="$setup/Horizon Launcher/horizon-launcher.exe"
|
||||
[[ -f "$installed" ]] || { echo "::error::the setup copied no launcher"; exit 1; }
|
||||
"$installed" uninstall --quiet
|
||||
[[ ! -f "$installed" ]] || { echo "::error::uninstall left the launcher"; exit 1; }
|
||||
rm -rf "$setup"
|
||||
fi
|
||||
rm -rf "$HORIZON_LAUNCHER_HOME"
|
||||
- name: The signing keychain, unlocked
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != ''
|
||||
@@ -299,18 +222,11 @@ jobs:
|
||||
# Developer ID): packaging/macos.
|
||||
python3 -m venv "$RUNNER_TEMP/dmg" && "$RUNNER_TEMP/dmg/bin/pip" install --quiet dmgbuild==1.6.5
|
||||
version=${HORIZON_LAUNCHER_VERSION:-$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)}
|
||||
DMGBUILD="$RUNNER_TEMP/dmg/bin/dmgbuild" ../packaging/macos/package.sh "$BIN/${{ matrix.binary }}" "$version" out ${{ matrix.mac_arch }}
|
||||
DMGBUILD="$RUNNER_TEMP/dmg/bin/dmgbuild" ../packaging/macos/package.sh target/release/${{ matrix.binary }} "$version" out
|
||||
rm -rf out/Horizon.app
|
||||
else
|
||||
version=${HORIZON_LAUNCHER_VERSION:-$(sed -n 's/^version = "\(.*\)"/\1/p' Cargo.toml | head -1)}
|
||||
if [[ "$RUNNER_OS" == "Linux" ]]; then
|
||||
# The .tar.gz below is what the launcher updates itself from; the AppImage is what a
|
||||
# player downloads and double-clicks, and it replaces itself instead
|
||||
# (packaging/linux/appimage.sh, launcher/src/backend.rs).
|
||||
../packaging/linux/appimage.sh "$BIN/${{ matrix.binary }}" "$version" out
|
||||
fi
|
||||
mkdir -p dist
|
||||
cp "$BIN/${{ matrix.binary }}" dist/
|
||||
cp target/release/${{ matrix.binary }} dist/
|
||||
if [[ "${{ matrix.asset }}" == *.tar.gz ]]; then
|
||||
(cd dist && tar czf ../out/${{ matrix.asset }} ${{ matrix.binary }})
|
||||
else
|
||||
@@ -318,13 +234,7 @@ jobs:
|
||||
fi
|
||||
fi
|
||||
ls -l out
|
||||
- name: Setup exe (Windows)
|
||||
# The launcher's binary under another name: started with no arguments it shows the per-user
|
||||
# installer instead of Home (launcher/src/installer.rs). Its name is what makes it the setup,
|
||||
# so the ZIP's copy stays the launcher. Both go into the release's signed SHA256SUMS.
|
||||
if: runner.os == 'Windows'
|
||||
run: cp "$BIN/${{ matrix.binary }}" "out/${{ matrix.setup_asset }}"
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: launcher/out/*
|
||||
@@ -342,12 +252,12 @@ jobs:
|
||||
# tools/ci/sign_release.sh, which calls only the runner's sha256sum and OpenSSL (docs/release-flow.md).
|
||||
environment: ${{ needs.decide.outputs.dry_run != 'true' && 'release' || '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: tools/ci/sign_release.sh
|
||||
sparse-checkout-cone-mode: false
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
pattern: horizon-launcher-*
|
||||
@@ -359,13 +269,13 @@ jobs:
|
||||
EPHEMERAL: ${{ needs.decide.outputs.dry_run == 'true' && 'yes' || '' }}
|
||||
TAG: ${{ needs.decide.outputs.tag }}
|
||||
run: bash tools/ci/sign_release.sh "$TAG" dist/horizon-launcher-*
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: signature
|
||||
path: dist/SHA256SUMS*
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: needs.decide.outputs.dry_run == 'true'
|
||||
with:
|
||||
name: ephemeral.pub
|
||||
@@ -379,7 +289,7 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Notes
|
||||
@@ -389,7 +299,7 @@ jobs:
|
||||
python3 tools/release_train.py notes --kind launcher --tag "${{ needs.decide.outputs.tag }}" \
|
||||
--head "${{ needs.decide.outputs.head }}" --out notes > /dev/null
|
||||
{ echo "## $(cat notes/title.txt)"; echo; cat notes/body.md; } >> "$GITHUB_STEP_SUMMARY"
|
||||
- uses: actions/download-artifact@v8
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
@@ -401,13 +311,6 @@ jobs:
|
||||
key=(); [[ -n "$EPHEMERAL" ]] && key=(--key "$(cat dist/ephemeral.pub)")
|
||||
cargo run --locked --quiet -p horizon-release-sign -- verify --tag "$TAG" --publishing "${key[@]}" dist
|
||||
# Never marked latest: Horizon's own releases stay the repository's latest.
|
||||
- name: The Windows ARM64 launcher, if it built
|
||||
# Its build may fail without holding the release (continue-on-error): the release then has no ARM64
|
||||
# files, and ARM64 launchers stay on their version until one has (backend::launcher_update_from).
|
||||
run: |
|
||||
for file in horizon-launcher-windows-arm64.zip horizon-launcher-setup-arm64.exe; do
|
||||
[[ -f "dist/$file" ]] || echo "::warning::$file is missing: this release goes out without it"
|
||||
done
|
||||
- name: Publish ${{ needs.decide.outputs.tag }}
|
||||
if: needs.decide.outputs.dry_run != 'true'
|
||||
env:
|
||||
@@ -422,7 +325,7 @@ jobs:
|
||||
run: |
|
||||
echo "Would publish ${{ needs.decide.outputs.tag }} at ${{ needs.decide.outputs.head }}: $(cat notes/title.txt)"
|
||||
ls -l dist
|
||||
- uses: actions/upload-artifact@v7
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: launcher-release-notes
|
||||
path: notes/
|
||||
|
||||
@@ -15,23 +15,17 @@ on:
|
||||
- '.github/workflows/mod-registry.yml'
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
group: mod-registry-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
jobs:
|
||||
check:
|
||||
# Our checks runners (label horizon-checks, docs/ci-runners.md); SELF_HOSTED_CI=light or off: GitHub's.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && vars.SELF_HOSTED_CI != 'light' && fromJSON('["self-hosted", "linux", "horizon-checks"]') || 'ubuntu-latest' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
defaults:
|
||||
run:
|
||||
working-directory: crates/horizon-mod-registry
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
- run: rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
# Ours keep their build folder between jobs.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted'
|
||||
with:
|
||||
workspaces: crates/horizon-mod-registry
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
name: mojang republish
|
||||
# Hourly: does Mojang's version manifest list a pinned-version JSON that research-lock.json does not know?
|
||||
# If so, one issue "Mojang republished <version>: <sha8>" with the hashes and a lock snippet
|
||||
# (tools/ci/mojang_republish.py). Reads only Mojang's public manifest.
|
||||
# gh workflow run "mojang republish" -f dry_run=true
|
||||
on:
|
||||
schedule:
|
||||
- cron: '23 * * * *' # hourly: a republished JSON breaks horizon-prepare for every new player until accepted
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: Only print what it would do with issues
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
concurrency:
|
||||
group: mojang-republish
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
check:
|
||||
# One of our small runners (label horizon-light, docs/ci-runners.md): main's script, Mojang's public manifest.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- name: Check the manifest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: python3 tools/ci/mojang_republish.py ${{ inputs.dry_run && '--dry-run' || '' }}
|
||||
@@ -1,59 +0,0 @@
|
||||
name: native hook stamp
|
||||
# Opens a PR that numbers pending fragments after they merge. Only pushes to
|
||||
# main run main's own tool; fragments are read as data, not PR code.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'tools/native-hook-fragments/*.json'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: native-hook-stamp
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
stamp:
|
||||
if: github.repository == 'horizon-rust/horizon'
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
- name: Open a stamp pull request
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
set -eu
|
||||
branch=automation/native-hook-stamp
|
||||
if [ -n "$(gh pr list --state open --head "$branch" --json number --jq '.[0].number // empty')" ]; then
|
||||
echo "A stamp pull request is already open."
|
||||
exit 0
|
||||
fi
|
||||
python3 tools/stamp_native_hooks.py
|
||||
if git diff --quiet; then
|
||||
echo "No fragments to stamp."
|
||||
exit 0
|
||||
fi
|
||||
git config user.name 'github-actions[bot]'
|
||||
git config user.email '41898282+github-actions[bot]@users.noreply.github.com'
|
||||
git checkout -b "$branch"
|
||||
git add -u
|
||||
git commit -m 'Stamp native hook API fragments'
|
||||
if git ls-remote --exit-code --heads origin "$branch" >/dev/null; then
|
||||
git fetch origin "+refs/heads/$branch:refs/remotes/origin/$branch"
|
||||
fi
|
||||
git push --force-with-lease origin "$branch"
|
||||
# The repo doesn't let GitHub Actions open pull requests (that setting would also let it approve them):
|
||||
# the branch is pushed, and a maintainer opens the PR from it.
|
||||
if ! gh pr create --base main --head "$branch" --title 'Stamp native hook API fragments' --body 'Assign API numbers to the pending native hook fragments. Close and reopen this PR to run CI.'; then
|
||||
echo "::warning::Stamped fragments are on $branch; open a pull request from it (GitHub Actions may not open one here)."
|
||||
fi
|
||||
@@ -1,315 +0,0 @@
|
||||
name: nightly build
|
||||
run-name: nightly build${{ inputs.request && format(' (request {0})', inputs.request) || '' }}
|
||||
# The Nightly, the only build Horizon ships since 2026-10-28 (docs/release-flow.md "Nightly"; Ludovic). When the batch
|
||||
# train decides (release.yml, with the commit as `base`), once a night, and when a trusted
|
||||
# reviewer asks (`/nightly 2640 2642`, nightly-command.yml), it builds main plus the pull requests the reviewers
|
||||
# picked, merged in order (tools/ci/nightly_set.py), or main alone with none picked. Main is its newest commit where
|
||||
# checks and parity-main passed (or the `base` input), as for a release, and no Nightly is published while a
|
||||
# release-blocker is open. It publishes the result as the `nightly` pre-release, which every launcher and
|
||||
# `horizon-server update` install. The previous nightly stays a week as nightly-<date>.
|
||||
#
|
||||
# Why the signing key never meets the pull requests' code:
|
||||
# - `pick` merges the picked heads onto main with `git merge-tree --write-tree`: git objects only, no working tree,
|
||||
# so none of their files reaches the disk and no hook, filter or script of theirs runs. It refuses any pull
|
||||
# request that changes a path CODEOWNERS gives to Ludovic (this folder, tools/ci/, the signing and update code),
|
||||
# pushes the merge as nightly/build-<date>-<n> and saves the set on the nightly-state branch.
|
||||
# - This file, game-build.yml and every script below run from main's copy: a schedule runs the default branch, and
|
||||
# `uses: ./…` takes the caller's commit. A picked pull request's own .github/ is never read.
|
||||
# - `build` (game-build.yml, `trusted: false`) never reaches a release's tools: its macOS jobs run on the runner
|
||||
# that already runs pull requests' parity jobs, never the release runner; its Rust cache has its own key and is
|
||||
# never saved; and releases don't read the machine's shared sccache.
|
||||
# - `build` (game-build.yml) checks out and compiles the merge with no secrets: its token reads contents only and
|
||||
# isn't kept in the checkout; the macOS programs are signed ad hoc (Developer ID needs the runner's keychain,
|
||||
# which stays locked for nightlies).
|
||||
# - `sign` is the only job with RELEASE_SIGNING_KEY. It checks out nothing but main's tools/ci/sign_release.sh, which
|
||||
# runs the runner's sha256sum and OpenSSL over the archives: it hashes them, never runs them. The signed message
|
||||
# names the channel ("horizon release nightly"), so a nightly's signature can't pass for a release's.
|
||||
# - `publish` verifies the signature with main's horizon-release-sign, checks the smoke test, and only then moves
|
||||
# the tag. Like sign, it never executes what build produced.
|
||||
# - The source ships with the build: `pick` writes horizon-source.tar.gz with `git archive` (git objects again, nothing
|
||||
# run), `sign` signs it with the builds, and `publish` attaches it and tags the commit nightly-source/<date>-<short>
|
||||
# for good (the dated release and the build branch go after 7 days; native mods pin the commit: docs/native-mods.md).
|
||||
# gh workflow run "nightly build" # now (skips when the pick is the same commit as last night's)
|
||||
# gh workflow run "nightly build" -f force=true # build and publish even if unchanged
|
||||
# gh workflow run "nightly build" -f dry_run=true # build and sign with a throwaway key, publish nothing
|
||||
on:
|
||||
schedule:
|
||||
- cron: '17 20 * * *' # 20:17 UTC: after the day's waves, before the 03:07 Paris parity audit takes the Mac mini
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force:
|
||||
description: Build and publish even if tonight's pick is the commit already published
|
||||
type: boolean
|
||||
default: false
|
||||
dry_run:
|
||||
description: Build and sign with a throwaway key, publish nothing
|
||||
type: boolean
|
||||
default: false
|
||||
issue:
|
||||
description: The issue or pull request whose `/nightly` comment asked for this build (answered there)
|
||||
type: string
|
||||
default: ''
|
||||
request:
|
||||
description: The command's id, in the run's name so it can link the run
|
||||
type: string
|
||||
default: ''
|
||||
prs:
|
||||
description: A dry run's own set, `2640@<head> 2642@<head>` (the saved set stays)
|
||||
type: string
|
||||
default: ''
|
||||
base:
|
||||
description: The commit of main to build on (default main's newest with green checks and parity-main)
|
||||
type: string
|
||||
default: ''
|
||||
urgent:
|
||||
description: Past the day's cap of 12 builds (the train, for a release-now pull request or a forced run)
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
# One build at a time. A newer request replaces one still waiting: it builds the set as it is by then, so no pick
|
||||
# is lost.
|
||||
group: nightly-build
|
||||
cancel-in-progress: false
|
||||
jobs:
|
||||
pick:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: write # nightly/build-<date>-<n> and the nightly-state branch (main is protected)
|
||||
issues: write # says in the thread when the picked pull requests conflict
|
||||
pull-requests: write
|
||||
actions: read # main's newest green checks and parity-main runs (the base)
|
||||
outputs:
|
||||
build: ${{ steps.pick.outputs.build }}
|
||||
sha: ${{ steps.pick.outputs.sha }}
|
||||
short: ${{ steps.pick.outputs.short }}
|
||||
source: ${{ steps.pick.outputs.source }}
|
||||
date: ${{ steps.pick.outputs.date }}
|
||||
version: ${{ steps.pick.outputs.version }}
|
||||
nightly: ${{ steps.pick.outputs.nightly }}
|
||||
source_tag: ${{ steps.pick.outputs.source_tag }}
|
||||
dry_run: ${{ steps.mode.outputs.dry_run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- id: mode
|
||||
# A dry run never publishes; a hand-started run off main is always one.
|
||||
run: echo "dry_run=${{ github.event_name == 'workflow_dispatch' && (inputs.dry_run || github.ref != 'refs/heads/main') }}" >> "$GITHUB_OUTPUT"
|
||||
- id: pick
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
FORCE: ${{ (inputs.force || steps.mode.outputs.dry_run == 'true') && 'yes' || '' }}
|
||||
DRY_RUN: ${{ steps.mode.outputs.dry_run }}
|
||||
NIGHTLY_ISSUE: ${{ inputs.issue }}
|
||||
NIGHTLY_PRS: ${{ inputs.prs }}
|
||||
NIGHTLY_BASE: ${{ inputs.base }}
|
||||
NIGHTLY_URGENT: ${{ inputs.urgent }}
|
||||
run: |
|
||||
python3 tools/ci/nightly.py pick ${FORCE:+--force} | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
{ echo; cat nightly-notes.md; } >> "$GITHUB_STEP_SUMMARY"
|
||||
- name: Old nightly/build-* branches deleted (scheduled runs only)
|
||||
# Ludovic, 2026-10-27: older than 7 days, but never the newest build or one a published nightly points to;
|
||||
# nothing but nightly/build-* (nightly.py stale_builds, tests/test_nightly.py).
|
||||
if: github.event_name == 'schedule'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
{ echo "### nightly/build-* branches"; python3 tools/ci/nightly.py prune-builds --days 7; } | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
- name: The source of the build (horizon-source.tar.gz)
|
||||
if: steps.pick.outputs.build == 'true'
|
||||
env:
|
||||
SHA: ${{ steps.pick.outputs.sha }}
|
||||
run: git archive --format=tar.gz --prefix="horizon-${SHA:0:7}/" -o horizon-source.tar.gz "$SHA"
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: steps.pick.outputs.build == 'true'
|
||||
with:
|
||||
name: horizon-source
|
||||
path: horizon-source.tar.gz
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: nightly-notes
|
||||
path: nightly-notes.md
|
||||
retention-days: 3
|
||||
|
||||
build:
|
||||
needs: pick
|
||||
if: needs.pick.outputs.build == 'true'
|
||||
uses: ./.github/workflows/game-build.yml
|
||||
with:
|
||||
ref: ${{ needs.pick.outputs.sha }}
|
||||
version: ${{ needs.pick.outputs.version }}
|
||||
nightly: ${{ needs.pick.outputs.nightly }}
|
||||
developer_id: false
|
||||
trusted: false # it can hold unreviewed pull requests: their own cache key, never saved, not the release runner
|
||||
|
||||
sign:
|
||||
needs: [pick, build]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
# The key's only job: main's sign_release.sh hashes the archives and signs with the runner's OpenSSL.
|
||||
environment: ${{ needs.pick.outputs.dry_run != 'true' && 'release' || '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
sparse-checkout: tools/ci/sign_release.sh
|
||||
sparse-checkout-cone-mode: false
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: dist
|
||||
pattern: horizon-*
|
||||
merge-multiple: true
|
||||
- name: Sign the checksums for the nightly channel (SHA256SUMS.sig) and for this build (SHA256SUMS.v2.sig)
|
||||
# SHA256SUMS.sig is for launchers from before v2 (signed for "nightly"); SHA256SUMS.v2.sig is signed for
|
||||
# nightly-<date>-<commit>, the version the release title names, which current launchers and servers
|
||||
# require (docs/security.md, "Nightly signatures"). The publish step titles the release from the same values.
|
||||
env:
|
||||
RELEASE_SIGNING_KEY: ${{ secrets.RELEASE_SIGNING_KEY }}
|
||||
RELEASE_SIGNING_KEY_NEXT: ${{ secrets.RELEASE_SIGNING_KEY_NEXT }}
|
||||
EPHEMERAL: ${{ needs.pick.outputs.dry_run == 'true' && 'yes' || '' }}
|
||||
ALSO_FOR: nightly-${{ needs.pick.outputs.date }}-${{ needs.pick.outputs.short }}
|
||||
run: |
|
||||
# Windows ARM64's build may fail without holding the Nightly (game-build.yml): then it is left out.
|
||||
arm64=(); if [[ -f dist/horizon-windows-arm64.zip ]]; then arm64=(dist/horizon-windows-arm64.zip)
|
||||
else echo "::warning::horizon-windows-arm64.zip is missing: SHA256SUMS goes out without it"; fi
|
||||
musl=(); if [[ -f dist/horizon-linux-musl-x86_64.tar.gz ]]; then musl=(dist/horizon-linux-musl-x86_64.tar.gz)
|
||||
else echo "::warning::horizon-linux-musl-x86_64.tar.gz is missing: SHA256SUMS goes out without it"; fi
|
||||
bash tools/ci/sign_release.sh nightly dist/horizon-linux-x86_64.tar.gz dist/horizon-windows-x64.zip \
|
||||
${arm64[@]+"${arm64[@]}"} ${musl[@]+"${musl[@]}"} \
|
||||
dist/horizon-macos-arm64.zip dist/horizon-macos-x64.zip dist/horizon-server-linux-x86_64.tar.gz \
|
||||
dist/horizon-source.tar.gz
|
||||
- uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: signature
|
||||
path: dist/SHA256SUMS*
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/upload-artifact@v7
|
||||
if: needs.pick.outputs.dry_run == 'true'
|
||||
with:
|
||||
name: ephemeral.pub
|
||||
path: dist/ephemeral.pub
|
||||
retention-days: 3
|
||||
|
||||
publish:
|
||||
needs: [pick, build, sign]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: write
|
||||
issues: read # the open release-blocker issues (gate)
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v8
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
- name: The signatures, checked as launchers check them
|
||||
env:
|
||||
EPHEMERAL: ${{ needs.pick.outputs.dry_run == 'true' && 'yes' || '' }}
|
||||
DATE: ${{ needs.pick.outputs.date }}
|
||||
SHORT: ${{ needs.pick.outputs.short }}
|
||||
run: |
|
||||
key=(); [[ -n "$EPHEMERAL" ]] && key=(--key "$(cat dist/ephemeral.pub)")
|
||||
cargo run --locked --quiet -p horizon-release-sign -- verify --tag nightly --publishing "${key[@]}" dist
|
||||
# The version's own signature, which current launchers require: the title below names the same version.
|
||||
cargo run --locked --quiet -p horizon-release-sign -- verify --tag "nightly-${DATE}-${SHORT}" \
|
||||
--signature SHA256SUMS.v2.sig --publishing "${key[@]}" dist
|
||||
- name: Ready to publish (the smoke test drew a world, no release-blocker is open)
|
||||
# Right before publishing, as for a release: an issue labelled while the builds ran still holds it. A dry run
|
||||
# only reports what a real run would do (that is how a blocker's fix is tried).
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
DRY_RUN: ${{ needs.pick.outputs.dry_run }}
|
||||
run: |
|
||||
if ! python3 tools/release_train.py gate --kind game --smoke dist/smoke-test.json --blockers; then
|
||||
[[ "$DRY_RUN" == true ]] || { echo "::error::Nothing published"; exit 1; }
|
||||
echo "::warning::A real run would publish nothing"
|
||||
fi
|
||||
- name: Publish as the `nightly` pre-release
|
||||
if: needs.pick.outputs.dry_run != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
SHA: ${{ needs.pick.outputs.sha }}
|
||||
SHORT: ${{ needs.pick.outputs.short }}
|
||||
DATE: ${{ needs.pick.outputs.date }}
|
||||
SOURCE_TAG: ${{ needs.pick.outputs.source_tag }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
python3 tools/ci/nightly.py rotate
|
||||
signature=(); [[ -f dist/SHA256SUMS.sig ]] && signature=(dist/SHA256SUMS.sig)
|
||||
[[ -f dist/SHA256SUMS.v2.sig ]] && signature+=(dist/SHA256SUMS.v2.sig)
|
||||
# The title is what launchers parse (strictly) into the version SHA256SUMS.v2.sig is signed for.
|
||||
[[ "${SHA:0:7}" == "$SHORT" ]] || { echo "::error::the build's commit isn't the one signed"; exit 1; }
|
||||
# The ARM64 archive only when its build succeeded (the sign job left it out of SHA256SUMS otherwise).
|
||||
arm64=()
|
||||
if [[ -f dist/horizon-windows-arm64.zip ]]; then
|
||||
arm64=("dist/horizon-windows-arm64.zip#Game files the launcher installs (Nightly): Windows ARM64 (horizon-windows-arm64.zip)")
|
||||
else
|
||||
echo "::warning::horizon-windows-arm64.zip is missing: the Nightly goes out without it (ARM64 launchers install the x64 build)"
|
||||
fi
|
||||
musl=()
|
||||
if [[ -f dist/horizon-linux-musl-x86_64.tar.gz ]]; then
|
||||
musl=("dist/horizon-linux-musl-x86_64.tar.gz#Game files for musl Linux (horizon-linux-musl-x86_64.tar.gz)")
|
||||
else
|
||||
echo "::warning::horizon-linux-musl-x86_64.tar.gz is missing: the Nightly goes out without it"
|
||||
fi
|
||||
# A pre-release, never GitHub's latest: the latest stays the last vX.Y.Z, which launchers and servers from
|
||||
# before the Nightly-only switch keep (they don't read Nightlies).
|
||||
gh release create nightly --prerelease --latest=false --target "$SHA" \
|
||||
--title "Nightly $DATE · ${SHA:0:7}" --notes-file dist/nightly-notes.md \
|
||||
"dist/horizon-linux-x86_64.tar.gz#Game files the launcher installs (Nightly): Linux (horizon-linux-x86_64.tar.gz)" \
|
||||
${musl[@]+"${musl[@]}"} \
|
||||
"dist/horizon-windows-x64.zip#Game files the launcher installs (Nightly): Windows (horizon-windows-x64.zip)" \
|
||||
${arm64[@]+"${arm64[@]}"} \
|
||||
"dist/horizon-macos-arm64.zip#Game files the launcher installs (Nightly): macOS on Apple Silicon (horizon-macos-arm64.zip)" \
|
||||
"dist/horizon-macos-x64.zip#Game files the launcher installs (Nightly): macOS on Intel (horizon-macos-x64.zip)" \
|
||||
"dist/horizon-server-linux-x86_64.tar.gz#Nightly dedicated server for Linux (horizon-server-linux-x86_64.tar.gz)" \
|
||||
"dist/horizon-source.tar.gz#Source of this Nightly, commit ${SHA:0:7} (horizon-source.tar.gz; kept for good as the tag $SOURCE_TAG)" \
|
||||
dist/SHA256SUMS "${signature[@]}" dist/smoke-test.json
|
||||
python3 tools/ci/nightly.py keep-source "$SHA" "$DATE"
|
||||
python3 tools/ci/nightly.py prune --days 7
|
||||
- name: Dry run, the nightly that would be published
|
||||
if: needs.pick.outputs.dry_run == 'true'
|
||||
run: |
|
||||
echo "Would publish nightly at ${{ needs.pick.outputs.sha }} (${{ needs.pick.outputs.source }})"
|
||||
ls -l dist
|
||||
|
||||
answer:
|
||||
# Tells the thread that asked for this build how it ended. A conflict `pick` already explained there.
|
||||
needs: [pick, build, sign, publish]
|
||||
if: always() && inputs.issue != '' && needs.pick.result == 'success'
|
||||
# One comment, no checkout and no secret: one of our small runners (label horizon-light, docs/ci-runners.md).
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
ISSUE: ${{ inputs.issue }}
|
||||
BUILD: ${{ needs.pick.outputs.build }}
|
||||
PUBLISHED: ${{ needs.publish.result }}
|
||||
DRY_RUN: ${{ needs.pick.outputs.dry_run }}
|
||||
NAME: Nightly ${{ needs.pick.outputs.date }} · ${{ needs.pick.outputs.short }}
|
||||
RUN: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
run: |
|
||||
if [[ "$BUILD" != true ]]; then
|
||||
text="nothing new: the published Nightly is already this build."
|
||||
elif [[ "$PUBLISHED" == success && "$DRY_RUN" == true ]]; then
|
||||
text="the dry run built and signed $NAME; nothing was published. $RUN"
|
||||
elif [[ "$PUBLISHED" == success ]]; then
|
||||
text="published $NAME: https://github.com/$GITHUB_REPOSITORY/releases/tag/nightly. Launchers install it at their next check."
|
||||
else
|
||||
text="the build failed, nothing was published: $RUN"
|
||||
fi
|
||||
gh api "repos/$GITHUB_REPOSITORY/issues/$ISSUE/comments" -f body="🤖 Nightly: $text"
|
||||
@@ -1,48 +0,0 @@
|
||||
name: nightly command
|
||||
# `/nightly …` comments: the trusted reviewers in .github/trusted-reviewers.txt (and Ludovic) pick the pull requests
|
||||
# the Nightly holds (docs/release-flow.md "Nightly channel", tools/ci/nightly_set.py). This job only checks who asked,
|
||||
# saves the set on the nightly-state branch, starts `nightly build` and answers in the thread.
|
||||
#
|
||||
# Why no pull request's code runs here, though the token can write:
|
||||
# - `issue_comment` always runs this file from main, whoever comments and wherever; a pull request's own copy of it
|
||||
# is never read.
|
||||
# - It checks out main and runs main's nightly_set.py. The comment's text and author reach it as env vars, never in
|
||||
# a shell line.
|
||||
# - It never checks out, fetches or merges a pull request: it reads their file lists through the API. The merge
|
||||
# happens in nightly-build.yml's `pick`, with git objects only; their code runs in its `build`, without secrets.
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
command:
|
||||
# Every other comment skips here, before a runner starts.
|
||||
if: startsWith(github.event.comment.body, '/nightly') && github.event.comment.user.type != 'Bot'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: write # the nightly-state branch (main is protected)
|
||||
actions: write # starts `nightly build`
|
||||
issues: write # answers in the thread
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
.github/CODEOWNERS
|
||||
.github/trusted-reviewers.txt
|
||||
tools/ci/nightly_set.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Run the command
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BODY: ${{ github.event.comment.body }}
|
||||
AUTHOR: ${{ github.event.comment.user.login }}
|
||||
# Who may act is decided by this numeric ID: a login can be claimed by someone else after a rename.
|
||||
AUTHOR_ID: ${{ github.event.comment.user.id }}
|
||||
ISSUE: ${{ github.event.issue.number }}
|
||||
COMMENT_URL: ${{ github.event.comment.html_url }}
|
||||
run: python3 tools/ci/nightly_set.py command
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
else
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
if: steps.when.outputs.run == 'true'
|
||||
with:
|
||||
fetch-depth: 0
|
||||
@@ -82,7 +82,7 @@ jobs:
|
||||
run: python3 tools/ci/parity_issues.py --since "${{ steps.audit.outputs.since }}" ${{ inputs.dry_run && '--dry-run' || '' }} | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
- name: Logs of the failed harnesses
|
||||
if: steps.when.outputs.run == 'true' && steps.audit.outputs.exit != '0'
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: nightly-parity-logs
|
||||
path: .local/parity-runner/logs/
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
name: overlap note
|
||||
# One comment on a pull request naming the other open pull requests that close the same issue or change the same
|
||||
# functions, edited on every push (tools/ci/overlap_note.py, issue #3859).
|
||||
#
|
||||
# Why no pull request's code runs here, though `pull_request_target` gives a token that can write:
|
||||
# - `pull_request_target` runs this file and the script from main, never the pull request's copy.
|
||||
# - The checkout is main's (`ref: main`), blobless, with the script alone on disk. The pull requests' heads are fetched
|
||||
# as git objects and only diffed, never checked out; git runs with hooks, fsmonitor, external diff and textconv off.
|
||||
# - The rest comes from the API. The token writes the comment only.
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, ready_for_review]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
note:
|
||||
if: github.event.pull_request.base.ref == 'main'
|
||||
# A newer push replaces the note being computed.
|
||||
concurrency:
|
||||
group: overlap-note-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
# One of our small runners (horizon-light), out of GitHub's pool: it runs main's script only (above), so a fork's
|
||||
# pull request runs none of its code there (docs/ci-runners.md). SELF_HOSTED_CI=off: GitHub's runners.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 10
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
fetch-depth: 0
|
||||
filter: blob:none
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
tools/ci/overlap_note.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Note
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: python3 tools/ci/overlap_note.py event
|
||||
@@ -1,72 +0,0 @@
|
||||
name: pack load bench
|
||||
# How long resource packs take to load: crates/horizon-client-render/examples/pack_load_bench.rs on generated packs
|
||||
# (no game files), on the branch and then on `base` with the branch's copy of the bench, on the same runner, so a pull
|
||||
# request can show its numbers next to main's. Started by hand, or by a push to a `pack-bench/*` branch (a fork can't
|
||||
# start a workflow its main lacks), against horizon-rust/horizon's main.
|
||||
on:
|
||||
push:
|
||||
branches: ['pack-bench/**']
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
base:
|
||||
description: Ref to compare against
|
||||
default: main
|
||||
scale:
|
||||
description: How many times the default pack sizes
|
||||
default: '1'
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
HORIZON_TELEMETRY_URL: "off"
|
||||
CARGO_TERM_COLOR: never
|
||||
|
||||
jobs:
|
||||
bench:
|
||||
# Our checks runners (label horizon-checks, docs/ci-runners.md): the branch and the base on the same machine, as
|
||||
# the comparison needs. SELF_HOSTED_CI=light or off: GitHub's.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && vars.SELF_HOSTED_CI != 'light' && fromJSON('["self-hosted", "linux", "horizon-checks"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 90
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Install Rust and the ALSA and udev headers
|
||||
env:
|
||||
HOSTED: ${{ runner.environment == 'github-hosted' }}
|
||||
run: |
|
||||
if [ "$HOSTED" = true ]; then
|
||||
sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
|
||||
fi
|
||||
rustup toolchain install stable --profile minimal
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted'
|
||||
with:
|
||||
shared-key: pack-bench
|
||||
- name: Bench the branch
|
||||
env:
|
||||
SCALE: ${{ inputs.scale || '1' }}
|
||||
run: |
|
||||
cargo run --profile fast -p horizon-client-render --example pack_load_bench -- --scale "$SCALE" > head.md
|
||||
- name: Bench the base, with the branch's bench
|
||||
env:
|
||||
BASE: ${{ inputs.base || 'main' }}
|
||||
SCALE: ${{ inputs.scale || '1' }}
|
||||
run: |
|
||||
git fetch https://github.com/horizon-rust/horizon.git "$BASE"
|
||||
# Our runners keep the folder beside the checkout between jobs.
|
||||
git worktree remove --force ../base 2> /dev/null || rm -rf ../base
|
||||
git worktree prune
|
||||
git worktree add ../base FETCH_HEAD
|
||||
cp crates/horizon-client-render/examples/pack_load_bench.rs ../base/crates/horizon-client-render/examples/
|
||||
# A bench row that times a function the base lacks keeps it from building there: then
|
||||
# the branch's own rows compare the two ways.
|
||||
target=${CARGO_TARGET_DIR:-$GITHUB_WORKSPACE/target}
|
||||
(cd ../base && CARGO_TARGET_DIR="$target" cargo run --profile fast -p horizon-client-render \
|
||||
--example pack_load_bench -- --scale "$SCALE") > base.md \
|
||||
|| echo "The bench does not build on the base." > base.md
|
||||
- name: Summary
|
||||
run: |
|
||||
{
|
||||
echo "### Branch ($(git rev-parse --short HEAD))"; cat head.md
|
||||
echo; echo "### Base (${{ inputs.base || 'main' }})"; cat base.md
|
||||
} | tee -a "$GITHUB_STEP_SUMMARY"
|
||||
@@ -30,7 +30,7 @@ jobs:
|
||||
runs-on: [self-hosted, macOS, horizon-parity-main]
|
||||
timeout-minutes: 240 # a core-crate batch reruns ~300 harnesses (~60-90 min), a bisect a few rounds of the failures
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
fetch-depth: 0
|
||||
@@ -69,7 +69,7 @@ jobs:
|
||||
python3 tools/parity_main.py bisect "$BASE_SHA" --comment
|
||||
- name: Logs of the failed harnesses
|
||||
if: steps.harnesses.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: parity-main-logs
|
||||
path: .local/parity-main-logs/
|
||||
|
||||
@@ -20,12 +20,6 @@ on:
|
||||
busy the job waits for it.
|
||||
type: boolean
|
||||
default: false
|
||||
frame_identity:
|
||||
description: >-
|
||||
The pull request carries the frame-identity label: it must leave the picture alone (HDR, shader packs), so
|
||||
the frame_identity harness, which no automatic selection picks, runs too.
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
contents: read
|
||||
env:
|
||||
@@ -39,7 +33,7 @@ jobs:
|
||||
# harnesses at a time) up to a few hours, and any pull request's job may land there.
|
||||
timeout-minutes: ${{ inputs.full && 360 || 180 }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# The commit the event names: a fork's later pushes need another run-parity label. The next step merges
|
||||
# main into it.
|
||||
@@ -93,15 +87,9 @@ jobs:
|
||||
PARITY_HOSTS: ''
|
||||
BASE_SHA: ${{ steps.merge.outputs.base }}
|
||||
run: python3 tools/parity.py --changed "$BASE_SHA" --timeout 2400 # world_spawn takes ~1480 s on a busy runner
|
||||
- name: The pictures this change must leave alone
|
||||
if: ${{ !cancelled() && inputs.frame_identity }}
|
||||
env:
|
||||
PARITY_HOSTS: ''
|
||||
BASE_SHA: ${{ steps.merge.outputs.base }}
|
||||
run: python3 tools/parity.py frame_identity --timeout 2400
|
||||
- name: Logs of the failed harnesses
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v7
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: parity-logs
|
||||
path: .local/parity-runner/logs/
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
name: pr labels
|
||||
# A pull request's kind label (the box ticked in the template) and area labels (the paths it changes):
|
||||
# tools/ci/pr_labels.py, CONTRIBUTING.md "Pull requests".
|
||||
#
|
||||
# Why no pull request's code runs here, though `pull_request_target` gives a token that can write to fork PRs:
|
||||
# - `pull_request_target` runs this file and the script from main, never the pull request's copy.
|
||||
# - It checks out main's script only (`ref: main`), never the pull request's head or merge commit.
|
||||
# - The script reads the event file (the description is data in JSON, never in a shell line) and the API's list of
|
||||
# changed file names; it runs, builds and imports nothing of theirs. The token writes labels only.
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, reopened, synchronize, edited, ready_for_review]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
label:
|
||||
# Title-only edits change nothing: skip them before a runner starts.
|
||||
if: github.event.action != 'edited' || github.event.changes.body != null
|
||||
# One of our small runners (horizon-light), out of GitHub's pool: it runs main's script only (above), so a fork's
|
||||
# pull request runs none of its code there (docs/ci-runners.md). SELF_HOSTED_CI=off: GitHub's runners.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
tools/ci/pr_labels.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Label
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
REPO: ${{ github.repository }}
|
||||
run: python3 tools/ci/pr_labels.py event
|
||||
@@ -1,15 +1,22 @@
|
||||
name: release
|
||||
# Automatic game releases (docs/release-flow.md). Horizon ships only the Nightly since 2026-10-28 (Ludovic): this
|
||||
# workflow is the batch train that decides when a new Nightly goes out, and `nightly build` (nightly-build.yml) builds,
|
||||
# signs and publishes it. After every green `checks` run on main, every 10 minutes (so a batch waiting for merges to
|
||||
# settle goes out without another merge) and by hand, tools/release_train.py decides, for a commit whose checks and
|
||||
# parity-main (the vanilla harnesses on main) both passed: a Nightly when 5 pull requests merged since the published
|
||||
# Nightly changed what players run and the newest merged 5 minutes ago, or when the oldest has waited 6 hours, or at
|
||||
# once for a pull request labelled release-now. RELEASES_PAUSED=1 (repository variable) stops it; so does an open issue
|
||||
# labelled release-blocker, forced runs too (nightly-build.yml checks again before publishing). One Nightly build at a
|
||||
# time, at most 12 a day (release-now and force=true pass the cap). No `vX.Y.Z` game release is made any more.
|
||||
# gh workflow run release --ref <branch> # dry run: decides, starts nothing
|
||||
# gh workflow run release -f dry_run=false -f force=true # on main: a Nightly now, whatever the rules say
|
||||
# Automatic game releases (docs/release-flow.md). After every green `checks` run on main, every 10 minutes (so a
|
||||
# release waiting for merges to settle goes out without another merge) and by hand, tools/release_train.py decides,
|
||||
# for a commit whose checks and parity-main (the vanilla harnesses on main) both passed:
|
||||
# a release when 5 pull requests merged since the last one changed what players run and the newest merged 5 minutes
|
||||
# ago, or when the oldest has waited 6 hours, or at once for a pull request labelled release-now.
|
||||
# RELEASES_PAUSED=1 (repository variable) stops them; so does an open issue labelled release-blocker, forced runs too.
|
||||
# Builds Linux (an older Ubuntu, so the binary runs on any recent distribution and on NixOS through nix-ld) and
|
||||
# Windows on GitHub, macOS on the Mac mini's runner (MAC_RUNNER=macos-latest sends it to GitHub), then
|
||||
# publishes vX.Y.Z on the release line in .github/release-line.txt (docs/versioning.md; without it, the dated
|
||||
# vYYYY.MM.DD[.N] from before 0.2) with notes from the merged pull requests, as the release and GitHub's latest: one
|
||||
# channel, which launchers, `horizon-server update` and install.sh follow at once. So it is published only after the
|
||||
# checks that used to gate a promotion pass in this run: the Mac mini's smoke test drew a world, and no release-blocker
|
||||
# is open (tools/release_train.py gate); otherwise nothing is published. macOS: with the repository variable
|
||||
# MACOS_SIGN_IDENTITY set, the programs are signed with
|
||||
# Developer ID and the hardened runtime and the zip is notarized, from the runner's signing keychain
|
||||
# (packaging/macos/README.md); unset (forks), ad hoc.
|
||||
# gh workflow run release --ref <branch> # dry run: builds and notes, publishes nothing
|
||||
# gh workflow run release -f dry_run=false -f force=true # on main: release now, whatever the rules say
|
||||
on:
|
||||
workflow_run:
|
||||
# A game release ships a commit both passed on (parity-main runs on batches: the newest commit it passed on).
|
||||
@@ -21,24 +28,19 @@ on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
dry_run:
|
||||
description: Decide only; start no Nightly build
|
||||
description: Build everything and write the notes, but publish nothing
|
||||
type: boolean
|
||||
default: true
|
||||
force:
|
||||
description: A Nightly even without player-facing changes, before merges settle, while paused or past the day's cap
|
||||
description: Release even without player-facing changes, before merges settle or while paused
|
||||
type: boolean
|
||||
default: false
|
||||
permissions:
|
||||
contents: read
|
||||
# The open release-blocker issues (decide).
|
||||
issues: read
|
||||
# The checks, parity-main and nightly build runs (decide).
|
||||
actions: read
|
||||
concurrency:
|
||||
# One release at a time. A hand-started dry run publishes nothing, so it can't race a real release: it gets a
|
||||
# group of its own. In the shared group, a release queued behind it replaced it as the pending run and GitHub
|
||||
# cancelled it (#2779's dry run, 2026-10-27), which happens all day while releases go out in batches.
|
||||
group: game-release${{ github.event_name == 'workflow_dispatch' && inputs.dry_run && '-dry-run' || '' }}
|
||||
group: game-release
|
||||
cancel-in-progress: false
|
||||
jobs:
|
||||
decide:
|
||||
@@ -49,11 +51,12 @@ jobs:
|
||||
timeout-minutes: 10
|
||||
outputs:
|
||||
release: ${{ steps.decide.outputs.release }}
|
||||
tag: ${{ steps.decide.outputs.tag }}
|
||||
version: ${{ steps.decide.outputs.version }}
|
||||
head: ${{ steps.decide.outputs.head }}
|
||||
urgent: ${{ steps.decide.outputs.urgent }}
|
||||
dry_run: ${{ steps.mode.outputs.dry_run }}
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- id: mode
|
||||
@@ -70,21 +73,364 @@ jobs:
|
||||
run: |
|
||||
python3 tools/release_train.py decide --kind game ${HEAD_SHA:+--head "$HEAD_SHA"} ${FORCE:+--force} | tee decision.json
|
||||
echo "### $(jq -r '.reason' decision.json)" >> "$GITHUB_STEP_SUMMARY"
|
||||
# The version the programs are built with (docs/versioning.md): the tag without its v.
|
||||
tag=$(jq -r '.tag' decision.json)
|
||||
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
|
||||
# A dry run builds whatever the decision, to test the builds.
|
||||
if [[ "${{ steps.mode.outputs.dry_run }}" == true ]]; then echo "release=true" >> "$GITHUB_OUTPUT"; fi
|
||||
|
||||
nightly:
|
||||
# The Nightly is the release: nightly-build.yml builds the decided commit plus the reviewers' picks, signs it for
|
||||
# the Nightly channel and publishes it once its smoke test passed and no release-blocker is open.
|
||||
exporters:
|
||||
needs: decide
|
||||
if: needs.decide.outputs.release == 'true' && needs.decide.outputs.dry_run != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
actions: write # starts `nightly build`
|
||||
if: needs.decide.outputs.release == 'true'
|
||||
# This runner holds the maintainer's own pinned Minecraft jars. Only our classes leave it.
|
||||
runs-on: ${{ vars.MAC_RUNNER || 'ludovics-mac-mini' }}
|
||||
# Three full preparations (two isolated, one batched) besides the compile.
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
HEAD_SHA: ${{ needs.decide.outputs.head }}
|
||||
URGENT: ${{ needs.decide.outputs.urgent }}
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide.outputs.head }}
|
||||
persist-credentials: false
|
||||
clean: true
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- run: bash tools/ci/runner-env.sh
|
||||
- run: bash tools/ci/vanilla-data.sh
|
||||
- name: Compile and validate original exporters against the pinned jars
|
||||
shell: bash
|
||||
run: |
|
||||
gh workflow run nightly-build.yml --repo "$GITHUB_REPOSITORY" --ref main -f base="$HEAD_SHA" -f urgent="$URGENT"
|
||||
echo "### Started \`nightly build\` on ${HEAD_SHA:0:9}" >> "$GITHUB_STEP_SUMMARY"
|
||||
set -euo pipefail
|
||||
# target/ is gone after the clean checkout, and vanilla-data.sh builds the preparer only when it
|
||||
# prepares afresh.
|
||||
cargo build --release --locked -p horizon-prepare
|
||||
# Compiled here, never taken from the runner's shared preparations: pull requests' parity jobs
|
||||
# write those (vanilla-data.sh links .local/exporters to them).
|
||||
rm -rf .local/exporters
|
||||
bundle=$(target/release/horizon-prepare compile-exporters --root "$PWD" | tail -1)
|
||||
mkdir -p exporters
|
||||
cp -R "$bundle/server" "$bundle/client" "$bundle/manifest.json" exporters/
|
||||
# Only our classes and their manifest leave this runner.
|
||||
stray=$(find exporters -type f ! -path exporters/manifest.json \
|
||||
! \( -name '*.class' \( -path 'exporters/server/dev/horizonlab/parity/*' -o -path 'exporters/client/dev/horizonlab/parity/*' \) \))
|
||||
[ -z "$stray" ] || { echo "::error::not one of our classes: $stray"; exit 1; }
|
||||
python3 tools/check_prepare_exporters.py --binary target/release/horizon-prepare
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: original-exporters
|
||||
path: exporters/
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
|
||||
build:
|
||||
needs: [decide, exporters]
|
||||
if: needs.decide.outputs.release == 'true'
|
||||
name: build ${{ matrix.name }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: linux
|
||||
os: ubuntu-22.04
|
||||
dir: horizon-linux-x86_64
|
||||
asset: horizon-linux-x86_64.tar.gz
|
||||
# The server build too: packaging/server/install.sh installs it on Linux.
|
||||
server_dir: horizon-server-linux-x86_64
|
||||
server_asset: horizon-server-linux-x86_64.tar.gz
|
||||
- name: windows
|
||||
os: windows-latest
|
||||
dir: horizon-windows-x64
|
||||
asset: horizon-windows-x64.zip
|
||||
exe: .exe
|
||||
# The C runtime linked in, so the game runs without the Visual C++ redistributable.
|
||||
rustflags: -C target-feature=+crt-static
|
||||
- name: macos
|
||||
mac: true
|
||||
dir: horizon-macos-arm64
|
||||
asset: horizon-macos-arm64.zip
|
||||
runs-on: ${{ matrix.mac && (vars.MAC_RUNNER || 'ludovics-mac-mini') || matrix.os }}
|
||||
# Notarizing the zip can take a few minutes.
|
||||
timeout-minutes: ${{ matrix.mac && 60 || 40 }}
|
||||
env:
|
||||
RUSTFLAGS: ${{ matrix.rustflags }}
|
||||
# The release's version, built in (horizon_core::release): --version, user agents, crash reports and
|
||||
# telemetry say it. No version-bump commits.
|
||||
HORIZON_VERSION: ${{ needs.decide.outputs.version }}
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.decide.outputs.head }}
|
||||
persist-credentials: false
|
||||
# Always from a clean checkout, the Mac mini's runner too: its work folder is shared with pull requests'
|
||||
# parity jobs, and nothing they leave (target/, an untracked .cargo/config.toml, a build script's output)
|
||||
# may end up in a release. target/ is rebuilt from scratch; .local/ is relinked by vanilla-data.sh, which
|
||||
# keeps its preparations outside the checkout.
|
||||
clean: true
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted'
|
||||
with:
|
||||
shared-key: release-${{ matrix.name }}
|
||||
- name: ALSA and udev headers
|
||||
if: runner.os == 'Linux'
|
||||
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends libasound2-dev libudev-dev
|
||||
- name: Build the client, horizon-ctl, horizon-prepare and horizon-server
|
||||
# `horizon-client/mods`: every released game runs code mods (the feature is off in dev builds).
|
||||
run: cargo build --release --locked --features horizon-client/mods -p horizon-client --bin horizon-client --bin horizon-ctl -p horizon-prepare --bin horizon-prepare -p horizon-server --bin horizon-server
|
||||
- name: Every program the release folder takes was built
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
test -f "target/release/$binary${{ matrix.exe }}" || { echo "::error::target/release/$binary${{ matrix.exe }} is missing"; exit 1; }
|
||||
done
|
||||
- name: The signing keychain, unlocked
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != ''
|
||||
env:
|
||||
MACOS_SIGN_IDENTITY: ${{ vars.MACOS_SIGN_IDENTITY }}
|
||||
run: packaging/macos/keychain.sh unlock
|
||||
- name: Signed with Developer ID and the hardened runtime
|
||||
# Before the checks below, so they run the programs as players will.
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != ''
|
||||
env:
|
||||
MACOS_SIGN_IDENTITY: ${{ vars.MACOS_SIGN_IDENTITY }}
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
codesign --force --options runtime --timestamp --keychain "$MACOS_SIGN_KEYCHAIN" \
|
||||
--identifier "dev.horizon.${binary#horizon-}" --sign "$MACOS_SIGN_IDENTITY" "target/release/$binary"
|
||||
codesign --verify --strict --verbose=2 "target/release/$binary"
|
||||
done
|
||||
- name: Only system libraries
|
||||
# Windows: no non-system DLL (a "DLL not found" dialog on some players' machines). Linux: the standard
|
||||
# loader and libraries every desktop distribution has. macOS: only the system's own libraries.
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
file="target/release/$binary${{ matrix.exe }}"
|
||||
if [[ "$RUNNER_OS" == macOS ]]; then
|
||||
others=$(otool -L "$file" | tail -n +2 | awk '{print $1}' | grep -v -E '^(/usr/lib/|/System/Library/)' || true)
|
||||
[[ -z "$others" ]] || { echo "::error::$binary links $others"; exit 1; }
|
||||
else
|
||||
${{ runner.os == 'Windows' && 'python' || 'python3' }} tools/check_imports.py "$file"
|
||||
fi
|
||||
done
|
||||
- name: Every program starts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
bin=target/release
|
||||
"$bin/horizon-client${{ matrix.exe }}" --help | grep -q -- '--resources'
|
||||
"$bin/horizon-ctl${{ matrix.exe }}" --help > /dev/null
|
||||
"$bin/horizon-prepare${{ matrix.exe }}" --help | grep -q -- '--minecraft-dir'
|
||||
# The version is the release's.
|
||||
for binary in horizon-prepare horizon-server; do
|
||||
out=$("$bin/$binary${{ matrix.exe }}" --version | tr -d '\r')
|
||||
echo "$out"
|
||||
[[ "$out" == "$binary $HORIZON_VERSION" ]] || { echo "::error::expected $binary $HORIZON_VERSION"; exit 1; }
|
||||
done
|
||||
- name: Tools from the runner
|
||||
if: runner.environment == 'self-hosted'
|
||||
run: bash tools/ci/runner-env.sh
|
||||
- name: Resources prepared from the runner's own Minecraft
|
||||
if: runner.environment == 'self-hosted'
|
||||
run: bash tools/ci/vanilla-data.sh
|
||||
- name: The game runs (offscreen, a new world, 1500 frames)
|
||||
if: runner.environment == 'self-hosted'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# From a scratch folder: the game keeps its saves and options in the folder it starts in.
|
||||
home="$RUNNER_TEMP/horizon-smoke"
|
||||
rm -rf "$home" && mkdir -p "$home"
|
||||
version=$(sed -n 's/.*"version": *"\([^"]*\)".*/\1/p' research-lock.json | head -1)
|
||||
client="$PWD/target/release/horizon-client"
|
||||
resources="$PWD/.local/horizon-client/$version"
|
||||
(cd "$home" && HORIZON_HOME="$home" HORIZON_NO_AUDIO=1 "$client" --resources "$resources" --offscreen \
|
||||
--world smoke --seed 1 --render-distance 4 --world-frames 1500 --timeout-seconds 180 \
|
||||
--smoke-report "$home/smoke.json" > "$home/client.log" 2>&1) || { tail -40 "$home/client.log"; exit 1; }
|
||||
python3 - "$home/smoke.json" <<'EOF'
|
||||
import json, sys
|
||||
report = json.load(open(sys.argv[1]))
|
||||
print(json.dumps(report))
|
||||
if report.get("error") is not None or report.get("frames", 0) < 1500 or not report.get("chunks") \
|
||||
or not report.get("meshed_sections") or not report.get("player"):
|
||||
sys.exit("the smoke run did not draw a world")
|
||||
EOF
|
||||
# Published with the release; the publish job checks it again before it publishes anything.
|
||||
cp "$home/smoke.json" "$RUNNER_TEMP/smoke-test.json"
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: runner.environment == 'self-hosted'
|
||||
with:
|
||||
name: smoke-test.json
|
||||
path: ${{ runner.temp }}/smoke-test.json
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: original-exporters
|
||||
path: exporters
|
||||
- name: Package
|
||||
run: |
|
||||
set -euo pipefail
|
||||
cargo run --locked -p xtask -- package "target/release/horizon-client${{ matrix.exe }}" "dist/${{ matrix.dir }}"
|
||||
cd dist
|
||||
rm -f "${{ matrix.asset }}"
|
||||
case "${{ matrix.asset }}" in
|
||||
*.tar.gz) tar czf "${{ matrix.asset }}" "${{ matrix.dir }}" ;;
|
||||
*) if [[ "$RUNNER_OS" == Windows ]]; then 7z a -tzip "${{ matrix.asset }}" "${{ matrix.dir }}" > /dev/null
|
||||
else
|
||||
# Without resource forks and extended attributes: plain ditto adds an
|
||||
# AppleDouble `._` file beside every file that has any.
|
||||
ditto -c -k --norsrc --noextattr --noqtn --keepParent "${{ matrix.dir }}" "${{ matrix.asset }}"
|
||||
if unzip -Z1 "${{ matrix.asset }}" | grep -E '(^|/)(\._|__MACOSX/)'; then
|
||||
echo "::error::macOS metadata files in ${{ matrix.asset }}"; exit 1
|
||||
fi
|
||||
fi ;;
|
||||
esac
|
||||
ls -l "${{ matrix.asset }}"
|
||||
- name: Notarized
|
||||
# A zip of programs can't be stapled: Gatekeeper asks Apple the first time each one runs.
|
||||
if: runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != ''
|
||||
run: |
|
||||
for binary in horizon-client horizon-ctl horizon-prepare horizon-server; do
|
||||
codesign --verify --strict "dist/${{ matrix.dir }}/$binary"
|
||||
done
|
||||
packaging/macos/notarize.sh "dist/${{ matrix.asset }}"
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.asset }}
|
||||
path: dist/${{ matrix.asset }}
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- name: The server build (the game without sound or controllers, as horizon-engine)
|
||||
if: matrix.server_asset
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# After the client is packaged: target/release/horizon-client is rebuilt without the audio and
|
||||
# controllers features, so it needs neither libasound nor libudev (minimal server images lack them),
|
||||
# and with code mods like the client.
|
||||
cargo build --release --locked -p horizon-client --no-default-features --features mods --bin horizon-client
|
||||
cargo run --locked -p xtask -- package-server target/release/horizon-client "dist/${{ matrix.server_dir }}"
|
||||
folder="dist/${{ matrix.server_dir }}"
|
||||
python3 tools/check_imports.py --server "$folder/horizon-engine" "$folder/horizon-server" "$folder/horizon-prepare"
|
||||
"$folder/horizon-engine" --help | grep -q -- '--resources'
|
||||
[[ "$("$folder/horizon-server" --version)" == "horizon-server $HORIZON_VERSION" ]]
|
||||
cd dist
|
||||
rm -f "${{ matrix.server_asset }}"
|
||||
tar czf "${{ matrix.server_asset }}" "${{ matrix.server_dir }}"
|
||||
ls -l "${{ matrix.server_asset }}"
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: matrix.server_asset
|
||||
with:
|
||||
name: ${{ matrix.server_asset }}
|
||||
path: dist/${{ matrix.server_asset }}
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- name: The signing keychain, locked again
|
||||
if: always() && runner.os == 'macOS' && vars.MACOS_SIGN_IDENTITY != ''
|
||||
run: packaging/macos/keychain.sh lock
|
||||
|
||||
sign:
|
||||
needs: [decide, build]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
# The only job that holds the release signing key, a secret of the `release` environment, which only main's real
|
||||
# releases enter (dry runs sign with a throwaway key). It runs no code from the repository but
|
||||
# tools/ci/sign_release.sh, which calls only the runner's sha256sum and OpenSSL (docs/release-flow.md).
|
||||
environment: ${{ needs.decide.outputs.dry_run != 'true' && 'release' || '' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
sparse-checkout: tools/ci/sign_release.sh
|
||||
sparse-checkout-cone-mode: false
|
||||
persist-credentials: false
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
pattern: horizon-*
|
||||
merge-multiple: true
|
||||
- name: Sign the checksums (SHA256SUMS, SHA256SUMS.sig)
|
||||
env:
|
||||
RELEASE_SIGNING_KEY: ${{ secrets.RELEASE_SIGNING_KEY }}
|
||||
RELEASE_SIGNING_KEY_NEXT: ${{ secrets.RELEASE_SIGNING_KEY_NEXT }}
|
||||
EPHEMERAL: ${{ needs.decide.outputs.dry_run == 'true' && 'yes' || '' }}
|
||||
TAG: ${{ needs.decide.outputs.tag }}
|
||||
run: |
|
||||
bash tools/ci/sign_release.sh "$TAG" dist/horizon-linux-x86_64.tar.gz dist/horizon-windows-x64.zip \
|
||||
dist/horizon-macos-arm64.zip dist/horizon-server-linux-x86_64.tar.gz
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: signature
|
||||
path: dist/SHA256SUMS*
|
||||
if-no-files-found: error
|
||||
retention-days: 3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: needs.decide.outputs.dry_run == 'true'
|
||||
with:
|
||||
name: ephemeral.pub
|
||||
path: dist/ephemeral.pub
|
||||
retention-days: 3
|
||||
|
||||
publish:
|
||||
needs: [decide, build, sign]
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: write
|
||||
issues: read
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Notes
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
python3 tools/release_train.py notes --kind game --tag "${{ needs.decide.outputs.tag }}" \
|
||||
--head "${{ needs.decide.outputs.head }}" --out notes > /dev/null
|
||||
{ echo "## $(cat notes/title.txt)"; echo; cat notes/body.md; } >> "$GITHUB_STEP_SUMMARY"
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: dist
|
||||
merge-multiple: true
|
||||
- name: The signature, checked as launchers check it
|
||||
env:
|
||||
TAG: ${{ needs.decide.outputs.tag }}
|
||||
EPHEMERAL: ${{ needs.decide.outputs.dry_run == 'true' && 'yes' || '' }}
|
||||
run: |
|
||||
key=(); [[ -n "$EPHEMERAL" ]] && key=(--key "$(cat dist/ephemeral.pub)")
|
||||
cargo run --locked --quiet -p horizon-release-sign -- verify --tag "$TAG" --publishing "${key[@]}" dist
|
||||
- name: Ready to publish (the smoke test passed, no release-blocker is open)
|
||||
# Right before publishing: an issue labelled while the builds ran still holds this release. A dry run only
|
||||
# reports what a real run would do.
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
DRY_RUN: ${{ needs.decide.outputs.dry_run }}
|
||||
run: |
|
||||
if ! python3 tools/release_train.py gate --kind game --smoke dist/smoke-test.json --blockers; then
|
||||
[[ "$DRY_RUN" == true ]] || { echo "::error::Nothing published"; exit 1; }
|
||||
echo "::warning::A real run would publish nothing"
|
||||
fi
|
||||
- name: Publish ${{ needs.decide.outputs.tag }}
|
||||
if: needs.decide.outputs.dry_run != 'true'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
TAG: ${{ needs.decide.outputs.tag }}
|
||||
run: |
|
||||
signature=(); [[ -f dist/SHA256SUMS.sig ]] && signature=(dist/SHA256SUMS.sig)
|
||||
# The release and the latest at once: there is one channel (docs/release-flow.md). Each archive gets a
|
||||
# label (file#label), which GitHub's page shows instead of the file name, so nobody takes the game's
|
||||
# files for the download (#1647). Launchers, servers and install.sh match the name, which stays.
|
||||
gh release create "$TAG" --target "${{ needs.decide.outputs.head }}" --title "$(cat notes/title.txt)" \
|
||||
--notes-file notes/body.md --latest \
|
||||
"dist/horizon-linux-x86_64.tar.gz#Game files the launcher installs: Linux (horizon-linux-x86_64.tar.gz)" \
|
||||
"dist/horizon-windows-x64.zip#Game files the launcher installs: Windows (horizon-windows-x64.zip)" \
|
||||
"dist/horizon-macos-arm64.zip#Game files the launcher installs: macOS (horizon-macos-arm64.zip)" \
|
||||
"dist/horizon-server-linux-x86_64.tar.gz#Dedicated server for Linux (horizon-server-linux-x86_64.tar.gz)" \
|
||||
dist/SHA256SUMS "${signature[@]}" dist/smoke-test.json
|
||||
- name: Dry run, the release that would be published
|
||||
if: needs.decide.outputs.dry_run == 'true'
|
||||
run: |
|
||||
echo "Would publish ${{ needs.decide.outputs.tag }} at ${{ needs.decide.outputs.head }} as the release and latest: $(cat notes/title.txt)"
|
||||
ls -l dist
|
||||
- uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: release-notes
|
||||
path: notes/
|
||||
retention-days: 3
|
||||
@@ -5,15 +5,11 @@ name: run-parity
|
||||
# skipped `verify`, and GitHub counts a skipped required check as passed.
|
||||
on:
|
||||
pull_request:
|
||||
# A push starts a run only to cancel the old head's (see concurrency): the job runs on the label alone.
|
||||
types: [labeled, synchronize]
|
||||
types: [labeled]
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
# The run-parity label and pushes share one group per pull request, so the newest run cancels the one before: a
|
||||
# pushed pull request's run tested a head the merge would no longer land. Any other label gets a group of its own:
|
||||
# in the shared one, adding needs-proof cancelled the parity run queued seconds before (run 40766180150).
|
||||
group: run-parity-${{ github.event.pull_request.number }}${{ github.event.action == 'labeled' && github.event.label.name != 'run-parity' && format('-{0}', github.run_id) || '' }}
|
||||
group: run-parity-${{ github.event.pull_request.number }}
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
# Test runs never reach the telemetry server: no live-count ping, no uploads (docs/telemetry.md).
|
||||
@@ -27,4 +23,3 @@ jobs:
|
||||
base: ${{ github.event.pull_request.base.sha }}
|
||||
head: ${{ github.event.pull_request.head.sha }}
|
||||
full: ${{ contains(github.event.pull_request.labels.*.name, 'full-parity') }}
|
||||
frame_identity: ${{ contains(github.event.pull_request.labels.*.name, 'frame-identity') }}
|
||||
@@ -15,23 +15,17 @@ on:
|
||||
- '.github/workflows/telemetry-server.yml'
|
||||
permissions:
|
||||
contents: read
|
||||
concurrency:
|
||||
group: telemetry-server-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
jobs:
|
||||
check:
|
||||
# Our checks runners (label horizon-checks, docs/ci-runners.md); SELF_HOSTED_CI=light or off: GitHub's.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && vars.SELF_HOSTED_CI != 'light' && fromJSON('["self-hosted", "linux", "horizon-checks"]') || 'ubuntu-latest' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
defaults:
|
||||
run:
|
||||
working-directory: crates/horizon-telemetry-server
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
- uses: actions/checkout@v4
|
||||
- run: rustup toolchain install stable --profile minimal --component rustfmt --component clippy
|
||||
# Ours keep their build folder between jobs.
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
if: runner.environment == 'github-hosted'
|
||||
with:
|
||||
workspaces: crates/horizon-telemetry-server
|
||||
save-if: ${{ github.ref == 'refs/heads/main' }}
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
name: triage command
|
||||
# `/close`, `/reopen`, `/label`, `/unlabel` comments: the trusted reviewers in .github/trusted-reviewers.txt (and
|
||||
# Ludovic) triage issues and pull requests without any repository role (docs/release-flow.md "Trusted reviewers",
|
||||
# tools/ci/triage_command.py).
|
||||
#
|
||||
# Why no pull request's code runs here, though the token can write:
|
||||
# - `issue_comment` always runs this file from main, whoever comments and wherever.
|
||||
# - It checks out main's script and list only, never a pull request; it reads threads through the API.
|
||||
# - The comment's text and author reach the script as env vars, never in a shell line. The token stays in the step.
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
permissions:
|
||||
contents: read
|
||||
jobs:
|
||||
command:
|
||||
# Every other comment skips here, before a runner starts.
|
||||
if: >-
|
||||
github.event.comment.user.type != 'Bot' && (
|
||||
startsWith(github.event.comment.body, '/close') ||
|
||||
startsWith(github.event.comment.body, '/reopen') ||
|
||||
startsWith(github.event.comment.body, '/label') ||
|
||||
startsWith(github.event.comment.body, '/unlabel'))
|
||||
# One of our small runners (label horizon-light, docs/ci-runners.md): main's script only, as above.
|
||||
runs-on: ${{ vars.SELF_HOSTED_CI != 'off' && fromJSON('["self-hosted", "linux", "horizon-light"]') || 'ubuntu-latest' }}
|
||||
timeout-minutes: 5
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: actions/checkout@v7
|
||||
with:
|
||||
ref: main
|
||||
persist-credentials: false
|
||||
sparse-checkout: |
|
||||
.github/trusted-reviewers.txt
|
||||
tools/ci/nightly_set.py
|
||||
tools/ci/triage_command.py
|
||||
sparse-checkout-cone-mode: false
|
||||
- name: Run the command
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
BODY: ${{ github.event.comment.body }}
|
||||
AUTHOR: ${{ github.event.comment.user.login }}
|
||||
# Who may act is decided by this numeric ID: a login can be claimed by someone else after a rename.
|
||||
AUTHOR_ID: ${{ github.event.comment.user.id }}
|
||||
ISSUE: ${{ github.event.issue.number }}
|
||||
REPO: ${{ github.repository }}
|
||||
COMMENT_URL: ${{ github.event.comment.html_url }}
|
||||
run: python3 tools/ci/triage_command.py command
|
||||
@@ -21,7 +21,6 @@
|
||||
.DS_Store
|
||||
# What the client writes to its working directory when run from the repo root.
|
||||
/options.txt
|
||||
/debug-profile.json
|
||||
/horizon.txt
|
||||
/horizon-graphics.txt
|
||||
/horizon-controller.txt
|
||||
|
||||
@@ -9,26 +9,18 @@ Feature → files → harness for the most-changed areas: [docs/architecture.md]
|
||||
- **Never commit Mojang's files**: game jars, assets, decompiled source, prepared resources (`.local/`).
|
||||
`tools/check_public_tree.py` rejects them; `git config core.hooksPath .githooks` runs it on commit.
|
||||
- **Keep your runs away from real player data.** Any game or launcher you start gets fresh `mktemp -d`
|
||||
folders in `HORIZON_HOME` (logs, crash reports, telemetry consent, recordings; not saves), `HORIZON_LAUNCHER_HOME`, `XDG_DATA_HOME` and
|
||||
`XDG_CONFIG_HOME`, plus `HORIZON_LAUNCHER_NO_SELF_UPDATE=1` and `HORIZON_NO_AUDIO=1`. Saves, `options.txt` and
|
||||
caches go in the game folder, by default the working directory: start the game from a scratch folder with
|
||||
`--game-dir` pointing at it, or they land in the repo root, hidden by `.gitignore`. For the
|
||||
folders in `HORIZON_HOME` (the game's data), `HORIZON_LAUNCHER_HOME`, `XDG_DATA_HOME` and
|
||||
`XDG_CONFIG_HOME`, plus `HORIZON_LAUNCHER_NO_SELF_UPDATE=1` and `HORIZON_NO_AUDIO=1`, and, for the
|
||||
launcher, `HORIZON_LAUNCHER_TRASH`, `HORIZON_LAUNCHER_CLIPBOARD` and `HORIZON_LAUNCHER_DESKTOP` pointing into the scratch home. Never write to
|
||||
`~/.local/share/{applications,horizon,horizon-launcher}` or `~/.local/bin`.
|
||||
- **Mark what an agent posts.** A PR body starts with a line naming the person whose agent opened it and
|
||||
the tool: `> 🤖 Opened by <login>'s AI agent (<tool, model>), not by <login> personally.`, where `<login>`
|
||||
is the GitHub account the PR is opened from (`gh api user --jq .login`). Issues say "Filed by", reviews
|
||||
"Review by". Every comment starts with `🤖 Agent:`. Write only as the person you work for: the lines on
|
||||
this page that name Ludovic are for his own agents (account `ludovic111`), never for anyone else's.
|
||||
- **Mark what an agent posts.** A PR body starts with a line naming whose agent opened it and with what.
|
||||
Ludovic's agents write `> 🤖 Opened by Ludovic's AI agent (Claude), not by Ludovic himself.`, and a
|
||||
contributor's agent names its own person and tool (issues: "Filed by", reviews: "Review by"). Every
|
||||
comment starts with `🤖 Agent:`. Never write as Ludovic or as anyone else.
|
||||
- **Attribution.** Commits end with a `Co-Authored-By:` line for the agent that wrote them, and PR bodies
|
||||
with that agent's own "Generated with" line. Example, Ludovic's agents (Claude Code on `ludovic111`):
|
||||
first line `> 🤖 Opened by Ludovic's AI agent (Claude), not by Ludovic himself.`, commits
|
||||
`Co-Authored-By: Claude <model> <[email protected]>`, last line
|
||||
with that agent's own "Generated with" line. Ludovic's agents use
|
||||
`Co-Authored-By: Claude <model> <[email protected]>` and
|
||||
`🤖 Generated with [Claude Code](https://claude.com/claude-code)`.
|
||||
- **Layers** ([docs/layers.md](docs/layers.md)): engine uses engine; platform uses engine and platform; Horizon (its extras,
|
||||
cosmetics, shop, telemetry, launcher) uses platform and Horizon only, never the engine: it moves to its own repository
|
||||
later. `tools/check_layers.py` checks it. New Horizon code goes behind `horizon-extras`; built-in addresses go in
|
||||
`horizon-addresses`.
|
||||
- Everything players run is Rust. Python/Java only for dev tools and harness drivers in `tools/`.
|
||||
- Horizon-only features follow [docs/design-system.md](docs/design-system.md) and are off by default where
|
||||
they would change the vanilla look.
|
||||
@@ -36,16 +28,6 @@ Feature → files → harness for the most-changed areas: [docs/architecture.md]
|
||||
change), none for a fix. Agents never add `release-now`: the maintainer decides it. Merges ship in batches of 5, or after
|
||||
6 hours ([docs/release-flow.md](docs/release-flow.md)).
|
||||
- Contributors first: `gh pr list --state open --search <area>` before you start; never duplicate theirs.
|
||||
- **No hardcoded user-facing strings.** Keep UI translation-ready from the start. In the launcher (`launcher/`), wrap visible text with `tr("...")` or `trf("... {arg} ...", &[("arg", &val)])` from `crate::i18n` instead of raw string literals or `format!`. In the game, use translation keys (`Text::tr`, `lang::get`), never hardcoded English strings.
|
||||
- **Claim before you start**: comment `/claim` on the issue (no issue yet: open one, then claim it). An assigned
|
||||
issue is taken, and so is one labelled `in progress` (claimed on Discord): pick another. `/unclaim` when you stop;
|
||||
a claim with no open PR linking it is released after 5 days. The issues free to claim, without reading threads:
|
||||
`gh issue list --search 'is:open no:assignee -label:"in progress" -label:tracker -label:proposal -label:"not claimable" -linked:pr'`
|
||||
- **Machine translations stay unreviewed.** `tools/lang_review/` records only text a person who speaks the language
|
||||
wrote or checked; never `lang_coverage.py --mark-reviewed` machine text ([docs/translations.md](docs/translations.md)).
|
||||
- **Controllers reach what registers.** Draw controls with a registering helper (`ui::button`, `settings_shell::foot_button`); `graphics_style::button` and `screen_draw::button` only paint, and registering one part of a screen ends its crosshair, so register all of it.
|
||||
- **Render passes keep HDR's light.** A pass that reads, filters or redraws the world's picture (upscaling,
|
||||
anti-aliasing, sharpening, frame generation, post effects, captures) follows [docs/hdr-passes.md](docs/hdr-passes.md).
|
||||
|
||||
## Crates
|
||||
|
||||
@@ -53,13 +35,9 @@ Game workspace (root `Cargo.toml`); `launcher/` and `crates/horizon-telemetry-se
|
||||
|
||||
| Crate | Owns |
|
||||
|---|---|
|
||||
| `horizon-client` | Gameplay library (`src/lib.rs`: `game.rs` + `game/`, `entry.rs`) and thin executable (`src/main.rs`). Also the dedicated server (`--dedicated`). Re-exports `horizon-client-lib` for existing mod paths. |
|
||||
| `horizon-client-lib` | Reusable client systems, `horizon-ctl`, probes and their tests. Its manifest points to the existing sources under `crates/horizon-client/`; the library root is `src/client_lib.rs`. It never depends on gameplay. |
|
||||
| `horizon-items` | Blocks and items below gameplay: `blocks.rs` (block facts), `items.rs`, `item_data.rs` (components), `enchant.rs`, `cooldowns.rs`, `bundle.rs`, `item_nbt.rs`. Re-exported as `horizon_client::items`... |
|
||||
| `horizon-client` | The game: a lib (`src/lib.rs`, ~180 flat modules) and the bin (`src/main.rs` → `game.rs` + `game/`), plus `horizon-ctl` (`src/bin/horizon-ctl/`). Also the dedicated server (`--dedicated`) |
|
||||
| `horizon-command` | Command parsing (Brigadier): the vanilla tree, argument types, selectors, suggestions, the tree's network form. Re-exported as `horizon_client::command` |
|
||||
| `horizon-client-core` | The client lib's bottom layer: `text.rs`, `lang.rs`, `snbt.rs`, `nbt_path.rs`, `component.rs`, `scoreboard.rs`, `bossbar.rs`, `gamerules.rs`, `block_entity_nbt.rs`, registry/particle/sound tables. Re-exported under the old paths (`horizon_client::text`...) |
|
||||
| `horizon-client-input` | Key bindings and key names, toggle keys, mouse options, controller settings and glyphs, the clipboard, window options (`keybinds.rs`, `gamepad.rs`, `mouse.rs`, `window.rs`...). Re-exported under the old paths |
|
||||
| `horizon-client-render` | The client's world data, rendering and screens (chunks, meshing, light, streaming, `gfx`, HUD, menus, settings), modules that horizon-client re-exports under the same paths. Nothing in it reaches gameplay |
|
||||
| `horizon-world` | Vanilla world data with no gameplay loop: NBT, regions, chunks, `datafix/`, `worldgen/`, `level/` (server-side block behaviour, ticks, redstone), entity physics, items, effects, food, damage |
|
||||
| `horizon-core` | Simulation primitives: Java `Random`s, `jmath` (HotSpot-exact `Math`), positions, noise, density, paletted storage, `version.rs` (the pinned version) |
|
||||
| `horizon-protocol` | Network protocol 777: codecs, framing, encryption, `packets/{handshake,status,login,configuration,play}.rs`, `entity_data.rs` |
|
||||
@@ -67,74 +45,51 @@ Game workspace (root `Cargo.toml`); `launcher/` and `crates/horizon-telemetry-se
|
||||
| `horizon-prepare` | Builds `.local/horizon-client/26.3` from the player's own Minecraft install (runs the Java exporters) |
|
||||
| `horizon-server` | `horizon-server`: `server.toml`, CLI, supervisor of the headless game ([docs/hosting.md](docs/hosting.md)) |
|
||||
| `horizon-server-files` | `server.properties`, eula, ops/whitelist/bans, usercache |
|
||||
| `horizon-anticheat` | The dedicated server's anticheat, off by default: `[anticheat]` settings, violation levels, the checks' rules; the hub runs them (`lan/anticheat.rs`) ([docs/anticheat.md](docs/anticheat.md)) |
|
||||
| `horizon-cosmetics` | Cosmetic items Horizon clients draw on players (off by default): the item format, bones and animations ([docs/cosmetics.md](docs/cosmetics.md)) |
|
||||
| `horizon-addresses` | Every built-in address of an outside service vanilla doesn't contact (Horizon layer; [docs/layers.md](docs/layers.md#built-in-addresses)) |
|
||||
| `horizon-friends`, `horizon-relay` | Play with Friends: invite codes, encrypted tunnel, the relay ([docs/play-with-friends.md](docs/play-with-friends.md)) |
|
||||
| `horizon-mods`, `cargo-horizon-mod` | Content mods (`.hmod`: manifest, content fence, no code), the registry index and `.hpack`, and `cargo horizon-mod` (`new`, `build`, `run`, `check`, `registry`) ([docs/mods.md](docs/mods.md)). Code mods are native, built by the launcher ([docs/native-mods.md](docs/native-mods.md)) |
|
||||
| `horizon-mods`, `horizon-mod-sdk`, `cargo-horizon-mod` | Sandboxed WebAssembly mods: runtime, SDK + WIT, `cargo horizon-mod` ([docs/mods.md](docs/mods.md)) |
|
||||
| `horizon-port-pack` | Porting Java modpacks ([docs/modpacks.md](docs/modpacks.md)) |
|
||||
| `horizon-optifine` | OptiFine-format pack files below every feature that reads them: `.properties`, the name/range/block matchers, paths and `optifine/` folders, and custom entity models (`cem/`: `.jem`/`.jpm` parsing and baking) |
|
||||
| `horizon-polytone` | Polytone-format pack files (`assets/*/polytone/`), read clean-room from the public wiki: targets, biome and dimension modifiers and their environment attribute layers (#11486) |
|
||||
| `horizon-shader-api` | Horizon's own WGSL shader packs ([docs/api/shaders.md](docs/api/shaders.md)): `horizon-shaders.toml`, the `.hshader` package; shared by the game, the launcher and the registry |
|
||||
| `horizon-shaders` | Shader packs (the `shaders/` folder format), rebuilt clean-room from a written spec of the format; no wgpu |
|
||||
| `horizon-theme` | Design tokens and fonts for the launcher, the game's own menus and the website |
|
||||
| `horizon-telemetry`, `horizon-telemetry-server`, `horizon-bench` | Opt-in data collection, its ingest server, the benchmark report format |
|
||||
| `horizon-system` | The machine the game runs on (OS, CPU, memory, drive, power, GPU maker and memory), for the crash report, the renderer's GPU info and telemetry |
|
||||
| `horizon-platform` | The platform's public API: what the Horizon layer may use of the engine ([docs/layers.md](docs/layers.md)); re-exports `horizon-system` today |
|
||||
| `horizon-hooks`, `horizon-game`, `horizon-official`, `horizon-heartbeat` | The layer seam: the engine's hooks for crates above it, the game an executable starts, the official executable (shipped as `horizon-client`) that registers Horizon's in-game parts, the first of them ([docs/layers.md](docs/layers.md#how-a-horizon-crate-plugs-in)) |
|
||||
| `horizon-dualsense`, `horizon-threads`, `horizon-release-sign`, `horizon-bots`, `xtask` | DualSense output, thread priorities, signed release checksums, load-test bots, repo tasks |
|
||||
| `launcher/` | GPUI launcher: `main.rs` (UI), `backend.rs` (installs, updates), `cli.rs`, `mcp.rs`, `*_page.rs` |
|
||||
|
||||
Other top-level folders: `tools/` (harnesses and dev scripts), `tests/` (Python unit tests: `python3 -m
|
||||
unittest discover -s tests`), `mods/horizon/src/test/java/dev/horizonlab/parity/` (Java oracles),
|
||||
`docs/`, `.github/workflows/`. The website (playhorizon.dev) is the private horizon-rust/horizon-site: its build
|
||||
`docs/`, `.github/workflows/`. The website (playhorizon.dev) is the private ludovic111/horizon-site: its build
|
||||
reads `README.md`, `launcher/links.json`, `docs/api/`, `roadmap/roadmap.json` and `crates/horizon-theme/tokens.css` from main.
|
||||
|
||||
## Write tests with signal
|
||||
|
||||
- Test observable behavior, not words in docs, comments or source. Keep checks for machine-consumed contracts.
|
||||
- Use independent expected values or a vanilla oracle; do not derive the answer from the code under test.
|
||||
- Test outcomes, not only calls to stubs. Use mocks to isolate behavior, not as the behavior itself.
|
||||
- Skip tests of trivial constants, derives and getters, or behavior already covered by another test.
|
||||
- Avoid pinning implementation details; a harmless refactor should not break a behavior test.
|
||||
- Make slow tests faster without removing cases or weakening their coverage.
|
||||
- Never delete parity harnesses or tests that pin vanilla behaviour: they are the spec.
|
||||
|
||||
## Build and test fast
|
||||
|
||||
```sh
|
||||
python3 tools/pr_ready.py # the self-check: fmt, clippy -D warnings, touched crates' tests, harnesses; paste its block in the PR
|
||||
python3 tools/pr_ready.py --quick # same without harnesses
|
||||
cargo test -p horizon-client -p horizon-client-lib --lib --bins --tests # skips the examples (pr_ready does this); `--doc` separately
|
||||
cargo test -p horizon-client-lib --lib mod_content::tests:: -- --ignored # the slow content-root tests, #[ignore]d; pr_ready runs them when mod content, assets, blocks or items change
|
||||
cargo test -p horizon-client --lib --bins --tests # skips the 104 examples (pr_ready does this); `--doc` separately
|
||||
cargo test -p horizon-client --features horizon-client/mods --lib mod_content::tests:: -- --ignored # the 5 slow content-root tests, #[ignore]d; pr_ready runs them when mod content, assets, blocks or items change
|
||||
cargo build --profile fast -p horizon-client # optimized, quick to link: use it to play or run lan_e2e
|
||||
python3 tools/parity.py --changed origin/main # the harnesses your branch can affect (CI's parity job)
|
||||
python3 tools/parity.py --changed-files paths.txt --list # which harnesses cover these files, without running them
|
||||
python3 tools/parity.py mob_ai sculk # named harnesses
|
||||
python3 tools/lan_e2e.py --check chest # two real games over LAN (server-thread host)
|
||||
python3 tools/lan_e2e.py --check chest # two real games over LAN (server-thread host); --in-frame compares the fallback
|
||||
python3 tools/agent_control_e2e.py # horizon-ctl / MCP end to end
|
||||
python3 tools/lang_coverage.py --summary # the keys each language still misses, and its English leftovers
|
||||
```
|
||||
|
||||
- Harnesses and the game need the vanilla data in `.local/` (`minecraft/`, `horizon-client/26.3`, `datagen/`,
|
||||
`tools/`): see [docs/parity-workflow.md](docs/parity-workflow.md). Without it, pr_ready lists the
|
||||
harnesses for CI.
|
||||
- A harness = `tools/test_<name>_parity.py` + a Java oracle (`mods/horizon/src/test/java/dev/horizonlab/parity/Vanilla*Oracle.java`)
|
||||
+ a Rust probe: `crates/<crate>/examples/<name>_{probe,fixture}.rs` (mostly horizon-world and horizon-client),
|
||||
- A harness = `tools/test_<name>_parity.py` (324 of them) + a Java oracle (`mods/horizon/src/test/java/dev/horizonlab/parity/Vanilla*Oracle.java`)
|
||||
+ a Rust probe: `crates/<crate>/examples/<name>_{probe,fixture}.rs` (horizon-world 175, horizon-client 104),
|
||||
or the game binary with a fixture env var (`game/dispense_fixture.rs`, `game/sculk_fixture.rs`,
|
||||
`game/command_harness.rs`, `game/net_harness.rs`). Copy a nearby harness for a new one.
|
||||
- Developing a native mod? Run `horizon-launcher settings native-profile dev` once. `dev` builds the game crate
|
||||
unoptimized: a mod edit rebuilds about 6× faster than with `performance`, while game logic runs up to about twice as
|
||||
slow. Use it while developing, not for playing; `performance` stays the default for players and releases
|
||||
([docs/native-mods.md](docs/native-mods.md)).
|
||||
- Probes build into `.local/parity-target/`; harnesses find binaries via `lab.cargo_target()`, never `target/`.
|
||||
- Harness selection uses Cargo dep-info and reachable-code narrowing (`tools/parity_reach.py`).
|
||||
`horizon-client-lib` builds the control tool and client probes without gameplay; their dep-info
|
||||
excludes `game.rs` and `game/`, so gameplay edits do not rebuild or select those probes.
|
||||
Source paths remain in `crates/horizon-client/`. Measure actual harness selection on refreshed
|
||||
records with `tools/parity.py --changed-files paths.txt --list`; historical counts are not a guarantee.
|
||||
- What a change reruns (of 329 harnesses, measured 2026-10-23): a file of the game binary (`game.rs`, `game/`)
|
||||
~25, a file of the client lib ~103, of `horizon-world` ~103–109, of `horizon-core` ~119. Plan for it.
|
||||
- Rust integration tests: `crates/horizon-client/tests/` (`lan_bot.rs`, `generation_saves.rs`, `streaming_meshes.rs`).
|
||||
- Linux needs `libasound2-dev libudev-dev`; `--no-default-features` drops audio, controllers, `discord`, `friends` and `heartbeat` (the server build).
|
||||
- **macOS:** `cargo build/test --workspace` may fail to link the two wasm guest cdylibs (undefined
|
||||
`horizon:mods/events` symbols) until #1446 lands: add `--exclude coords-hud --exclude predator-missile --exclude horizon-mods-test-guest --exclude horizon-mods-test-ui-guest`.
|
||||
Their real check is `cargo test -p horizon-mods` (builds them for `wasm32-unknown-unknown`).
|
||||
- Linux needs `libasound2-dev libudev-dev`; `--no-default-features` drops audio and controllers (the server build).
|
||||
- Run and drive the game (starts the `horizon-client` beside `horizon-ctl`; other arguments go to the game):
|
||||
`target/fast/horizon-ctl --socket $PWD/ctl.sock launch --world W --creative --offscreen --wait --resources $PWD/.local/horizon-client/26.3`,
|
||||
then `horizon-ctl --socket … state|keys|turn|command|screenshot|quit`
|
||||
@@ -142,13 +97,10 @@ python3 tools/lang_coverage.py --summary # the keys each language still misses
|
||||
|
||||
## Vanilla reference
|
||||
|
||||
- Start parity work from the port ledger, not grep: `python3 tools/port_ledger.py issue N` (or `where
|
||||
Class.method`, `what file:line`), and `check --base origin/main` before the PR. How:
|
||||
[.claude/skills/vanilla-parity/SKILL.md](.claude/skills/vanilla-parity/SKILL.md), [docs/port-ledger.md](docs/port-ledger.md).
|
||||
- Decompiled sources: `.local/minecraft/26.3/sources/{client,server}/` (`python3 tools/lab.py decompile`).
|
||||
- Bytecode queries (callers through lambdas, every overload):
|
||||
`python3 tools/rea_vanilla.py method net.minecraft.world.level.block.DispenserBlock dispenseFrom`
|
||||
([docs/parity-workflow.md](docs/parity-workflow.md#reading-vanilla)).
|
||||
([docs/decompilation-status.md](docs/decompilation-status.md)).
|
||||
- A harness runs the oracle against the real 26.3 jars and the Rust probe on the same inputs, then compares
|
||||
their JSON. Oracle runs are cached by `tools/parity_shim.py`; `--fresh` reruns them.
|
||||
- Mirror vanilla's `Math` calls with `horizon_core::jmath`, and vanilla's RNG with `horizon_core::random`:
|
||||
@@ -156,70 +108,69 @@ python3 tools/lang_coverage.py --summary # the keys each language still misses
|
||||
|
||||
## horizon-client: where things live
|
||||
|
||||
`L:` = lib (`crates/horizon-client/src/`, or `crates/horizon-client-render/src/` for the modules that crate holds, under
|
||||
the same `horizon_client::<module>` paths), `G:` = gameplay (`crates/horizon-client/src/game/`), also in the lib in normal builds.
|
||||
Gameplay keeps its `horizon_client::<module>` imports through a self-crate alias. The executable
|
||||
contains only the allocator, mod API marker and a call to `entry::main`. For unit tests, the lib
|
||||
excludes `entry` and `game`, and the executable test target owns `game` so its process-wide test
|
||||
state stays separate from the library tests. This compiles gameplay twice for executable tests.
|
||||
`L:` = lib (`crates/horizon-client/src/`), `G:` = bin (`crates/horizon-client/src/game/`). The lib can't see
|
||||
`Game`; bin code reaches the lib as `horizon_client::<module>`.
|
||||
|
||||
| Subsystem | Files |
|
||||
|---|---|
|
||||
| Game loop, tick, frame | `game.rs`: `fn run`, `fn tick`, `fn tick_world`, `fn render`; G: `window_handler.rs` (`impl ApplicationHandler for Game`: `window_event`, `about_to_wait`), `launch_options.rs` (the command line); L: `clock.rs`, `spans.rs`; `horizon-client-input/src/window.rs` |
|
||||
| Rendering | L: `gfx.rs` (`Renderer::new`, `Renderer::render`), `gfx/` (cull, occlusion, translucency, upload, timing, lod, weather, stars, end_sky), `*.wgsl`, `particles.rs`, `block_entity_render.rs`, `item_render.rs`, `fog.rs`, `clouds.rs`, `camera.rs`, `first_person.rs`; G: `render_tick.rs`, `frame_geometry.rs` (cracks, sun and moon, first-person hand, rain and snow), `item_draw.rs`, `screen_backgrounds.rs` (panorama, menu blur, border wall) |
|
||||
| Chunks, streaming, light | L: `streaming.rs` (worker pool: generate, light, mesh), `world.rs`, `chunk.rs`, `chunk_map.rs`, `light.rs`, `mesher.rs` + `mesher/`, `vanillagen.rs` (binds horizon-world's generator), `lod.rs` + `lod/`, `server_terrain.rs` (a server's kept chunks), `bluemap.rs` + `bluemap_detect.rs` (far terrain from its web map), `ticket_levels.rs`; G: `world_loading.rs`, `world_entry.rs`, `postprocess.rs`, `world_update.rs` (`fn update_world`, far terrain) |
|
||||
| Game loop, tick, frame | `game.rs`: `fn run`, `impl ApplicationHandler for Game` (`window_event`, `about_to_wait`), `fn tick`, `fn tick_world`, `fn render`; L: `clock.rs`, `window.rs`, `spans.rs` |
|
||||
| Rendering | L: `gfx.rs` (`Renderer::new`, `Renderer::render`), `gfx/` (cull, occlusion, translucency, upload, timing, lod, weather, stars, end_sky), `*.wgsl`, `particles.rs`, `block_entity_render.rs`, `item_render.rs`, `fog.rs`, `clouds.rs`, `camera.rs`, `first_person.rs`; G: `render_tick.rs`, `item_draw.rs` |
|
||||
| Chunks, streaming, light | L: `streaming.rs` (worker pool: generate, light, mesh), `world.rs`, `chunk.rs`, `chunk_map.rs`, `light.rs`, `mesher.rs` + `mesher/`, `vanillagen.rs` (binds horizon-world's generator), `lod.rs` + `lod/`, `ticket_levels.rs`; G: `world_loading.rs`, `postprocess.rs`; game.rs `fn update_world` |
|
||||
| World generation | `crates/horizon-world/src/worldgen/` (`generator*.rs`, `feature_graph.rs`, `structure/`, `carver/`) |
|
||||
| Block behaviour | `crates/horizon-world/src/level/` (`mod.rs`, `tick.rs`, `hooks.rs`, `redstone.rs`, `place.rs`, `interact.rs`); G: `block_ticks.rs` (`fn tick_blocks`); game.rs `fn process_level_events` |
|
||||
| Block behaviour | `crates/horizon-world/src/level/` (`mod.rs`, `tick.rs`, `hooks.rs`, `redstone.rs`, `place.rs`, `interact.rs`); game.rs `fn tick_blocks`, `fn process_level_events` |
|
||||
| Mobs | L: `mobs.rs` (types), `mobs/` (`ai.rs`, `goals.rs`, `brain.rs`, `*_brain.rs`, `nav.rs`, `path.rs`, `species.rs`, `spawning.rs`, `render.rs`, `anim.rs`); G: `creatures.rs` (ticking, spawning, mob events), one file per mob family (`dragon.rs`, `wither.rs`, `villagers.rs`, `piglins.rs`, `golems.rs`...), `natural_spawning.rs` |
|
||||
| Other entities | L: `entities.rs`, `projectiles.rs`, `arrows.rs`; G: `item_entities.rs` (dropped items, experience orbs), `boats.rs`, `minecarts.rs`, `mounts.rs`, `armor_stands.rs`, `paintings.rs`, `frames.rs`, `fireworks.rs`, `tnt.rs`, `explosion.rs` |
|
||||
| Player actions | game.rs (`fn tick_mining`, `fn break_block`); G: `use_hand.rs` (`fn use_hand`), `item_actions.rs` (`fn use_item`), `melee.rs` (`fn attack`), `hand.rs`, `combat.rs`, `consume.rs`, `using_item.rs` (an item in use, tick by tick), `potions.rs`, `shield.rs`, `crossbow.rs`, `trident.rs`, `fishing.rs`; L: `motion.rs` + `motion/` (movement), `collisions.rs`; crate `horizon-items`: `items.rs`, `item_data.rs`, `enchant.rs`, `blocks.rs` |
|
||||
| Inventory and containers | L: `menu.rs` (`AbstractContainerMenu.clicked`), `container_screen.rs`, `containers.rs`, `creative.rs`, `crafting.rs`, `recipe_book*.rs`, `stations.rs`, `merchant.rs`; G: `menu_clicks.rs` (`fn menu_ops`, `fn click_inventory`), `stations.rs`, `trading.rs`, `recipe_book.rs`, `machines.rs`, `inventory_input.rs` (keys and clicks over a container), `inventory_slots.rs` (slot layout and drawing) |
|
||||
| Other entities | L: `entities.rs`, `projectiles.rs`, `arrows.rs`; G: `boats.rs`, `minecarts.rs`, `mounts.rs`, `armor_stands.rs`, `paintings.rs`, `frames.rs`, `fireworks.rs`, `tnt.rs`, `explosion.rs` |
|
||||
| Player actions | game.rs (`fn use_hand`, `fn use_item`, `fn attack`, `fn tick_mining`, `fn break_block`); G: `hand.rs`, `combat.rs`, `consume.rs`, `potions.rs`, `shield.rs`, `crossbow.rs`, `trident.rs`, `fishing.rs`; L: `motion.rs` + `motion/` (movement), `collisions.rs`, `items.rs`, `item_data.rs` |
|
||||
| Inventory and containers | L: `menu.rs` (`AbstractContainerMenu.clicked`), `container_screen.rs`, `containers.rs`, `creative.rs`, `crafting.rs`, `recipe_book*.rs`, `stations.rs`, `merchant.rs`; game.rs `fn menu_ops`, `fn click_inventory`; G: `stations.rs`, `trading.rs`, `recipe_book.rs`, `machines.rs` |
|
||||
| Commands | parse: crate `horizon-command` (`args.rs`, `selector.rs`, `tree_*.rs`, `vanilla.rs`); run: G: `commands.rs` (dispatch) + `commands/*.rs` (`admin`, `execute`, `items`, `players`, `world_cmds`...); L: `scoreboard_cmd.rs`, `data_cmd.rs`; `horizon-client-core`: `nbt_path.rs`, `scoreboard.rs`; G: `functions.rs`, `command_blocks.rs` |
|
||||
| UI screens | `Screen` enum in game.rs; L: `title.rs` + `title/`, `options_ui.rs`, `multiplayer.rs`, `pack_screen.rs`, `settings_shell.rs` (Horizon's settings screens on it: `extras_ui.rs`, `graphics_ui.rs`, `controller_ui.rs`, `shader_ui.rs`; a page list too long for its column collapses into one row), `screen_draw.rs`, `ui.rs` (widgets), `hud.rs`, `hud_layout.rs`, `hud_overlays.rs`, `hud_kit/` (Horizon overlays' `Room` and `Plate`, the collapsed page strip `tabs` the shell's page list uses, [docs/ui-kit.md](docs/ui-kit.md)), `pad_glyph.rs` (controller glyphs, by what the button does), `chat.rs`, `tab_list.rs`; G: `startup_menu.rs`, `loading_screen.rs` (the loading screen, the pre-game `App`), `resource_loader.rs` (what a start loads, `run_loading`), `screens.rs` (pause, death), `options.rs`, `lan_screen.rs`, `chat.rs`, `sign_edit.rs`, `books.rs`, `creative_screen.rs` |
|
||||
| UI screens | `Screen` enum in game.rs; L: `title.rs` + `title/`, `options_ui.rs`, `multiplayer.rs`, `pack_screen.rs`, `graphics_ui.rs`, `screen_draw.rs`, `ui.rs` (widgets), `hud.rs`, `hud_layout.rs`, `hud_overlays.rs`, `chat.rs`, `tab_list.rs`; G: `startup_menu.rs`, `screens.rs` (pause, death), `options.rs`, `lan_screen.rs`, `chat.rs`, `sign_edit.rs`, `books.rs` |
|
||||
| Multiplayer client | L: `net.rs` (network thread); G: `remote.rs` (`fn handle_packet`, `fn tick_remote`), `remote_*.rs` (mob data, objects, projectiles, vehicles, stations) |
|
||||
| LAN host / server side | L: `lan/` (`conn.rs` handshake + login threads, `hub.rs` + `hub/` play state, `chunks.rs`, `entity.rs`, `tracking.rs`, `guest.rs`, `playerdata.rs`); G: `lan.rs` (`LanHost`), `lan_actions.rs` (`fn as_guest`, `fn tick_guests`), `lan_*.rs` per feature, `lan_entities.rs` (tracked entities) |
|
||||
| Integrated server | G: `integrated.rs` (the server thread), `levels.rs` (one level per dimension, `fn tick_server`), `server_travel.rs` |
|
||||
| Dedicated server | G: `dedicated.rs`, `dedicated/status.rs`; crates `horizon-server-files`, `horizon-server`, `horizon-anticheat` (L: `lan/anticheat.rs`) |
|
||||
| Save and load | L: `save.rs` (level.dat, regions, playerdata), `entity_nbt.rs`, `options_file.rs`; `horizon-client-core/src/block_entity_nbt.rs`; G: `saving.rs`, `persist.rs` (entities), `world_session.rs` (opening and closing a world); `crates/horizon-world/src/{region.rs,nbt.rs,datafix/}` |
|
||||
| Input | game.rs `fn window_event`; G: `play_keys.rs` (`fn key_pressed`), `play_input.rs` (`fn play_mouse`, toggled keys, the hotbar wheel); crate `horizon-client-input` (`keybinds.rs`, `keymapping.rs`, `key_names.rs`, `mouse.rs`, `input.rs`, `interaction_input.rs`, `gamepad.rs`, `clipboard.rs`); L: `osk.rs`; G: `pad.rs`, `pad_menu.rs`, `pad_craft.rs`, `pointer_capture.rs` (mouse look, pointer grab) |
|
||||
| Dedicated server | G: `dedicated.rs`, `dedicated/status.rs`; crates `horizon-server-files`, `horizon-server` |
|
||||
| Save and load | L: `save.rs` (level.dat, regions, playerdata), `entity_nbt.rs`, `options_file.rs`; `horizon-client-core/src/block_entity_nbt.rs`; G: `saving.rs`, `persist.rs` (entities); `crates/horizon-world/src/{region.rs,nbt.rs,datafix/}` |
|
||||
| Input | game.rs `fn window_event`, `fn key_pressed`, `fn play_mouse`; L: `keybinds.rs`, `keymapping.rs`, `key_names.rs`, `mouse.rs`, `input.rs`, `interaction_input.rs`, `gamepad.rs`, `osk.rs`, `clipboard.rs`; G: `pad.rs`, `pad_menu.rs` |
|
||||
| Audio | L: `audio.rs` (mixer), `sound_engine.rs`, `sound_events.rs`, `music.rs`, `ambience.rs`; G: `music.rs`, `subtitle_hud.rs` |
|
||||
| Resource packs | L: `packs.rs` + `packs/`, `pack_screen.rs`, `atlas_sources.rs`, `sprites.rs`, `mipmap.rs`, `model_library.rs`, `font.rs`, `mobs/cem.rs` + `mobs/cem_anim.rs` (OptiFine/EMF entity models and their animations); `horizon-client-core/src/lang.rs`; crates `horizon-assets`, `horizon-optifine`; G: `packs.rs` |
|
||||
| Resource packs | L: `packs.rs` + `packs/`, `pack_screen.rs`, `atlas_sources.rs`, `sprites.rs`, `mipmap.rs`, `model_library.rs`, `font.rs`; `horizon-client-core/src/lang.rs`; crate `horizon-assets`; G: `packs.rs` |
|
||||
| Agent control | L: `control.rs` (socket), `bin/horizon-ctl/`; G: `control.rs`, `agent.rs`, `events.rs`, `ui_control.rs` ([docs/agent-control.md](docs/agent-control.md)) |
|
||||
| Mods | crate `horizon-mods`; G: `mods.rs`; L: `mod_content.rs`, `mod_list.rs` |
|
||||
| Horizon extras, settings | L: `extras.rs`, `graphics.rs`, `settings.rs`, `minimap.rs`; G: `extras.rs`, `tweaks.rs`, `options.rs` |
|
||||
|
||||
## How `Game` is organised
|
||||
|
||||
- `struct Game` (game.rs) holds everything. Its methods are spread over many files: game.rs keeps
|
||||
- `struct Game` (game.rs, ~290 fields) holds everything. Its methods are spread over ~180 files: game.rs keeps
|
||||
the core (tick, render, input, inventory, world open/close) and each `game/<feature>.rs` adds an
|
||||
`impl Game<'_>` block for one feature, with its own state types. Fields stay private to the gameplay module and its descendants. Gameplay tests run in the gameplay library, separate from reusable-library tests.
|
||||
`impl Game<'_>` block for one feature, with its own state types. Fields are private to the bin.
|
||||
- Find a feature's code: `grep -rn "fn tick_<thing>\|fn <verb>_<thing>" crates/horizon-client/src/game*`;
|
||||
the file is usually `game/<thing>s.rs`. Who calls it: grep the name in game.rs's `fn tick` / `fn tick_world`.
|
||||
- Fields that say which mode runs: `remote` (this window is a client of a server: multiplayer, LAN guest, or
|
||||
single player on its server thread), `lan` (`LanHost`: this world is open to the network), `integrated`
|
||||
(the window's own server thread), `serving` (this `Game` *is* that server thread), `options.dedicated`.
|
||||
`fn tick` returns `tick_remote()` when `remote` is set; a server ticks its levels (`fn tick_world`).
|
||||
- A server's players run through the shared gameplay code: `as_guest` swaps the guest's
|
||||
`fn tick` returns `tick_remote()` when `remote` is set; nothing else of the local simulation runs.
|
||||
- A server's players run through the same gameplay code as the local player: `as_guest` swaps the guest's
|
||||
state (position, inventory, mode, mining, item use) into `Game` for one call (`game/lan_actions.rs`), and
|
||||
`levels.rs` swaps whole dimensions in the same way. Changes reach clients through the block log, level
|
||||
events and the entity tracker (`lan/tracking.rs`, `game/lan_entities.rs`).
|
||||
- Shared read-only data: `Resources` (`res`: blocks, items, recipes, mob types, biomes) and `PackResources`
|
||||
(`pack`), both in game.rs, their methods in `game/resource_tables.rs`.
|
||||
(`pack`), both in game.rs.
|
||||
|
||||
## Single player runs on a server thread
|
||||
## The two single-player paths
|
||||
|
||||
`game/integrated.rs` runs a second `Game` (`serving`) on a "Server thread" with one level per dimension;
|
||||
the window joins it as a client through memory (`remote`), exactly as a LAN guest or a dedicated server's
|
||||
player does (#1514). A window's `Game` never ticks a world itself: the old in-frame path is gone
|
||||
(`--in-frame` and `--no-server-thread` only print a notice; `HORIZON_SERVER_THREAD` is ignored).
|
||||
Open `[server-thread]` issues list the gaps left.
|
||||
1. **Server thread (default since #1514):** `game/integrated.rs` runs a second `Game` (`serving`) on a
|
||||
"Server thread" with one level per dimension; the window joins it as a client through memory (`remote`),
|
||||
exactly as a LAN guest or a dedicated server's player does. This is what players run. Open
|
||||
`[server-thread]` issues list the gaps left.
|
||||
2. **In-frame (`--in-frame`, `--no-server-thread` or `HORIZON_SERVER_THREAD=0`):** the window's `Game` ticks
|
||||
the world itself, one level that follows the player (`fn enter_dimension`). Deterministic rule fixtures still use this path; player-facing integration uses the default server thread.
|
||||
|
||||
Single player, LAN guests and dedicated servers all run the server code, so a fix there serves all three.
|
||||
Test the server thread when you touch player-facing gameplay:
|
||||
LAN guests and dedicated servers always use the server code, so a fix there serves both. Test both paths
|
||||
when you touch player-facing gameplay:
|
||||
|
||||
```sh
|
||||
cargo run --profile fast -p horizon-client -- --resources .local/horizon-client/26.3 --world T # server thread
|
||||
cargo run --profile fast -p horizon-client -- --resources .local/horizon-client/26.3 --world T --in-frame # in-frame
|
||||
python3 tools/lan_e2e.py --check <name> # host on its server thread, guest is a server client
|
||||
python3 tools/lan_e2e.py --in-frame --check <name> # comparison (portals, levels, distance, lava need server-thread mode)
|
||||
python3 tools/parity.py dedicated_server server_entities server_player_damage
|
||||
```
|
||||
|
||||
|
||||
@@ -2,111 +2,59 @@
|
||||
|
||||
Thanks for helping. Horizon is Minecraft: Java Edition 26.3 rewritten in Rust, and the one rule that shapes
|
||||
everything is that **it plays exactly like vanilla**. This page is the short version of how we work; questions are
|
||||
welcome on [Discord](https://discord.gg/playhorizon).
|
||||
welcome on [Discord](https://discord.gg/HcTeMZxe5E).
|
||||
|
||||
This repository holds the game and the launcher, plus the tools, tests and docs that build, check and release them.
|
||||
The website (playhorizon.dev) is built in a separate repository from this one's README, `docs/api/` and roadmap. Anything
|
||||
else (videos, Discord and other community material) lives elsewhere.
|
||||
The website (playhorizon.dev) is built in a separate repository from this one's README, `docs/api/` and roadmap. Anything else (videos, Discord and other community material) lives elsewhere.
|
||||
|
||||
**Where to start: [playhorizon.dev/hub](https://playhorizon.dev/hub).** It shows what is being done now and next
|
||||
([ROADMAP.md](ROADMAP.md) in the repository), the work board, good first tasks, and the forms to report a bug or
|
||||
suggest something. A pull request for a roadmap item carries its `roadmap:<id>` label; ideas go to the suggestion
|
||||
queue (the hub, or `/suggest` on Discord) rather than to issues, which are for bugs.
|
||||
|
||||
**Mod-related pull requests go to [arismoko/horizon](https://github.com/arismoko/horizon)**, the fork that carries the
|
||||
mod API and reviews and merges that work. That covers the mod API, native hooks and events for mods, native mods,
|
||||
content mods (`.hmod`), mixins, wasm mods, `cargo horizon-mod`, `horizon-mods`, mod builds and the registry, and
|
||||
their docs ([mods](docs/mods.md), [native mods](docs/native-mods.md)). Open the pull request there from your usual
|
||||
branch. Mod-related pull requests opened here are closed with a pointer to it. Engine extension points that Horizon's
|
||||
own crates register (the [layer split](docs/layers.md)), resource and shader pack formats, and gameplay fixes stay
|
||||
here.
|
||||
|
||||
## Build it
|
||||
|
||||
- **Prerequisites:** Rust (stable), Python 3.10+, JDK 25, and on Linux the ALSA and udev headers
|
||||
(`libasound2-dev libudev-dev`).
|
||||
- **Resources:** Horizon never downloads the game; it prepares its resources from your own copy of Minecraft 26.3, as
|
||||
described in [Build from source](README.md#build-from-source).
|
||||
- **Commands:**
|
||||
You need Rust (stable), Python 3.10+, JDK 25, and on Linux the ALSA and udev headers (`libasound2-dev libudev-dev`).
|
||||
Horizon never downloads the game: it prepares its resources from your own copy of Minecraft 26.3, as described in
|
||||
[Build from source](README.md#build-from-source).
|
||||
|
||||
```sh
|
||||
cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar
|
||||
cargo run --release -p horizon-client
|
||||
```
|
||||
```sh
|
||||
cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar
|
||||
cargo run --release -p horizon-client
|
||||
```
|
||||
|
||||
- **Launcher:** its own Cargo workspace in `launcher/` (`cd launcher && cargo run`; on NixOS, `nix-shell` first).
|
||||
The launcher is its own Cargo workspace in `launcher/` (`cd launcher && cargo run`; on NixOS, `nix-shell` first).
|
||||
|
||||
## Vanilla first
|
||||
|
||||
Wherever vanilla has a feature, vanilla is the specification, down to the order of random calls. "Parity" here means
|
||||
Horizon gives the same results as the pinned 26.3 client and server for the same inputs, checked by a **harness**: a
|
||||
`tools/test_*_parity.py` script that runs a small Java oracle against the real game and a Rust probe against Horizon,
|
||||
and compares their outputs.
|
||||
Wherever vanilla has a feature, vanilla is the specification, down to the order of random calls. "Parity" here
|
||||
means Horizon gives the same results as the pinned 26.3 client and server for the same inputs, checked by a
|
||||
**harness**: a `tools/test_*_parity.py` script that runs a small Java oracle against the real game and a Rust
|
||||
probe against Horizon, and compares their outputs. There are about 290 of them.
|
||||
|
||||
- **Read the vanilla code before writing Horizon's.** `tools/rea_vanilla.py` queries the pinned game bytecode:
|
||||
`python3 tools/rea_vanilla.py method net.minecraft.world.level.block.DispenserBlock dispenseFrom`.
|
||||
Say in your pull request which vanilla classes and methods you followed.
|
||||
- **One version: 26.3.** Parity work targets 26.3 until its parity is good, redstone first. Don't open pull requests
|
||||
that move Horizon to a newer Minecraft version for now; to join servers on a newer version, put a Via proxy
|
||||
(ViaVersion, ViaProxy) in front of them.
|
||||
- **Gameplay changes come with a harness**, new or extended, so the next change can't silently break them.
|
||||
[The parity workflow](docs/parity-workflow.md) shows how harnesses run; copy a nearby one.
|
||||
- **Horizon's own features** (the launcher, the new menus) follow [the design system](docs/design-system.md) and are
|
||||
off by default wherever they would change the vanilla look.
|
||||
- **Three layers: engine, platform, Horizon.**
|
||||
- Vanilla code never depends on the platform (mods, shader packs, HDR, the settings system) or on Horizon
|
||||
(its extras, cosmetics, the shop, official servers, telemetry).
|
||||
- The platform never depends on Horizon.
|
||||
- Horizon uses only the platform, never the engine: it will live in its own repository.
|
||||
|
||||
[docs/layers.md](docs/layers.md) says where a new feature goes; CI checks the dependencies.
|
||||
- **Everything players run is Rust.** Python and Java are fine for dev tools and harness drivers in `tools/`, never
|
||||
for player-facing code.
|
||||
- **No game files in the repo.** Never commit game files, decompiled source or prepared resources (`.local/`):
|
||||
`tools/check_public_tree.py` rejects them (`git config core.hooksPath .githooks` runs it before every commit).
|
||||
The pre-push hook checks the full history reachable from the branches and tags being pushed. Run
|
||||
`python3 tools/check_public_tree.py --history` to audit the history of all local refs.
|
||||
|
||||
## Only original code, or code whose license allows it
|
||||
Never commit game files, decompiled source or prepared resources (`.local/`): `tools/check_public_tree.py` rejects
|
||||
them (`git config core.hooksPath .githooks` runs it before every commit).
|
||||
The pre-push hook checks the full history reachable from the branches and tags being pushed. Run
|
||||
`python3 tools/check_public_tree.py --history` to audit the history of all local refs.
|
||||
|
||||
Horizon is MIT. Its code is written from Minecraft 26.3 itself and from public documentation. Since 30 October 2026
|
||||
another project's source may also be read and used, **only when that project's license allows it**:
|
||||
## Only original code
|
||||
|
||||
- **Allowed:** MIT, MIT-0, BSD-2-Clause, BSD-3-Clause, 0BSD, ISC, zlib, Apache-2.0, Unlicense, and the CC0-1.0
|
||||
public-domain dedication. That code may be read, copied or adapted.
|
||||
- **Off limits, even to read:** GPL, LGPL (Iris), AGPL, MPL, EPL, Polyform (Sodium), the Creative Commons licenses
|
||||
(CC BY, CC BY-SA, CC BY-NC and the others; CC0 is a public-domain dedication, not one of them), custom or
|
||||
"source available" licenses, all rights reserved (OptiFine), and any project with no license or an unclear one.
|
||||
Don't read, copy, translate or paraphrase their source, and don't send code an AI tool wrote from it. Being able
|
||||
to download a mod or a pack does not give you the right to read its files.
|
||||
- **Java's own library is GPL too.** OpenJDK's source (`java.lang.Math`, `StrictMath`, `FdLibm`, `HashMap`, the
|
||||
sorts, `Double.toString`, HotSpot's intrinsics...) is GPL-2.0, so it is off limits like the rest. Reproduce Java's
|
||||
behaviour from its API documentation (the Javadoc) and from what a JVM returns, or from a permissive original such
|
||||
as Sun's fdlibm C sources (see [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)); see #6741.
|
||||
- **Check the license yourself.** Read the LICENSE file at the commit you use and the header of each file you take:
|
||||
some repositories mix licenses, and a file under another license is off limits. A license that changed: the one at
|
||||
your commit counts. In doubt, don't: ask in #contributors first.
|
||||
- **Say it in the pull request:** the project, a link to the commit, its license, and what you read or copied. A
|
||||
pull request that used another project's source without saying so is closed.
|
||||
- **Copied or adapted code** keeps its copyright line and license notice at the top of the file, and gets an entry
|
||||
in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md). Apache-2.0 code also keeps its NOTICE text and says what
|
||||
was changed.
|
||||
|
||||
User documentation and file formats are fine to read, and packs and mods are fine to run and observe, whatever their
|
||||
license. Shader packs are a clean-room rewrite of the pack format, produced from a written description of it (see
|
||||
#1561): the [specification and its provenance log](docs/cleanroom/README.md) are public. They carry no foreign
|
||||
source, and the rules above still apply to anything you read while working on them. A shader-pack pull request
|
||||
names its sources: the sections of that specification, the documentation pages and the packs it ran.
|
||||
|
||||
## Vendor libraries and Java mods
|
||||
|
||||
- **Upscalers and latency tools.** AMD FSR (MIT) may go in the repository, like any code under an allowed license.
|
||||
NVIDIA's DLSS, Reflex and any other library under an NVIDIA license may not: they ship only as an optional native mod
|
||||
that downloads NVIDIA's files itself, on the player's machine. No NVIDIA binaries, headers or SDK files in the
|
||||
repository.
|
||||
- **The JVM bridge** (running Java mods) is only ever a separate, optional download, never installed or on by
|
||||
default. The game may offer to turn it on when it finds a Java mod; the player decides. It is promoted out of beta
|
||||
only after MSPT and RAM benchmarks against the Java client with the same mods ([#13914](https://github.com/horizon-rust/horizon/issues/13914)).
|
||||
Horizon's code is written from Minecraft 26.3 itself and from public documentation, never from another mod, loader
|
||||
or renderer. Don't read, copy, translate or paraphrase the source of Iris, OptiFine, Sodium or any other project,
|
||||
and don't send code an AI tool wrote from it. Their user documentation and file formats are fine to read, and their
|
||||
packs and mods are fine to run and observe. Shader packs were removed on 24 October 2026 (#1561) because their code
|
||||
had been written from another project's source; they come back only as a clean-room rewrite from a written
|
||||
description of the pack format.
|
||||
|
||||
## Before asking for review
|
||||
|
||||
@@ -122,71 +70,25 @@ your change can affect. Without the vanilla data on your machine it lists those
|
||||
`--quick` skips the harnesses. It exits non-zero when something fails.
|
||||
|
||||
For the game workspace, Clippy checks all targets of the touched crates and their transitive workspace dependents,
|
||||
including examples. The dependency scope includes optional, platform, build and development dependencies. Tests run
|
||||
library, binary, integration and doc tests without building unrelated example executables. Shared Cargo
|
||||
including examples. The dependency scope includes optional, platform, build and development dependencies.
|
||||
Tests run library, binary, integration and doc tests without building unrelated example executables. Shared Cargo
|
||||
configuration and toolchain changes select the whole workspace; CI also keeps its workspace-wide checks.
|
||||
|
||||
### Translations
|
||||
|
||||
Most of Horizon's translations were written by machine and stay marked unreviewed until someone who speaks the
|
||||
language checks them. To report a wrong string or review your language, see [docs/translations.md](docs/translations.md)
|
||||
and #translations on Horizon's Discord. Never mark machine-written text as reviewed.
|
||||
|
||||
## Claim before you start
|
||||
|
||||
Work is tracked in GitHub issues, and an issue that is assigned is taken (so is one with the `in progress` label:
|
||||
claimed on Discord with Kira's `/claim`): pick another, or ask its holder in the thread. Before you start, comment
|
||||
**`/claim`** on the issue; you are assigned at once, no role needed. No issue for your work yet? Open one (a line is
|
||||
enough), then claim it. `/unclaim` gives it back. Issues labelled `tracker`, `proposal` or `not claimable` aren't
|
||||
claimed whole: claim one of the issues a tracker lists, or open one for the part you take.
|
||||
|
||||
A claim with no open pull request linking the issue (`Fixes #123` in the description, or a draft) is released after
|
||||
5 days, with a comment: open a draft early. You can hold 8 open issues at a time, not counting the ones your
|
||||
pull requests already fix. Agents claim the same way.
|
||||
|
||||
When your pull request changes the same functions as another open one, or closes the same issue, a bot comment names
|
||||
it (edited on every push, never repeated): talk to its author in the thread before you both finish the same work.
|
||||
|
||||
## Pull requests
|
||||
|
||||
- **Small.** One change per pull request, under about 500 lines of code where you can; split bigger work into
|
||||
pieces that each make sense alone. Small pull requests get reviewed and merged the same day. Bigger than that:
|
||||
[large pull requests](#large-pull-requests).
|
||||
pieces that each make sense alone. Small pull requests get reviewed and merged the same day.
|
||||
- **Fill in the template**: what and why, the vanilla reference, the pr_ready block, screenshots for anything you
|
||||
can see.
|
||||
- **Tick "Allow edits by maintainers".** When something small is left (a lint, a rebase, a nit) we push the fixup
|
||||
ourselves instead of sending it back to you; only design questions come back.
|
||||
- **Once we've pushed to your branch, merge main into it; don't rebase or force-push.** A rebase or force-push
|
||||
replaces our commits with yours and erases the fixes we added (it happened on #5188 and #5203). Tell your agent
|
||||
too: `git merge origin/main`, never `git rebase` or `git push --force` on a branch a maintainer has touched. If
|
||||
our fixes get erased anyway, we finish the work in our own pull request that keeps your commits and credits you.
|
||||
- **Tick its kind** in the template: `parity` (Horizon now does what vanilla does), `bug` (a crash or breakage),
|
||||
`perf`, `feature` (new for players), `extra` (Horizon-only, off by default), `tooling` or `docs`. A workflow sets
|
||||
that label, and area labels (`launcher`, `mobs`, `worldgen`, `rendering`...) from the paths you change.
|
||||
`label:parity` is the list of real progress toward vanilla.
|
||||
- **Release labels** (we set them if you can't): `feature` also puts it under "New" in the release notes,
|
||||
`skip-release` when players see no change (tooling, docs, tests), nothing for a fix. `release-now` is for crash
|
||||
fixes that shouldn't wait. pr_ready suggests one.
|
||||
|
||||
Who reviews and merges: the Horizon Team, on CI for ordinary pull requests; risky ones (saves, network, world
|
||||
generation, the launcher's updates) wait for a local proof first ([merging](docs/release-flow.md#merging)).
|
||||
- **Labels** (we set them if you can't): `feature` when players get something new (it appears under "New" in the
|
||||
release notes), `skip-release` when players see no change (tooling, docs, tests), nothing for a fix.
|
||||
`release-now` is for crash fixes that shouldn't wait. pr_ready suggests one.
|
||||
|
||||
Every merge to main is released automatically ([release flow](docs/release-flow.md)), so main always stays playable.
|
||||
How agents, checks, releases and signed updates keep this safe: [security](docs/security.md).
|
||||
|
||||
### Large pull requests
|
||||
|
||||
500 lines stays the default. A pull request that can't be split below it starts from a spec:
|
||||
|
||||
1. **Open an issue with the spec** before the code: what changes, the files it touches, the behaviour players and
|
||||
other code will see, and the tests or harnesses that prove it.
|
||||
2. **A maintainer approves the spec** in the issue. Code written before that may have to change or wait.
|
||||
3. **The pull request links the approved issue** (`Spec: #123` in the description) and stays within it; a change of
|
||||
plan goes back to the issue first.
|
||||
4. **An agent check compares the code with the spec**, run by the maintainers' agents: anything the spec doesn't
|
||||
cover, or that it promises and the code doesn't do, comes back to you.
|
||||
5. **Then the normal review**, as for any pull request.
|
||||
|
||||
## Parity checks on forks
|
||||
|
||||
The `verify` check (formatting, lints, tests) runs on every pull request. The `parity` check runs the affected
|
||||
@@ -196,5 +98,5 @@ new pushes, we add it again.
|
||||
|
||||
## Talk to us
|
||||
|
||||
[Discord](https://discord.gg/playhorizon) for questions and ideas, [issues](https://github.com/horizon-rust/horizon/issues)
|
||||
for bugs. To take something on, `/claim` its issue ([above](#claim-before-you-start)).
|
||||
[Discord](https://discord.gg/HcTeMZxe5E) for questions and ideas, [issues](https://github.com/ludovic111/horizon/issues)
|
||||
for bugs. If you want to take something on, say so in its issue so nobody else starts the same work.
|
||||
@@ -1,26 +1,15 @@
|
||||
[workspace]
|
||||
exclude = ["launcher", "crates/horizon-telemetry-server", "crates/horizon-mod-registry", "third_party/wgpu-hal", "third_party/naga", "third_party/libmimalloc-sys"]
|
||||
exclude = ["launcher", "crates/horizon-telemetry-server", "crates/horizon-mod-registry", "third_party/wgpu-hal"]
|
||||
members = [
|
||||
"crates/horizon-addresses",
|
||||
"crates/horizon-core",
|
||||
"crates/horizon-dualsense",
|
||||
"crates/horizon-narrator",
|
||||
"crates/horizon-threads",
|
||||
"crates/horizon-hdr",
|
||||
"crates/horizon-world",
|
||||
"crates/horizon-client",
|
||||
"crates/horizon-client-lib",
|
||||
"crates/horizon-client-core",
|
||||
"crates/horizon-client-input",
|
||||
"crates/horizon-client-render",
|
||||
"crates/horizon-cosmetics",
|
||||
"crates/horizon-command",
|
||||
"crates/horizon-items",
|
||||
"crates/horizon-server-files",
|
||||
"crates/horizon-anticheat",
|
||||
"crates/horizon-chat-filter",
|
||||
# The Model Context Protocol, shared by horizon-ctl, horizon-server and the launcher.
|
||||
"crates/horizon-mcp",
|
||||
"crates/horizon-server",
|
||||
"crates/horizon-bots",
|
||||
"crates/horizon-assets",
|
||||
@@ -28,34 +17,38 @@ members = [
|
||||
"crates/horizon-theme",
|
||||
"crates/horizon-prepare",
|
||||
"crates/horizon-telemetry",
|
||||
"crates/horizon-system",
|
||||
"crates/horizon-platform",
|
||||
"crates/horizon-hooks",
|
||||
"crates/horizon-game",
|
||||
"crates/horizon-official",
|
||||
"crates/horizon-heartbeat",
|
||||
"crates/horizon-bench",
|
||||
"crates/horizon-friends",
|
||||
"crates/horizon-relay",
|
||||
"crates/horizon-mod-sdk",
|
||||
"crates/horizon-mods",
|
||||
"crates/horizon-mod-api-gen",
|
||||
"crates/horizon-mod-api-gen/dispatch-tests",
|
||||
"crates/horizon-mods/tests/guest",
|
||||
"crates/horizon-mods/tests/ui_guest",
|
||||
"crates/cargo-horizon-mod",
|
||||
"crates/horizon-port-pack",
|
||||
"crates/horizon-shaders",
|
||||
"crates/horizon-optifine",
|
||||
"crates/horizon-polytone",
|
||||
"crates/horizon-shader-api",
|
||||
"crates/horizon-release-sign",
|
||||
"crates/horizon-mod-deps",
|
||||
"crates/horizon-mod-sdk/examples/coords-hud",
|
||||
"crates/horizon-mod-sdk/examples/coords-hud-lua",
|
||||
"crates/horizon-mod-sdk/examples/predator-missile",
|
||||
"crates/horizon-mod-sdk/examples/welcome",
|
||||
"crates/horizon-mod-sdk/examples/beacons",
|
||||
"mods/official/fps-overlay",
|
||||
"mods/official/keystrokes",
|
||||
"mods/official/far-view",
|
||||
"mods/official/minimap",
|
||||
"mods/official/zoom",
|
||||
"xtask",
|
||||
"mods/official/recipes",
|
||||
"crates/horizon-mod-lua",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
[workspace.package]
|
||||
edition = "2024"
|
||||
license = "MIT"
|
||||
rust-version = "1.95"
|
||||
rust-version = "1.85"
|
||||
|
||||
# Ports mirror vanilla's Java signatures, index loops and nested generic types
|
||||
# one to one so they can be checked against the decompiled sources.
|
||||
@@ -68,42 +61,16 @@ large_enum_variant = "allow"
|
||||
# wgpu-hal 30.0.1 with gfx-rs/wgpu#10124: wgpu 30 creates a Vulkan descriptor
|
||||
# pool with no pool sizes while it creates the device, which Vulkan allows only
|
||||
# since 1.3.215, and Intel's Windows driver for 6th-10th gen iGPUs (HD 520/530,
|
||||
# UHD 620/630) crashes on it with an access violation (#746). It also fixes the
|
||||
# Metal backend's lookup of the CoreGraphics HDR colour space names, which handed
|
||||
# CoreGraphics a symbol's address as the string and crashed HDR output on macOS.
|
||||
# And gfx-rs/wgpu#10714: on Windows, Vulkan waits for the acquire fence only in
|
||||
# FIFO (VSync), where it was meant to pace frames; with VSync off it made every
|
||||
# frame wait for the GPU to finish the one before (#4604).
|
||||
# Drop this and the folder once a wgpu release has these fixes.
|
||||
# UHD 620/630) crashes on it with an access violation (#746). Drop this and the
|
||||
# folder once a wgpu release has the fix.
|
||||
[patch.crates-io]
|
||||
wgpu-hal = { path = "third_party/wgpu-hal" }
|
||||
# naga 30.0.1, with the fixes to its GLSL frontend that shader packs need (THIRD_PARTY_NOTICES.md).
|
||||
naga = { path = "third_party/naga" }
|
||||
# libmimalloc-sys 0.1.49 whose mimalloc v3 counts bits without POPCNT when MSVC builds it: the
|
||||
# game died before main on CPUs without it (Core 2, #7264; THIRD_PARTY_NOTICES.md). Drop this and
|
||||
# the folder once a libmimalloc-sys release has microsoft/mimalloc#1291's fix.
|
||||
libmimalloc-sys = { path = "third_party/libmimalloc-sys" }
|
||||
|
||||
# Line tables keep file:line in backtraces; full debug info made every
|
||||
# example and test binary hundreds of megabytes and slow to link.
|
||||
[profile.dev]
|
||||
debug = "line-tables-only"
|
||||
|
||||
# The native mod API is generated by a build script that parses every file of game/ with syn on
|
||||
# each gameplay edit; unoptimized that took ~6 s of every rebuild, optimized ~1.5 s.
|
||||
[profile.dev.package.horizon-mod-api-gen]
|
||||
opt-level = 3
|
||||
[profile.dev.package.syn]
|
||||
opt-level = 3
|
||||
[profile.dev.package.proc-macro2]
|
||||
opt-level = 3
|
||||
[profile.release.package.horizon-mod-api-gen]
|
||||
opt-level = 3
|
||||
[profile.release.package.syn]
|
||||
opt-level = 3
|
||||
[profile.release.package.proc-macro2]
|
||||
opt-level = 3
|
||||
|
||||
[profile.release]
|
||||
lto = "thin"
|
||||
codegen-units = 1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 Ludovic Marie and the Horizon contributors
|
||||
Copyright (c) 2026 Ludovic
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -1,169 +1,171 @@
|
||||
<p align="center">
|
||||
<img src="docs/media/banner.webp" alt="Horizon: the game you know, rebuilt in Rust" width="100%">
|
||||
<img src="docs/media/banner.webp" alt="Horizon: Minecraft: Java Edition 26.3, rewritten in Rust and checked against vanilla by 281 differential harnesses" width="100%">
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/ludovic111/horizon/actions/workflows/ci.yml"><img src="https://github.com/ludovic111/horizon/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
||||
<img src="https://img.shields.io/badge/Minecraft-Java%2026.3-5D9C3F" alt="Minecraft Java 26.3">
|
||||
<img src="https://img.shields.io/badge/Rust-stable-B7410E?logo=rust&logoColor=white" alt="Rust">
|
||||
<img src="https://img.shields.io/badge/vanilla%20parity-100%25-F0795A" alt="Vanilla parity 100%">
|
||||
<img src="https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20Windows-2A2470" alt="Linux, macOS and Windows">
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-3B2F7E" alt="MIT license"></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://playhorizon.dev"><b>Website</b></a> ·
|
||||
<a href="#download"><b>Download</b></a> ·
|
||||
<a href="https://playhorizon.dev/docs/"><b>Docs</b></a> ·
|
||||
<a href="https://discord.gg/playhorizon"><b>Discord</b></a> ·
|
||||
<a href="https://playhorizon.dev/docs/"><b>Documentation</b></a> ·
|
||||
<a href="https://github.com/ludovic111/horizon/releases"><b>Release notes</b></a> ·
|
||||
<a href="ROADMAP.md"><b>Roadmap</b></a> ·
|
||||
<a href="#project-status"><b>Project status</b></a> ·
|
||||
<a href="#contributing"><b>Contributing</b></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="#project-status"><img src="https://img.shields.io/badge/player--visible%20gaps-0%20open-F0795A" alt="Player-visible gaps open"></a>
|
||||
</p>
|
||||
|
||||
# Horizon
|
||||
|
||||
**Minecraft: Java Edition 26.3, rewritten in Rust.** Your worlds, the same rules and the same terrain as the Java game, checked against it by hundreds of differential tests, in one native program with no Java. Free, open source (MIT) and unofficial: you play it with your own copy of Java Edition.
|
||||
Horizon is Minecraft: Java Edition 26.3 rewritten in Rust: a native game that reads the same worlds, follows the same rules and generates the same terrain as the Java game, and is checked against it by 281 differential harnesses. You play it through a small launcher, on the files from your own copy of Minecraft. It is free, open source and unofficial.
|
||||
|
||||
<p align="center">
|
||||
<img src="docs/media/readme/valley.webp" alt="A river valley with a plains village, savanna hills and a cherry grove, seen from above with a long view distance" width="100%">
|
||||
</p>
|
||||
|
||||
## What works today
|
||||
|
||||
Everything below is in the current release.
|
||||
|
||||
- **The game.** Survival, creative, hardcore and spectator; vanilla world generation in all three dimensions, mobs, villagers, raids, redstone, every command, the HUD and the recipe book. Vanilla saves open as they are, and worlds from 1.8 to 26.2 are upgraded.
|
||||
- **Multiplayer.** Join vanilla and Horizon servers (online mode included), open a world to LAN, or invite friends with a code from the launcher's Home page.
|
||||
- **Graphics.** Distant terrain up to 1,024 chunks, graphics presets, HDR and controllers, all off by default where they would change the vanilla look ([settings](https://playhorizon.dev/docs/settings)).
|
||||
- **Packs.** Resource packs, data packs and shader packs ([below](#mods-and-shader-packs)).
|
||||
- **Mods.** Content mods and native Rust mods, installed from the launcher ([below](#mods-and-shader-packs)).
|
||||
- **Servers.** Host one from the launcher, or run `horizon-server` on a VPS ([below](#host-a-server)).
|
||||
- **The launcher.** It installs and updates the game, prepares its files from your copy of Minecraft, and updates itself.
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/media/readme/sunset.webp" alt="Sunset behind a cherry grove on a hill, with a river below"></td>
|
||||
<td width="50%"><img src="docs/media/readme/nether.webp" alt="A crimson forest in the Nether, with a piglin among the fungi"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/media/readme/survival.webp" alt="Survival in a village square: two villagers, flowers, the hotbar, health and hunger"></td>
|
||||
<td width="50%"><img src="docs/media/readme/multiplayer.webp" alt="Two players in a LAN world: the other player's name tag and the player list"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<sub>Nightly 2026-11-05 on a Mac mini (Apple M4 Pro, Metal): vanilla's textures, no mods or shader packs, render distance 32 with distant terrain on.</sub>
|
||||
|
||||
## Performance
|
||||
|
||||
**Horizon draws more frames per second than Java Edition, and loads faster, on the same machine, world and path.** `tools/perf_bench.py` runs each game in turn, from a fresh world (seed 1234), waiting for the terrain and then flying it over a village, a forest, an ocean and a mountain. Measured on 2026-10-29/30 on an idle Windows 11 machine (Ryzen 7 9800X3D, RTX 5080), Horizon v0.2.97 as the launcher installs it, 1280x720 in a window, VSync off, three games per figure. Frames per second, mean of the four scenes, with the slowest 1% of frames in brackets:
|
||||
|
||||
| Render distance | Horizon v0.2.97 | Vanilla 26.3 | Vanilla + mods |
|
||||
| --- | --- | --- | --- |
|
||||
| 8 chunks | 3,289 (1,327) | 2,437 (640) | 2,375 (709) |
|
||||
| 16 chunks | 2,074 (598) | 1,661 (375) | 1,586 (432) |
|
||||
| 32 chunks | 1,207 (333) | 1,031 (176) | 879 (264) |
|
||||
|
||||
"Vanilla + mods" is Sodium, Lithium, FerriteCore and ImmediatelyFast. Horizon reaches the title screen in 2.9–3.2 s against vanilla's 7.5–7.7 s (the modded client's 10.8–11.1 s), loads a scene's chunks 2.9–3.8 times faster, and playing holds a steady working set of 1.1–1.7 GB against 1.9–2.9 GB. Every scene with its confidence interval and the run's load log: [the 2026-10-29 reports](benchmarks/perf/windows-9800x3d-5080-2026-10-29.md). Method, and how to measure your own machine: [docs/benchmark.md](docs/benchmark.md). [playhorizon.dev/benchmarks](https://playhorizon.dev/benchmarks) puts these runs beside a 2016 laptop, a Mac mini and a gaming desktop.
|
||||
> Not an official Minecraft product. Not approved by or associated with Mojang or Microsoft. Horizon contains no Minecraft code, assets or data: you need your own legally obtained copy of Minecraft: Java Edition 26.3.
|
||||
|
||||
## Download
|
||||
|
||||
Get **the Horizon launcher** from [playhorizon.dev](https://playhorizon.dev), or from [the launcher releases](https://github.com/horizon-rust/horizon/releases?q=launcher&expanded=true):
|
||||
Horizon is installed through **the Horizon launcher**. Get it from [playhorizon.dev](https://playhorizon.dev) (the Download button picks your system) or from [the launcher releases](https://github.com/ludovic111/horizon/releases?q=launcher-v&expanded=true), for Linux x86-64, macOS on Apple Silicon or Windows x64. The launcher installs and updates the game, prepares its files from your own copy of Minecraft, and updates itself.
|
||||
|
||||
| Platform | File | Needs |
|
||||
| --- | --- | --- |
|
||||
| Windows x64 | `horizon-launcher-setup.exe` | Windows 10 or 11, a GPU with Vulkan or DirectX 12 |
|
||||
| Windows on Arm | `horizon-launcher-setup-arm64.exe` | Windows 11 on Arm |
|
||||
| macOS, Apple Silicon | `horizon-launcher-macos-arm64.dmg` | macOS 12 or later |
|
||||
| macOS, Intel | `horizon-launcher-macos-x64.dmg` | macOS 12 or later |
|
||||
| Linux x86-64 | `horizon-launcher-linux-x86_64.AppImage` or `.tar.gz` | a glibc distribution, X11 or Wayland, a GPU with Vulkan or OpenGL 3.3 |
|
||||
|
||||
**You also need a Microsoft account that owns Minecraft: Java Edition.** You sign in with it in the launcher, which plays only with an account that owns the game ([why](docs/microsoft-account.md)). Horizon contains no Minecraft code or assets: an existing install (official launcher, Prism, MultiMC...) is reused, and without one the launcher downloads 26.3 from Mojang for your account. Step by step: [Install and first launch](https://playhorizon.dev/docs/install).
|
||||
**You need** Minecraft: Java Edition 26.3, played once (the official launcher, Prism, MultiMC and other launchers all work); a Java 25 runtime, for the one-time preparation; and a GPU with Vulkan on Linux and Windows, or any Apple Silicon Mac. Step by step, with macOS's first-open prompt and the first launch: [Install and first launch](https://playhorizon.dev/docs/install).
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/media/readme/launcher-home.webp" alt="The launcher's Home page: the Horizon instance, Play, the version picker, the friend invite field, screenshots and the patch log"></td>
|
||||
<td width="50%"><img src="docs/media/readme/launcher-mods.webp" alt="The launcher's Mods page: Horizon's mod registry with Zoom selected, and tabs for modpacks, resource packs, shader packs and data packs"></td>
|
||||
<td width="50%"><img src="docs/media/launcher-play.webp" alt="The launcher's Play page: a version ready to play, its summary, Client and Server, the version picker and Play"></td>
|
||||
<td width="50%"><img src="docs/media/launcher-patch-notes.webp" alt="The launcher's Patch notes page"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Mods and shader packs
|
||||
## What works today
|
||||
|
||||
- **Content mods** (`.hmod`): blocks, items, recipes, loot, models and textures, with no code.
|
||||
- **Native mods** (`.hnmod`): Rust that the launcher compiles into the game for you, with nothing to install.
|
||||
- **Java mods** (Fabric, NeoForge, Forge) don't run: Horizon has no Java. The launcher carries over the data and assets inside their jars, and imports modpacks (`.mrpack`, CurseForge zips, Prism instances) the same way ([modpacks](https://playhorizon.dev/docs/modpacks)).
|
||||
- **Shader packs**: Iris/OptiFine-format packs (`shaders/` folders) and Horizon's own WGSL packs, under Video Settings → Shader Packs ([pack format](docs/shaders.md)).
|
||||
The [documentation](https://playhorizon.dev/docs/) covers each of these.
|
||||
|
||||
Mods are off by default: a fresh install plays exactly like vanilla 26.3. The launcher's Mods page browses Horizon's registry and Modrinth. [Mods](https://playhorizon.dev/docs/mods) · [make a mod](docs/mods.md).
|
||||
- **The game:** singleplayer with vanilla's world generation, mobs, villagers, raids, redstone, every command, the HUD and the recipe book, on saves in vanilla's format. Worlds from 1.8 to 26.2 are upgraded as vanilla does. [Status table](#project-status).
|
||||
- **Horizon's own extras:** new menus (vanilla's are one setting away), graphics presets, distant terrain up to 1024 chunks, controller support, optional zoom, minimap and more, all off by default where they would change the vanilla look. See [Settings](https://playhorizon.dev/docs/settings).
|
||||
- **Resource packs and data packs:** resource packs work, and data packs load functions, predicates and item modifiers.
|
||||
- **Playing with others:** invite friends from the pause menu's Friends button with a code, Open to LAN, and joining offline-mode servers. Horizon cannot sign in to a Microsoft account yet, so it cannot join servers that check accounts. See [Multiplayer](https://playhorizon.dev/docs/multiplayer).
|
||||
- **Mods:** Horizon has its own mod system (Rust compiled to WebAssembly). Java mod jars do not run. See [Mods and data packs](https://playhorizon.dev/docs/mods).
|
||||
|
||||
Screenshots, captured in the Rust client itself with vanilla assets and no mods or shaders:
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2"><img src="docs/media/sunset.webp" alt="Sunset over a savanna river valley and a plains village"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/media/survival.webp" alt="Survival at dusk: a zombie walks up, with the hotbar, health, hunger and experience"></td>
|
||||
<td width="50%"><img src="docs/media/settings.webp" alt="Vanilla's Video Settings screen with Horizon's own buttons at the top: Horizon Graphics and Advanced Graphics"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="50%"><img src="docs/media/village.webp" alt="A plains village among savanna hills, with farms, villagers and an iron golem"></td>
|
||||
<td width="50%"><img src="docs/media/nether.webp" alt="A crimson forest in the Nether with a zombified piglin"></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Host a server
|
||||
|
||||
The launcher's **Servers** page creates, starts, backs up and updates a server, and invites friends. On a VPS, `horizon-server` installs with one command, needs no Java, and takes vanilla 26.3 and Horizon players alike. [Host a server](https://playhorizon.dev/docs/hosting) ([reference](docs/hosting.md)).
|
||||
The launcher's **Servers** page creates, starts, backs up and updates a Horizon server with buttons, and invites friends over Tailscale. On a VPS, `horizon-server` installs with one command and runs without Java. Guide: [Host a server](https://playhorizon.dev/docs/hosting) ([reference](docs/hosting.md)).
|
||||
|
||||
## Modpacks
|
||||
|
||||
The launcher's **Modpacks** page imports a Modrinth or CurseForge pack, shows which of its mods Horizon can carry over, and plays the ones it can as their own profile. Today that means content mods made of data and assets; mods with Java code are not ported yet. See [Modpacks](https://playhorizon.dev/docs/modpacks).
|
||||
|
||||
## Agent control
|
||||
|
||||
AI agents and scripts can play Horizon. `horizon-ctl`, shipped with the game, reads its state as JSON and acts like a player; `horizon-ctl mcp` serves the same commands over MCP.
|
||||
AI agents and scripts can play Horizon. `horizon-ctl`, shipped beside the game in every release folder, is a command line that reads the game as JSON and acts like a player; `horizon-ctl mcp` serves the same commands as an MCP server (one tool per command, screenshots returned as images).
|
||||
|
||||
```sh
|
||||
horizon-ctl launch --world Survival --seed 5 --wait # finds the version the launcher installed
|
||||
horizon-ctl state # position, health, food, target, screen...
|
||||
horizon-ctl find-block birch_log # the nearest logs
|
||||
horizon-ctl goto -0.5 65 -2.5 --near 2.5 # walks there along a path
|
||||
horizon-ctl break -1 65 -3 # mines it; replies with the drops
|
||||
horizon-ctl open-inventory && horizon-ctl click-slot 0 # menus: slots, buttons by label, text fields
|
||||
```
|
||||
|
||||
`horizon-ctl help` lists every command. [Agent control](docs/native-client.md#agent-control-horizon-ctl-and-mcp).
|
||||
Commands block until the action is done and reply with what happened; errors are JSON with distinct exit codes, `horizon-ctl help` lists every command and `horizon-ctl COMMAND --help` explains one with examples. It talks to the game over a Unix socket on Linux and macOS and over a token-protected localhost port on Windows. See [Agent control in the native client guide](docs/native-client.md#agent-control-horizon-ctl-and-mcp).
|
||||
|
||||
## Build from source
|
||||
|
||||
Needs Rust 1.90+, Python 3.10+, JDK 25, and on Linux `libasound2-dev libudev-dev`. `horizon-prepare` builds the game's resources from **your own copy** of Java Edition 26.3 (checked against `research-lock.json`) and never downloads it:
|
||||
For developers. Requirements: Rust 1.90 or newer, Python 3.10 or newer, JDK 25, and on Linux the ALSA and udev development headers (`libasound2-dev libudev-dev` on Debian and Ubuntu). Development and the vanilla harnesses run on Linux.
|
||||
|
||||
1. **Client:** play 26.3 once in the official launcher. Horizon reads `~/.minecraft` (or `--minecraft-dir` / `HORIZON_MINECRAFT_DIR`).
|
||||
2. **Server jar:** the 26.3 server jar (`downloads.server.url` in `versions/26.3/26.3.json`), passed once with `--server-jar` or `HORIZON_SERVER_JAR`.
|
||||
Horizon contains no game files and never downloads them. It builds its resources from **your own copy** of Minecraft: Java Edition 26.3, verified against the checksums in `research-lock.json`:
|
||||
|
||||
1. **Client:** install Java Edition with the official launcher and play 26.3 once. Horizon reads `versions/26.3/`, `libraries/` and `assets/` from the launcher's game directory (`~/.minecraft` on Linux). If yours lives elsewhere, pass `--minecraft-dir` or set `HORIZON_MINECRAFT_DIR`.
|
||||
2. **Server jar:** the 26.3 server jar, from the `downloads.server.url` in your launcher's `versions/26.3/26.3.json` (or [minecraft.net/download/server](https://www.minecraft.net/en-us/download/server) while 26.3 is the current release). Pass it with `--server-jar` or set `HORIZON_SERVER_JAR`. It is only needed the first time.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/horizon-rust/horizon.git
|
||||
git clone https://github.com/ludovic111/horizon.git
|
||||
cd horizon
|
||||
cargo run --release -p horizon-prepare -- --prepare --server-jar ~/Downloads/server.jar # needs JDK 25
|
||||
cargo run --release -p horizon-prepare -- sounds # optional: sounds from your launcher install
|
||||
cargo run --release -p horizon-client
|
||||
```
|
||||
|
||||
Prepared files land in the gitignored `.local/`: never commit or share them. Options, controls and architecture: [the native client guide](docs/native-client.md); all developer docs: [docs/README.md](docs/README.md).
|
||||
Everything prepared lands in the gitignored `.local/`. It is derived from the game: never commit it or share it.
|
||||
|
||||
The client starts on the title screen. Command-line options (`--world`, `--seed`, `--creative`, `--render-distance`, `--dedicated`), controls, scripting through `horizon-ctl` and the architecture are described in [the native client guide](docs/native-client.md). The rest of the developer documentation is indexed in [docs/README.md](docs/README.md), including [the parity workflow](docs/parity-workflow.md).
|
||||
|
||||
## Roadmap
|
||||
|
||||
What is being done now, what comes next and where you can help, in plain words and in technical detail: [ROADMAP.md](ROADMAP.md). [playhorizon.dev/hub](https://playhorizon.dev/hub) shows it with the work board, the journal of what shipped and how to help.
|
||||
|
||||
## Contributing
|
||||
|
||||
Issues and pull requests are welcome: read [CONTRIBUTING.md](CONTRIBUTING.md) (vanilla first, small pull requests), and see [ROADMAP.md](ROADMAP.md) or [playhorizon.dev/hub](https://playhorizon.dev/hub) for what's next. Questions: [Discord](https://discord.gg/playhorizon). Before a pull request, run the self-check and paste its output:
|
||||
Issues and pull requests are welcome: see [CONTRIBUTING.md](CONTRIBUTING.md) for how we work (vanilla first, small pull requests, labels), or [the contributing guide](https://playhorizon.dev/docs/contributing) on the site. Questions and ideas: [Discord](https://discord.gg/HcTeMZxe5E). Before opening a pull request, run the self-check and paste the block it prints:
|
||||
|
||||
```sh
|
||||
git config core.hooksPath .githooks
|
||||
python3 tools/pr_ready.py
|
||||
```
|
||||
|
||||
It runs rustfmt, clippy, the touched crates' tests, the Python tests, the public-tree check and the vanilla harnesses your change affects. Never commit game files, decompiled source or prepared resources.
|
||||
It runs rustfmt, clippy with warnings denied, the tests of the crates you touched, the Python tests, the public-tree check, and the vanilla harnesses your change can affect. CI runs the same checks on GitHub's Linux runners; the vanilla harnesses need the game, which Horizon never downloads, so they run on a maintainer's computer holding their own copy. Never commit game files, decompiled source or prepared resources: `tools/check_public_tree.py` rejects them, and tracked Java is allowed only under the project's own `dev/horizonlab` namespace.
|
||||
|
||||
## Project status
|
||||
|
||||
**Player-visible gaps: 0 open** of the 833 the [port ledger](tools/port_ledger.py) found, reading every vanilla 26.3 method against Horizon's code: vanilla behaviour a player would notice that Horizon doesn't have yet. By area: Animals [0](https://github.com/horizon-rust/horizon/issues/3512); Monsters and bosses [0](https://github.com/horizon-rust/horizon/issues/3513); Entities, projectiles, vehicles and decorations [0](https://github.com/horizon-rust/horizon/issues/3514); Items, enchantments and inventories [0](https://github.com/horizon-rust/horizon/issues/3515); Blocks, redstone and fluids [0](https://github.com/horizon-rust/horizon/issues/3516); World, world generation and saves [0](https://github.com/horizon-rust/horizon/issues/3517); Screens, HUD and client packets [0](https://github.com/horizon-rust/horizon/issues/3518); Entity and block rendering, models [0](https://github.com/horizon-rust/horizon/issues/3519); Server and players on the server [0](https://github.com/horizon-rust/horizon/issues/3520); Mob AI, villagers and raids [0](https://github.com/horizon-rust/horizon/issues/3521). This number goes down as gaps close (`tools/parity_gaps.py`); the table below says what the harnesses compare.
|
||||
The table below is the project's own audit of each subsystem. Every subsystem now matches vanilla in every harness that compares it. 100% means 100% of what the harnesses compare, not proof that nothing else differs. The remaining known differences are listed below.
|
||||
|
||||
The table is the project's own audit of what the harnesses compare, subsystem by subsystem: a score says how much of that subsystem the harnesses cover and pass, not that nothing else differs from vanilla. What players still run into: [known issues](docs/known-issues.md).
|
||||
### Java parity: 100%
|
||||
|
||||
### What the harnesses compare
|
||||
|
||||
Scores: 0 (absent), 0.25 (started), 0.5 (playable, major features missing), 0.75 (mostly complete) or 1 (its harnesses cover the subsystem and pass). Last audited 2026-10-13: the harnesses pass on Linux and macOS. The [port ledger](tools/port_ledger.py) adds a method-by-method view of what is ported.
|
||||
Each subsystem scores 0 (absent), 0.25 (started, not playable), 0.5 (playable,
|
||||
major vanilla features missing), 0.75 (playable, mostly complete) or 1 (complete
|
||||
and verified against vanilla by differential tests). The percentage is the
|
||||
average; `tests/test_parity.py` keeps it in sync with this table. Last audited
|
||||
2026-10-13 against the harness results: all 281 harnesses pass on Linux, each
|
||||
rerun whenever one of its inputs changed, and the Mac mini now runs every one of
|
||||
them too (Rust uses Java's own float maths on each platform).
|
||||
|
||||
| Subsystem | Score | Main gaps |
|
||||
| --- | ---: | --- |
|
||||
| Window, input and game loop | 1 | None: game loop, options, camera, auto-jump, toggle sprint/sneak and frame limiter match |
|
||||
| Assets and resources | 1 | None: item models match over 196,290 stacks; the resource pack screen over 3,000 sessions |
|
||||
| Network protocol and multiplayer | 1 | None: joins vanilla servers; the dedicated server matches vanilla's files, login, configuration, play and command tree; LAN discovery over 462 cases (offline mode only) |
|
||||
| Window, input and game loop | 1 | None: the game loop, options, camera, auto-jump, toggle sprint/sneak, local input and the frame limiter match vanilla |
|
||||
| Assets and resources | 1 | None: item models match vanilla over 196,290 stacks and the client draws every item through them; the resource pack screen matches vanilla's drawing over 3,000 sessions of clicks, scrolling and searching, its incompatibility confirmation included |
|
||||
| Network protocol and multiplayer | 1 | None: joins vanilla servers; the dedicated server (`--dedicated`) matches vanilla's files, status ping, login, configuration, play, chunks, chat, recipes, advancements and command tree, a client built from vanilla's packet code joins it, Horizon joins a vanilla server, and LAN discovery matches over 462 cases (offline mode only) |
|
||||
| Chunk storage and palettes | 1 | None: client and saves share paletted containers, identical to vanilla over 266 scenarios |
|
||||
| Section meshing | 1 | None: 112 scenes and over a million quads identical to vanilla |
|
||||
| Rendering | 1 | None: entity models, block entity renderers (407 cases) and animations (296), HUD overlays (2,200 states), the recipe book (600), player list, subtitles and world border match |
|
||||
| Rendering | 1 | None: entity models, block entity renderers (407 cases, End portals, gateways and the loom's banner preview included) and their animations (296 cases, End gateway beams included), the HUD overlays (2,200 states), the recipe book (600 states), the player list, subtitles and the world border match vanilla |
|
||||
| Lighting | 1 | None: saved and relit light matches vanilla, slabs and stairs included |
|
||||
| World generation | 1 | None: 2,352 whole chunks over 225 structure sites, in all three dimensions, identical to vanilla |
|
||||
| Region files and saves | 1 | None: saves round-trip with vanilla; worlds from 1.8 to 26.2 upgrade as vanilla's DataFixers do |
|
||||
| Entities and physics | 1 | None: attributes, spawn rules, natural spawning (15,500 cases), raids and patrols (1,900), `finalizeSpawn` (24,000) and mob AI (92 scenarios) match |
|
||||
| Interaction and inventory | 1 | None: menu clicks over 8,000 sequences; recipe book placement (6,000), buttons (1,200), saved book (1,500), loom and crafter screens (1,600) |
|
||||
| Menus, HUD and chat | 1 | None: every command (758 over 39,685 inputs), scoreboards (81,000 operations), the player list (872,000 draw calls), chat and its suggestions (3,000 sessions) match |
|
||||
| Region files and saves | 1 | None: saves round-trip with vanilla, and worlds from 1.8 to 26.2 upgrade as vanilla's DataFixers do, superflat worlds included; old options.txt and hotbar.nbt files are upgraded too |
|
||||
| Entities and physics | 1 | None: attributes, dimensions, death loot, spawn rules, natural spawning (15,500 cases), raids and patrols (1,900 cases), spawned mobs' gear, enchantments and state (`finalizeSpawn`, 24,000 cases) and mob AI (92 scenarios: villager breeding and gossip, the warden, ghastlings and copper golems included) match vanilla |
|
||||
| Interaction and inventory | 1 | None: menu clicks match over 8,000 click sequences, the loom and the crafter included; recipe book placement (6,000 cases), its buttons (1,200), the saved book (1,500) and the loom and crafter screens (1,600) match vanilla |
|
||||
| Menus, HUD and chat | 1 | None: every command runs as vanilla (758 commands over 39,685 parsed inputs), scoreboards and teams match (81,000 operations), the player list matches over 872,000 draw calls with heads drawn from players' skins (authlib's textures, SkinManager's lookup, legacy skin conversion), and the chat matches focused and scrolled; the resource pack screen (selection over 4,000 cases, drawing and its incompatibility confirmation over 3,000 sessions) and the chat input with its command suggestions, usage lines, Tab completion and history (3,000 sessions on vanilla's client command tree) match vanilla |
|
||||
| Audio | 1 | None: the sound engine, sound events, music, situational music, ambience and subtitles match vanilla |
|
||||
| Block behaviours and ticking | 1 | None: block updates, random ticks, redstone, dispensers (6,000 cases), crafters (4,000), container spills (4,000), copper golems and the sculk family (435 scenarios) match |
|
||||
| Block behaviours and ticking | 1 | None: block updates, random ticks, redstone, dispensers (6,000 cases), crafters (4,000 crafts), block entity removal (containers spill, 4,000 cases), copper golem chest sorting and the sculk family (435 scenarios: shrieker warnings and warden summoning included) match vanilla |
|
||||
|
||||
### Known issues
|
||||
|
||||
Horizon can't sign in to a Microsoft account yet, so it can't join online-mode servers (it joins offline-mode ones); skins served over https show the default skin unless already cached; pack icons show the unknown-pack texture in game; the creative hotbar keys (C/X) aren't wired to the hotbar loader; item tooltips lack attribute lines.
|
||||
|
||||
## Licence
|
||||
|
||||
[MIT](LICENSE), for the project's original work; dependencies keep their own licences ([notices](THIRD_PARTY_NOTICES.md)). Horizon is made by [Ludovic Marie](https://lu4ovic.com) ([@ludovic111](https://github.com/ludovic111)) and [its contributors](https://github.com/horizon-rust/horizon/graphs/contributors); support it on [GitHub Sponsors](https://github.com/sponsors/ludovic111).
|
||||
[MIT](LICENSE), for the project's original work only. Dependencies keep their own licences. Minecraft is a trademark of Mojang Synergies AB; Minecraft code and assets belong to Mojang and Microsoft and are covered by the [Minecraft EULA](https://www.minecraft.net/en-us/eula). Decompiled game source and prepared resources stay on your machine and are never published.
|
||||
|
||||
NOT AN OFFICIAL MINECRAFT PRODUCT. NOT APPROVED BY OR ASSOCIATED WITH MOJANG OR MICROSOFT. Minecraft is a trademark of Mojang Synergies AB; its code and assets belong to Mojang and Microsoft under the [Minecraft EULA](https://www.minecraft.net/en-us/eula).
|
||||
Third-party credits and licenses: [Third-party notices](THIRD_PARTY_NOTICES.md).
|
||||
|
||||
## Author
|
||||
|
||||
Made by [Ludovic Marie](https://lu4ovic.com) ([@ludovic111](https://github.com/ludovic111)).
|
||||
@@ -1,102 +1,11 @@
|
||||
# Third-party notices
|
||||
|
||||
## Code removed for its license
|
||||
|
||||
Horizon once shipped three pieces of code under MIT that came from projects whose licenses don't allow that. All
|
||||
three are gone from main. They are listed here for anyone who holds an older commit, tag or release: in those
|
||||
versions, that code is not covered by Horizon's MIT license. It stays under its authors' copyright and its original
|
||||
license.
|
||||
|
||||
- **Shader packs written from Iris's source.** `crates/horizon-shaderpack` and the render stages that used it were
|
||||
written from the source of [Iris](https://github.com/IrisShaders/Iris) (LGPL-3.0, copyright the Iris contributors).
|
||||
They were added from 15 October 2026 (`b22583d057`), shipped in the game releases `v2026.10.16.02` to `v0.2.46`,
|
||||
and were removed on 24 October 2026 ([#1561](https://github.com/horizon-rust/horizon/pull/1561)) after a developer
|
||||
of Iris showed us. Shader packs came back in `crates/horizon-shaders`, first written from a description of the
|
||||
pack format.
|
||||
- **Math functions translated from OpenJDK.** In `crates/horizon-core/src/jmath.rs`, `fdlibm::{log, log10, cbrt,
|
||||
hypot}` were translated from OpenJDK's `java/lang/FdLibm.java` and `round_f32` from its `java/lang/Math.java`
|
||||
(GPL-2.0 with the Classpath Exception), and `aarch64::{sin, cos}` from HotSpot's `macroAssembler_aarch64_trig.cpp`
|
||||
(GPL-2.0); copyright Oracle and/or its affiliates, and Cavium for that file. The `fdlibm` and `aarch64` functions
|
||||
were added on 13 October 2026 (`558d140fca`, first released in `v2026.10.13`). `round_f32` was added on 14 October
|
||||
2026 as `java_round` in `crates/horizon-client/src/mipmap.rs` (`95db0fce9d`) and moved into `jmath.rs` on 3
|
||||
November ([#7770](https://github.com/horizon-rust/horizon/pull/7770)). All of them were replaced in
|
||||
[#11944](https://github.com/horizon-rust/horizon/pull/11944) by code written without OpenJDK's sources, from Sun's
|
||||
fdlibm C sources, the Java SE API documentation and a description of the behaviour, and checked against a JVM
|
||||
([#6741](https://github.com/horizon-rust/horizon/issues/6741)).
|
||||
- **Java's `HashMap` translated from OpenJDK.** `crates/horizon-world/src/java_hash_map.rs`, which reproduces the
|
||||
iteration order of `java.util.HashMap`, was translated from OpenJDK's `java/util/HashMap.java` (GPL-2.0 with the
|
||||
Classpath Exception; copyright Oracle and/or its affiliates). It was added on 7 October 2026 (`118e93ea51` and
|
||||
`194db0dbb4`, first released in `v2026.10.12`). It was replaced in
|
||||
[#12043](https://github.com/horizon-rust/horizon/pull/12043) by code written without OpenJDK's sources, from a
|
||||
description of the behaviour, the Java SE API documentation and the textbook red-black tree, and checked against a
|
||||
JVM ([#6741](https://github.com/horizon-rust/horizon/issues/6741)).
|
||||
|
||||
## Catnip / Ponder
|
||||
|
||||
`crates/horizon-client-render/src/fluid_render.rs` translates the still-fluid face tiling and
|
||||
UV rules of Catnip's `FluidRenderHelper` from Ponder 1.0.82 for Minecraft 1.21.1
|
||||
(`net.createmod.ponder:ponder-neoforge:1.0.82+mc1.21.1`). Copyright (c) 2022 The Create Team,
|
||||
licensed under MIT (`LICENSE_Ponder` in that artifact); the full license heads the Rust file.
|
||||
The native renderer uses Horizon's own block-sprite arrays, pose and light packing. The
|
||||
development-only oracle calls the unchanged helper from the player's local artifact. No
|
||||
original classes, game shaders, textures or prepared resources are distributed here.
|
||||
|
||||
## wgpu-hal
|
||||
|
||||
`third_party/wgpu-hal` is [wgpu-hal](https://github.com/gfx-rs/wgpu) 30.0.1 by the gfx-rs
|
||||
developers, with upstream fixes applied
|
||||
([gfx-rs/wgpu#10124](https://github.com/gfx-rs/wgpu/pull/10124),
|
||||
[gfx-rs/wgpu#10714](https://github.com/gfx-rs/wgpu/pull/10714)). Its GL backend also reports
|
||||
the context's sampled textures and samplers per shader stage (usually 32 on desktop GL,
|
||||
where WebGL2's minimum 16 was reported before), so a pipeline layout the driver accepts is
|
||||
not refused. It is licensed under MIT or Apache-2.0; both licenses are in that folder
|
||||
(`LICENSE.MIT`, `LICENSE.APACHE`).
|
||||
|
||||
## naga
|
||||
|
||||
`third_party/naga` is [naga](https://github.com/gfx-rs/wgpu) 30.0.1 by the gfx-rs developers, with
|
||||
fixes to its GLSL frontend that shader packs need, each applied in the commit that needed it. It is licensed under MIT or Apache-2.0; both licenses
|
||||
are in that folder (`LICENSE.MIT`, `LICENSE.APACHE`).
|
||||
|
||||
The GLSL frontend also resets the common type for each comma-separated declarator so one
|
||||
variable's array specifier does not change later variables.
|
||||
It also reads a struct member outside a constant expression through a pointer to the member,
|
||||
not out of a loaded copy of the whole struct, so a member an atomic function uses can be read.
|
||||
|
||||
## DirectX Shader Compiler
|
||||
|
||||
The Windows x64 game folder holds `dxcompiler.dll`, Microsoft's DirectX Shader Compiler
|
||||
[v1.9.2609](https://github.com/microsoft/DirectXShaderCompiler/releases/tag/v1.9.2609), unmodified: the
|
||||
`bin/x64/dxcompiler.dll` of `dxc_2026_09_29.zip` (zip SHA-256
|
||||
`ad31b1fc8443175d204f77a611fdb3ef2ec42759bdc2f1167368de24a4a7e7f1`, DLL SHA-256
|
||||
`0689e2fee0a1c9df8662a59680469f24e2a3ad7ce6bbbcc9284f7a83172bfc59`, 22,274,872 bytes). The release build downloads
|
||||
it and checks both checksums (`tools/ci/fetch_dxc.py`); it is not in this repository. DirectX 12 loads it only on
|
||||
integrated GPUs (`crates/horizon-client-render/src/gfx/dx12_compiler.rs`,
|
||||
[#8513](https://github.com/horizon-rust/horizon/issues/8513)); every other GPU compiles with FXC, part of Windows.
|
||||
|
||||
Copyright (c) Microsoft Corporation. It is not covered by Horizon's MIT license. It is distributed under the
|
||||
"Microsoft Software License Terms, Microsoft DirectX Shader Compiler" (`LICENSE-MS.txt` of that release). Its
|
||||
Distributable Code terms are the Windows SDK's: end users get terms that protect the code and Microsoft at least as
|
||||
much, and the distributor indemnifies Microsoft. The project accepted them on 2026-11-08. Its open-source part is also under the University of Illinois/NCSA license (`LICENSE-LLVM.txt`). Both
|
||||
files ship beside the DLL as `DXC-LICENSE-MS.txt` and `DXC-LICENSE-LLVM.txt`, with `DXC-NOTICE.txt`
|
||||
(`packaging/windows/`), which tells players those terms apply and that deleting the DLL brings back FXC.
|
||||
|
||||
- Only x64: the Windows SDK's list of distributable files
|
||||
([REDIST.TXT lists](https://learn.microsoft.com/en-us/legal/windows-sdk/redist), updated 2024-10-21) names
|
||||
`Redist\D3D\x64\dxcompiler.dll` and `dxil.dll` and their x86 copies, for classic Windows applications (Horizon is
|
||||
one), and no ARM64 copy. The release zip's own `LICENSE-MS.txt` refers to a list of distributable files that the zip
|
||||
doesn't contain, so the SDK's list is the one followed. The Windows ARM64 build ships no DXC and compiles with FXC.
|
||||
- No `dxil.dll`: since DXC 1.8.2505 the compiler signs shaders with its own validator and no longer loads it, and
|
||||
wgpu never does.
|
||||
|
||||
## libmimalloc-sys and mimalloc
|
||||
|
||||
`third_party/libmimalloc-sys` is [libmimalloc-sys](https://github.com/purpleprotocol/mimalloc_rust)
|
||||
0.1.49 by Octavian Oncescu, with the [mimalloc](https://github.com/microsoft/mimalloc) v3 sources it
|
||||
bundles (Copyright (c) 2018-2025 Microsoft Corporation, Daan Leijen), both under the MIT license
|
||||
(`LICENSE.txt` and `c_src/mimalloc/v3/LICENSE` in that folder). It holds only the v3 sources. One
|
||||
change: `mi_popcount` in `include/mimalloc/bits.h` uses mimalloc's portable bit count on MSVC
|
||||
x86/x64 instead of the POPCNT instruction, which CPUs before Nehalem lack (#7264).
|
||||
developers, with one upstream fix applied
|
||||
([gfx-rs/wgpu#10124](https://github.com/gfx-rs/wgpu/pull/10124)). It is licensed under MIT or
|
||||
Apache-2.0; both licenses are in that folder (`LICENSE.MIT`, `LICENSE.APACHE`).
|
||||
|
||||
## Pixelify Sans
|
||||
|
||||
@@ -110,251 +19,3 @@ by The Pixelify Sans Project Authors, licensed under the SIL Open Font License 1
|
||||
[Pixelarticons](https://github.com/halfmage/pixelarticons) by Gerrit Halfmann, under the MIT
|
||||
license (`crates/horizon-theme/icons/pixel/LICENSE-pixelarticons.txt`). `star.svg` is Horizon's own, drawn on
|
||||
the same grid.
|
||||
|
||||
## Hugeicons
|
||||
|
||||
`crates/horizon-theme/icons/glass/*.svg` are icons from the free set of
|
||||
[Hugeicons](https://github.com/hugeicons/hugeicons) (`@hugeicons/core-free-icons` 4.4.0), under
|
||||
the MIT license (`crates/horizon-theme/icons/glass/LICENSE-hugeicons.txt`), exported with a 1.6
|
||||
stroke in `currentColor`.
|
||||
|
||||
`crates/horizon-theme/icons/glass/discord.svg` is Discord's logo as drawn by
|
||||
[Simple Icons](https://github.com/simple-icons/simple-icons) 13.21.0 (CC0 1.0). The logo is Discord's
|
||||
trademark, used only on the button that opens Horizon's Discord server.
|
||||
|
||||
## AMD FidelityFX SDK (FSR 3.1 frame generation)
|
||||
|
||||
`crates/horizon-client-render/src/gfx/frame_gen/optical_flow.wgsl` and `interpolation.wgsl` are
|
||||
ports to WGSL of the optical flow and frame interpolation shaders of the
|
||||
[AMD FidelityFX SDK](https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK) 1.1.4
|
||||
(`sdk/include/FidelityFX/gpu/{opticalflow,frameinterpolation}`, at commit
|
||||
[c6efa6bf7f20](https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK/tree/c6efa6bf7f2027b3ec94f28578bb5965eabb9e55)),
|
||||
and `optical_flow.rs` and `interpolation.rs` follow the SDK's
|
||||
`sdk/src/components/{opticalflow/ffx_opticalflow.cpp,frameinterpolation/ffx_frameinterpolation.cpp}`
|
||||
(their passes, their order and their dispatch sizes). Copyright (C) 2024 Advanced Micro Devices,
|
||||
Inc., under the MIT license, whose text heads each file. AMD and FidelityFX are AMD's
|
||||
trademarks; Horizon is not affiliated with AMD.
|
||||
|
||||
## Mod loader logos
|
||||
|
||||
The launcher shows the logo of the mod loader an instance plays with, and offers the logos as
|
||||
instance icons.
|
||||
|
||||
- `launcher/assets/logos/{fabric,quilt,neoforge,forge}.png` are the loaders' logos as the launcher
|
||||
mockup on [playhorizon.dev/launcher](https://playhorizon.dev/launcher) shows them (horizon-site
|
||||
`public/media/launcher/*.webp`, converted to PNG), each its project's own mark:
|
||||
[Fabric](https://fabricmc.net/), [Quilt](https://quiltmc.org/) (its art is
|
||||
[CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/)),
|
||||
[NeoForged](https://neoforged.net/) (its art, by Ridanisaurus, is
|
||||
[CC BY 4.0](https://creativecommons.org/licenses/by/4.0/)) and
|
||||
[Minecraft Forge](https://minecraftforge.net/). They name the loader an instance runs.
|
||||
|
||||
Each logo belongs to its project. Showing it says which loader an instance runs; it does not mean
|
||||
the project endorses Horizon.
|
||||
|
||||
## Sign in with Microsoft
|
||||
|
||||
The launcher's sign-in buttons follow Microsoft's published branding guidelines for apps that sign in
|
||||
with Microsoft accounts
|
||||
([Sign in with Microsoft branding](https://learn.microsoft.com/en-us/entra/identity-platform/howto-add-branding-in-apps)).
|
||||
The four-square Microsoft symbol in `launcher/src/microsoft.rs` reproduces the squares, positions and
|
||||
colours of Microsoft's official `ms-symbollockup_mssymbol_19.svg` from that page, unmodified. Microsoft
|
||||
and its logo are trademarks of the Microsoft group of companies; Horizon is not endorsed by Microsoft.
|
||||
|
||||
## CIT Resewn
|
||||
|
||||
`crates/horizon-optifine/src/cit.rs` and `crates/horizon-client-render/src/cit.rs` follow the
|
||||
condition semantics of [CIT Resewn Continuation](https://github.com/EthanVisagie/CIT-Resewn-Continuation-1.21.11)
|
||||
(at `b792f9a`), a continuation of [CIT Resewn](https://github.com/SHsuperCM/CITResewn) by SHsuperCM: the
|
||||
1.21 component paths, enchantment levels, percent damage, text matching and rule ordering. It is
|
||||
licensed under the MIT license:
|
||||
|
||||
> Copyright (c) 2021 SHsuperCM
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
> and associated documentation files (the "Software"), to deal in the Software without
|
||||
> restriction, including without limitation the rights to use, copy, modify, merge, publish,
|
||||
> distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
||||
> Software is furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all copies or
|
||||
> substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
> BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## FusionExamples
|
||||
|
||||
The tile tables in `crates/horizon-optifine/src/fusion/layout.rs` were read off the connecting
|
||||
texture templates (`templates/template <layout>.png`) of
|
||||
[FusionExamples](https://github.com/SuperMartijn642/FusionExamples) (at `8c9c56e`), which is
|
||||
licensed under the MIT license:
|
||||
|
||||
> Copyright (c) 2024 Martijn van den Brand
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||
> and associated documentation files (the "Software"), to deal in the Software without
|
||||
> restriction, including without limitation the rights to use, copy, modify, merge, publish,
|
||||
> distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
|
||||
> Software is furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in all copies or
|
||||
> substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
|
||||
> BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
> DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## BlueMap
|
||||
|
||||
`crates/horizon-client-render/src/bluemap.rs` reads the lowres tiles of a server's
|
||||
[BlueMap](https://github.com/BlueMap-Minecraft/BlueMap) web map. It follows three of BlueMap's files:
|
||||
`core/src/main/java/de/bluecolored/bluemap/core/map/lowres/LowresLayer.java` (`saveTile`) for the
|
||||
tiles' pixel layout, `common/webapp/src/js/util/Utils.js` (`pathFromCoords`) for their paths, and
|
||||
`core/src/main/java/de/bluecolored/bluemap/core/map/MapSettingsSerializer.java` for a map's
|
||||
`settings.json`, at commit
|
||||
[96ae320d1d39](https://github.com/BlueMap-Minecraft/BlueMap/tree/96ae320d1d39581c10058d8222f2290f2fcb5333).
|
||||
BlueMap is licensed under the MIT license:
|
||||
|
||||
> Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||
> Copyright (c) contributors
|
||||
>
|
||||
> Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
> of this software and associated documentation files (the "Software"), to deal
|
||||
> in the Software without restriction, including without limitation the rights
|
||||
> to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
> copies of the Software, and to permit persons to whom the Software is
|
||||
> furnished to do so, subject to the following conditions:
|
||||
>
|
||||
> The above copyright notice and this permission notice shall be included in
|
||||
> all copies or substantial portions of the Software.
|
||||
>
|
||||
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
> IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
> FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
> AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
> LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
> OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
> THE SOFTWARE.
|
||||
|
||||
## JOML
|
||||
|
||||
`crates/horizon-client-render/src/camera.rs` (`joml::Mat4::rotation`, `invert_orthonormal`) and
|
||||
`crates/horizon-client-render/src/gfx/pack_uniforms.rs` (`invert_generic`, `invert_affine`, the
|
||||
formulas of `pack_projection` and `shadow_ortho`) adapt the float arithmetic of
|
||||
`Matrix4f.rotation(Quaternionfc)`, `invertOrthonormal`, `invertGenericNonThis`, `invertAffine`,
|
||||
`setPerspective` and `setOrtho` from
|
||||
[JOML](https://github.com/JOML-CI/JOML/tree/faf9eef2511242122beb6055fe3da92daed214c5) 1.10.9, the
|
||||
library vanilla 26.3 uses, so that shader packs get the same matrices to the last bit. Changes:
|
||||
ported to Rust; the pack_uniforms.rs functions drop JOML's property flags, and
|
||||
`pack_projection` works the formula in doubles. The copyright line and license notice also head
|
||||
both files.
|
||||
|
||||
`camera.rs` also adapts `Quaternionf.rotationX`, `rotationY` and `rotationZ`,
|
||||
`Matrix4f.rotateAffine` and `Vector4f.mulAffine` (`joml::Quat::rotation_x`/`_y`/`_z`,
|
||||
`joml::Mat4::rotate_affine`, `transform_affine`), for the sky's positions shader packs read.
|
||||
Changes: ported to Rust; `rotate_affine` keeps only the affine case.
|
||||
|
||||
```
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2015-2026 Richard Greenlees
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
```
|
||||
|
||||
## Just Enough Items
|
||||
|
||||
The Recipes GUI sprites and settings icon under `crates/horizon-client-render/src/jei_recipes` are from
|
||||
[Just Enough Items 31.17.0.108](https://github.com/mezz/JustEnoughItems/tree/0371fa6fafa14635a356019e4604f5580b26a34f)
|
||||
by mezz and contributors, under the MIT license in that directory (`LICENSE.txt`).
|
||||
|
||||
## Flywheel native model directional shading
|
||||
|
||||
The two-light diffuse expression and transformed-normal policy in
|
||||
`terrain.wgsl`'s native model entries follow Flywheel 1.0.6
|
||||
(`internal/diffuse.glsl`, `instance/transformed.vert`, `internal/common.vert`).
|
||||
No Flywheel classes, compiled shaders or original model/texture assets are bundled.
|
||||
|
||||
Copyright (c) 2021-2024 Jozufozu
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
## fdlibm
|
||||
|
||||
`crates/horizon-core/src/jmath/fdlibm.rs` and the `fdlibm_asin`, `fdlibm_atan` and
|
||||
`fdlibm_atan2` functions in `crates/horizon-core/src/geometry/trig.rs` are Rust ports of
|
||||
[fdlibm](https://www.netlib.org/fdlibm/) 5.3, Sun's freely distributable math library, whose
|
||||
results the Java SE API specifies for `StrictMath`. `fdlibm.rs` ports `e_log.c`, `e_log10.c`,
|
||||
`s_cbrt.c` and `e_hypot.c`, and, with fused multiply-adds, `s_sin.c`, `s_cos.c`, `k_sin.c`,
|
||||
`k_cos.c` and `e_rem_pio2.c`; `trig.rs` ports `e_asin.c`, `s_atan.c` and `e_atan2.c`. This
|
||||
notice also heads both files:
|
||||
|
||||
```
|
||||
Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||
|
||||
Developed at SunSoft, a Sun Microsystems, Inc. business.
|
||||
Permission to use, copy, modify, and distribute this
|
||||
software is freely granted, provided that this notice
|
||||
is preserved.
|
||||
```
|
||||
|
||||
## Starling
|
||||
|
||||
`crates/horizon-client-render/src/touch/layout.rs` and `crates/horizon-client-render/src/touch/aim.rs`
|
||||
are adapted from the touch layout and touch helpers of
|
||||
[Starling](https://github.com/starling-client/starling), an Android port of Horizon, at commit
|
||||
[150a414b09a1](https://github.com/starling-client/starling/tree/150a414b09a18c900489d9462a7fc035dae744b7)
|
||||
(`android` branch), written mostly by Vasysik. Starling is licensed under the same MIT license as
|
||||
Horizon (Copyright (c) 2026 Ludovic Marie and the Horizon contributors).
|
||||
|
||||
`crates/horizon-client-render/src/keypad.rs` is adapted from Starling's keypad profile
|
||||
(`crates/horizon-client-render/src/keypad.rs`) at the same commit.
|
||||
|
||||
`crates/horizon-client-render/src/android_gamepad.rs` is adapted from Starling's controller decoder
|
||||
(`crates/horizon-client-render/src/android_gamepad.rs`) and the input-mode part of its
|
||||
`android_runtime.rs`, at the same commit.
|
||||
|
||||
`crates/horizon-client-render/src/touch.rs` and `touch/tests/` are adapted from the touch input
|
||||
state of Starling's `crates/horizon-client-render/src/touch.rs` at the same commit.
|
||||
|
||||
`crates/horizon-client-render/src/android_runtime.rs` and `android_runtime/tests/` are adapted from the
|
||||
input part of Starling's `crates/horizon-client-render/src/android_runtime.rs` at the same commit.
|
||||
@@ -0,0 +1,78 @@
|
||||
# Entity model document loading
|
||||
|
||||
The three startup batches (boats/chest boats, minecarts, armor stands/player armor)
|
||||
now share one parsed document. For this fixture, that replaces 43 full document
|
||||
reads/parses (boat discovery plus 42 selected layers) with one. Selected models
|
||||
still produce independent `Part` trees; the document is dropped after the batches
|
||||
are built. Other entity loaders retain their existing behavior.
|
||||
|
||||
## Reproduce
|
||||
|
||||
From the repository root:
|
||||
|
||||
```sh
|
||||
python3 benchmarks/entity-model-document-2026-10-14/generate_fixture.py /tmp/horizon-entity-model-document-fixture.json
|
||||
ENTITY_MODEL_BENCH_DOCUMENT=/tmp/horizon-entity-model-document-fixture.json \
|
||||
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
|
||||
cargo test -p horizon-client --profile fast --bin horizon-client \
|
||||
entity_model_document_benchmark -- --ignored --nocapture
|
||||
```
|
||||
|
||||
`CARGO_TARGET_DIR` is optional and can be changed for another machine. Supply a
|
||||
prepared `entity-models.json` through `ENTITY_MODEL_BENCH_DOCUMENT` to benchmark
|
||||
that document instead; the harness copies only that file to a temporary root.
|
||||
`ENTITY_MODEL_BENCH_REPETITIONS` controls repetitions (default 15).
|
||||
|
||||
The opt-in Rust test calls the actual three optimized production loaders and
|
||||
compares every selected part name, pose, polygon normal/vertex and child against
|
||||
the previous algorithm using the compatible per-model `load_model` API. Timings
|
||||
include reading, parsing, constructing, normalizing into a common result map, and
|
||||
dropping the result. Each variant gets three warmups and 15 measured calls, with
|
||||
order alternating. `black_box` consumes inputs/results. No other builds or
|
||||
optimization benchmarks ran during the measured calls.
|
||||
|
||||
## Input and limitations
|
||||
|
||||
Prepared resources were unavailable in the repository and local Horizon asset
|
||||
directories. This is a **synthetic** 2,473,695-byte document with 458 model layers,
|
||||
each containing 12 posed parts with six exported quads and normals. It selects 22
|
||||
boat/chest-boat layers, six minecart layers and 14 armor/player layers (42 total).
|
||||
One wood name is synthetic (`test_wood`); boat discovery accepts arbitrary wood
|
||||
names. The extra layers model the cost of parsing a full production-size document
|
||||
for each selected model.
|
||||
|
||||
File data is warm in the OS page cache. Equipment files are absent, so equipment
|
||||
texture loading is excluded. This measures the entity-model batch only and does
|
||||
not establish overall startup, frame time or FPS improvement. Shapes/layer counts
|
||||
in real prepared documents can produce different absolute timings.
|
||||
|
||||
Machine: AMD Ryzen 5 5600X (6 cores / 12 threads), Linux x86_64,
|
||||
Rust 1.99.0 (b940084d7, LLVM 23.1.1), Cargo `fast` profile (opt-level 3,
|
||||
16 codegen units, no LTO). Baseline algorithm corresponds to main
|
||||
`73a019967e9665c6b96332988c13cb66679d8477`.
|
||||
|
||||
## Results
|
||||
|
||||
| Variant | Median batch time | Full document reads/parses |
|
||||
| --- | ---: | ---: |
|
||||
| Previous per-model algorithm | 1,434.974 ms | 43 |
|
||||
| Shared document | 33.420 ms | 1 |
|
||||
|
||||
The measured batch is **42.94× faster** on this synthetic input. All 15 samples
|
||||
for both variants, warmup count, document size and selected model count are in
|
||||
[`results.json`](results.json).
|
||||
|
||||
## Validation
|
||||
|
||||
```sh
|
||||
cargo fmt --all -- --check
|
||||
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
|
||||
cargo test -p horizon-client --profile fast --bin horizon-client \
|
||||
entity_model_loading_tests -- --nocapture
|
||||
CARGO_TARGET_DIR=/home/bob/Documents/horizon/target \
|
||||
cargo clippy -p horizon-client --profile fast --lib --bin horizon-client --tests -- -D warnings
|
||||
```
|
||||
|
||||
The regular tests cover full/sparse documents, unrelated layers, a missing file,
|
||||
invalid JSON, non-object JSON, missing model keys, independent model trees, and
|
||||
equipment loading when the document is unavailable.
|
||||
@@ -0,0 +1,31 @@
|
||||
"""Generate a production-size synthetic document; no prepared assets required."""
|
||||
import json
|
||||
import pathlib
|
||||
import sys
|
||||
|
||||
woods = "oak spruce birch jungle acacia dark_oak mangrove cherry bamboo pale_oak test_wood".split()
|
||||
carts = "minecart chest_minecart hopper_minecart furnace_minecart tnt_minecart command_block_minecart".split()
|
||||
keys = [f"minecraft:{prefix}/{wood}#main" for prefix in ("boat", "chest_boat") for wood in woods]
|
||||
keys += [f"minecraft:{cart}#main" for cart in carts]
|
||||
keys += [f"minecraft:{model}#{slot}" for model in ("player", "armor_stand", "armor_stand_small")
|
||||
for slot in ("helmet", "chestplate", "leggings", "boots")]
|
||||
keys += [f"minecraft:{model}#main" for model in ("armor_stand", "armor_stand_small")]
|
||||
|
||||
face = [[0, 0, 0, 0, 0], [16, 0, 0, 1, 0], [16, 16, 0, 1, 1], [0, 16, 0, 0, 1]]
|
||||
part = {"pose": [1, 2, 3, 0.25, -0.5, 0.75, 1, 1, 1], "polygons": [face] * 6,
|
||||
"normals": [[0, 0, 1]] * 6}
|
||||
model = {"pose": [0, 0, 0, 0, 0, 0, 1, 1, 1],
|
||||
"children": {f"part_{i}": part for i in range(12)}}
|
||||
encoded = json.dumps(model, separators=(",", ":"))
|
||||
entries = [json.dumps(key) + ":" + encoded for key in keys]
|
||||
size = 2 + sum(map(len, entries)) + len(entries) - 1
|
||||
index = 0
|
||||
while size < 2_470_000:
|
||||
entry = json.dumps(f"minecraft:fixture_{index}#main") + ":" + encoded
|
||||
entries.append(entry)
|
||||
size += 1 + len(entry)
|
||||
index += 1
|
||||
output = pathlib.Path(sys.argv[1])
|
||||
output.write_text("{" + ",".join(entries) + "}")
|
||||
print(json.dumps({"path": str(output), "bytes": output.stat().st_size,
|
||||
"layers": len(entries), "selected_layers": len(keys)}))
|
||||
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"baseline_median_ms": 1434.973835,
|
||||
"baseline_ms": [
|
||||
1400.008286,
|
||||
1406.761694,
|
||||
1408.9131360000001,
|
||||
1418.6680549999999,
|
||||
1419.149658,
|
||||
1427.082872,
|
||||
1433.088092,
|
||||
1434.973835,
|
||||
1449.7688150000001,
|
||||
1452.143883,
|
||||
1453.987998,
|
||||
1455.518231,
|
||||
1457.0334540000001,
|
||||
1458.588552,
|
||||
1485.34133
|
||||
],
|
||||
"document_bytes": 2473695,
|
||||
"optimized_median_ms": 33.419768000000005,
|
||||
"optimized_ms": [
|
||||
32.64795,
|
||||
32.812732,
|
||||
33.054488,
|
||||
33.056914,
|
||||
33.102999000000004,
|
||||
33.23532,
|
||||
33.28287,
|
||||
33.419768000000005,
|
||||
33.610569,
|
||||
33.874749,
|
||||
33.915657,
|
||||
33.93877,
|
||||
34.009893999999996,
|
||||
34.550526,
|
||||
36.096408000000004
|
||||
],
|
||||
"repetitions": 15,
|
||||
"selected_models": 42,
|
||||
"speedup": 42.937875421516985,
|
||||
"warmup_pairs": 3
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
# Entity occlusion split measurements — 2026-11-02
|
||||
|
||||
These measurements came from the pre-split integration branch for PR #7054. That build contained the entity-occlusion rewrite and particle light lookup cache; Particle Culling was Off. They are useful comparison evidence, but they are not a benchmark of this isolated entity-only commit. The cache-only run in PR #7391 measured effectively the same CPU time on the ordinary scene, but the combined result still cannot isolate interactions.
|
||||
|
||||
Host: Intel Core i7-3770S, Intel HD Graphics 4000, Vulkan/Mesa, 675×727, render distance 4, VSync off, 260 FPS cap. Two opposite-order passes measured for 8 seconds after warmup. Values are means. CPU is harness average CPU ms per frame; p99 is frame time. The driver supplied no usable GPU timing.
|
||||
|
||||
## Ordinary scene
|
||||
|
||||
The scene had 24 mobs, roughly 9,400–10,100 rain particles and campfire smoke.
|
||||
|
||||
| Build and mode | FPS | CPU ms/frame | Frame p99 ms |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Main, entity culling Off | 88.59 | 1.829 | 24.51 |
|
||||
| Pre-split integration branch, all culling Off | 88.33 | 2.063 | 24.51 |
|
||||
| Main, entity culling Synchronous | 89.34 | 1.965 | 23.99 |
|
||||
| Pre-split integration branch, entity Synchronous | 89.13 | 2.113 | 24.15 |
|
||||
|
||||
This normal-scene run does not show a large FPS change; its CPU differences are small relative to frame time and not attributable to the entity-only change by themselves.
|
||||
|
||||
## Opaque-wall scene
|
||||
|
||||
A 32×32 platform at Y=300, a 7-block wall with a one-block vertical opening, and 192 pigs spawned behind the wall (216 mobs in the captured scene). The player looked toward the opening from the near side. The same world and camera path were used for the main and integration builds.
|
||||
|
||||
| Build and mode | FPS | CPU ms/frame | Frame p99 ms |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Main, Off | 89.08 | 2.423 | 13.52 |
|
||||
| Integration branch, Off | 89.23 | 2.355 | 13.27 |
|
||||
| Main, Synchronous | 92.81 | 2.566 | 14.60 |
|
||||
| Integration branch, Synchronous | 93.21 | 2.550 | 12.84 |
|
||||
| Main, Asynchronous | 92.73 | 2.364 | 13.04 |
|
||||
| Integration branch, Asynchronous | 92.62 | 2.314 | 13.18 |
|
||||
|
||||
The asynchronous mode reduced measured CPU time slightly in this wall scene but did not improve FPS beyond run-to-run spread. This is a synthetic occlusion-heavy scene, not a broad performance claim.
|
||||
|
||||
## Captures
|
||||
|
||||
The HUD performance overlay is visible in each capture. The integration-build screenshots were recorded with the same wall and camera position in Off, Synchronous, and Asynchronous modes.
|
||||
|
||||
- Main, Off: `main-off.png`
|
||||
- Integration branch, Off: `branch-off.png`
|
||||
- Integration branch, Synchronous: `branch-sync.png`
|
||||
- Integration branch, Asynchronous: `branch-async.png`
|
||||
|
Before Width: | Height: | Size: 398 KiB |
|
Before Width: | Height: | Size: 398 KiB |
|
Before Width: | Height: | Size: 399 KiB |
|
Before Width: | Height: | Size: 398 KiB |
@@ -1,42 +0,0 @@
|
||||
# Entity occlusion pipeline — release/OpenGL run (2026-11-04)
|
||||
|
||||
This is the final local smoke benchmark for the entity-occlusion pipeline before opening the PR. It was run from the branch after the release build completed, with the OpenGL backend selected explicitly. The same process created each scene, switched the culling mode, flew the camera for two seconds, collected frame/CPU telemetry, and captured the screenshot after the scene settled.
|
||||
|
||||
**Host:** Intel Core i7-3770S, Intel HD Graphics 4000, Mesa OpenGL 4.2
|
||||
**Window:** 1280×720, offscreen, VSync disabled
|
||||
**World:** fresh temporary home, 32×32 platform at Y=300; wall scenes add a solid stone wall and an optional one-block slit
|
||||
**Entities:** 24 pigs in the normal scene, 192 pigs in wall scenes, 512 pigs in stress scenes
|
||||
**Settings:** render distance 8, `entityCullingPrecheck:64`, FPS overlay on, no resource-pack occlusion assumptions
|
||||
**Build:** `cargo build --release -p horizon-client`
|
||||
|
||||
## Results
|
||||
|
||||
The values below are branch-only measurements. They are useful for comparing the three modes under identical geometry and for checking that the worker is doing useful work. A fresh main binary was not built in this short pass, so these numbers do not claim a controlled main-to-branch delta.
|
||||
|
||||
| Scene | Off FPS / CPU p50 | Sync FPS / CPU p50 | Async FPS / CPU p50 | Async entities culled |
|
||||
| --- | ---: | ---: | ---: | ---: |
|
||||
| `entity_normal` (24 visible) | 240.5 / 0.586 ms | 233.5 / 0.762 ms | 239.3 / 0.686 ms | 0 |
|
||||
| `entity_wall` (192, solid) | 228.8 / 1.245 ms | 318.6 / 1.342 ms | **324.5 / 0.478 ms** | 124,608 |
|
||||
| `entity_wall_slit` (192, one-block slit) | 231.4 / 1.102 ms | 265.0 / 1.387 ms | **281.2 / 0.716 ms** | 102,826 |
|
||||
| `entity_stress` (512, solid) | 190.3 / 2.467 ms | 299.2 / 2.593 ms | **325.5 / 0.691 ms** | 290,234 |
|
||||
| `entity_stress_slit` (512, one-block slit) | 190.4 / 2.476 ms | 262.2 / 2.573 ms | **262.1 / 1.297 ms** | 227,301 |
|
||||
|
||||
Async telemetry confirmed that the render thread stayed non-blocking (`try_recv`/`try_send`, `worker_blocking_wait_ms: 0`). The latest wall/slit run completed 562 worker jobs, queued 3,982 queries, avoided about 4.0 million entity bytes, and had 379 ns recent p50 worker-job time. The solid 512-pig run culled 15,552 generated vertices; the slit run culled 120,290 generated vertices. The normal scene recorded no pre-model hides and kept the opt-in path close to Off.
|
||||
|
||||
## Captures
|
||||
|
||||
Every image includes the FPS performance overlay. The names are `<mode>-<scene>.png`:
|
||||
|
||||
- [Off — normal](screenshots/off-entity_normal.png), [wall](screenshots/off-entity_wall.png), [wall slit](screenshots/off-entity_wall_slit.png), [stress](screenshots/off-entity_stress.png), [stress slit](screenshots/off-entity_stress_slit.png)
|
||||
- [Sync — normal](screenshots/sync-entity_normal.png), [wall](screenshots/sync-entity_wall.png), [wall slit](screenshots/sync-entity_wall_slit.png), [stress](screenshots/sync-entity_stress.png), [stress slit](screenshots/sync-entity_stress_slit.png)
|
||||
- [Async — normal](screenshots/async-entity_normal.png), [wall](screenshots/async-entity_wall.png), [wall slit](screenshots/async-entity_wall_slit.png), [stress](screenshots/async-entity_stress.png), [stress slit](screenshots/async-entity_stress_slit.png)
|
||||
|
||||
## Reproduction
|
||||
|
||||
From the repository root, with prepared 26.3 resources available:
|
||||
|
||||
```sh
|
||||
python3 tools/entity_occlusion_bench.py
|
||||
```
|
||||
|
||||
The script uses fresh temporary game data, the release binary in `target/release`, OpenGL, the FPS overlay, and writes JSON plus captures under `/tmp/horizon-entity-occlusion-release-quick/`.
|
||||
|
Before Width: | Height: | Size: 290 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 292 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 288 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
|
Before Width: | Height: | Size: 202 KiB |
|
Before Width: | Height: | Size: 205 KiB |
|
Before Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 206 KiB |
@@ -0,0 +1,69 @@
|
||||
# Reuse parsed model states
|
||||
|
||||
`models::prepare` parsed `model-states.json` to select blocks, then
|
||||
`StateModels::load` reopened and parsed the same document for binding and baking.
|
||||
`StateModels::from_facts` now borrows the first parsed map. The public `load`
|
||||
entry point still reads, parses and validates its own document. Both paths retain
|
||||
the `fs::read` + `serde_json::from_slice` strategy merged in PR #205.
|
||||
|
||||
The shared map uses `BTreeMap`, preserving the original catalog loader's JSON
|
||||
validation, including rejection of top-level `null`. The old selection map was
|
||||
`serde_json::Map`, also backed by a BTreeMap with the project's current features.
|
||||
Catalog binding, model selection and baking are unchanged. Preparation no longer
|
||||
holds a second complete JSON tree while constructing the catalog; no persistent
|
||||
cache or extra clones were added.
|
||||
|
||||
## Measurement
|
||||
|
||||
The committed `model_states_bench` example runs main's two-parse sequence after PR #205
|
||||
(first a serde JSON map, then `StateModels::load`) and the new one-parse sequence
|
||||
(first a BTreeMap, then `StateModels::from_facts`). Both select blocks from the
|
||||
same generated document with slice parsing and call the actual catalog binding/baking code. Timing
|
||||
includes file reads, parsing, filtering, binding, baking and result destruction.
|
||||
Fixture generation and equality checks run outside the timed region.
|
||||
|
||||
Prepared Minecraft resources were unavailable locally, so this is a synthetic
|
||||
2,836,696-byte document containing 843 block schemas and 53,952 states. Schemas
|
||||
combine integer and named properties. Blockstate resources use weighted and
|
||||
conditional multipart choices with rotations and UV locking, sharing one model
|
||||
with a baked face. Its absent texture uses the normal missing-sprite fallback.
|
||||
Both paths read identical files with a warm OS cache. The workload does not
|
||||
represent the full diversity of production model and texture assets.
|
||||
|
||||
On AMD Ryzen 5 5600X, Linux 7.2.8-zen1-2-zen x86_64, rustc 1.99.0
|
||||
(b940084d7 2026-09-28), Cargo `fast` profile, serial execution:
|
||||
|
||||
| Path | Median (15 samples) |
|
||||
| --- | ---: |
|
||||
| Before: parse twice, with #205 slice readers | 96.080 ms |
|
||||
| After: reuse first parse, with #205 slice readers | 73.585 ms |
|
||||
|
||||
**1.306x speedup; 23.41% less elapsed time** for this loading segment after PR #205. Each path
|
||||
has two warmups, sample order alternates, and inputs/results use `black_box`.
|
||||
This excludes gallery placements, GPU work and overall application startup.
|
||||
|
||||
These measurements supersede the original unbuffered-reader timings
|
||||
(2732.004 ms → 1386.060 ms, 1.971x) after rebasing onto main at
|
||||
`e96e1571`. The reviewer measured approximately 1.05x with real prepared resources;
|
||||
the generated fixture's balance of parsing and binding differs from production.
|
||||
The change still removes one complete document read, parse and JSON tree.
|
||||
|
||||
Equality validation compares every state's selected variants and baked geometry
|
||||
at three positions, plus sprite layers and opacity/translucency flags. The
|
||||
focused test also checks matching schema/registry errors, malformed/missing
|
||||
source files, rejection of `null`, and successful shared-facts loading after the
|
||||
source file has been deleted.
|
||||
|
||||
## Reproduce
|
||||
|
||||
```sh
|
||||
export CARGO_TARGET_DIR=/home/bob/Documents/horizon/target
|
||||
export CARGO_INCREMENTAL=0
|
||||
cargo run -p horizon-client --profile fast --example model_states_bench -- 15
|
||||
cargo test -p horizon-client --profile fast --example model_states_bench
|
||||
cargo clippy -p horizon-client --all-targets --profile fast -- -D warnings
|
||||
cargo fmt --all -- --check
|
||||
```
|
||||
|
||||
The target directory can be changed for another machine. The example creates and
|
||||
removes its fixtures in the system temporary directory.
|
||||
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"date": "2026-10-15",
|
||||
"environment": "Linux x86_64/ext4/NVMe, Ryzen5 5600X, Rust1.99.0, Cargo fast",
|
||||
"scope": "actual resource_root vs original wrapper/builder; warmed storage; output equivalence outside timing",
|
||||
"warmups": 2,
|
||||
"median_samples": 11,
|
||||
"prepared_minecraft": "26.3",
|
||||
"prepared_schema": 7,
|
||||
"prepared_manifest_sha256": "fd03c686302748748e132ef3978b7b0bcf42024257e802985a5cc7175cc74298",
|
||||
"packs": [
|
||||
{
|
||||
"project": "faithful-32x",
|
||||
"version": "lDYpMiqk",
|
||||
"version_name": "[26.3] Faithful 32x \u2013 September 2026 Release",
|
||||
"publisher_page": "https://modrinth.com/resourcepack/faithful-32x/version/lDYpMiqk",
|
||||
"download_url": "https://cdn.modrinth.com/data/w0TnApzs/versions/lDYpMiqk/Faithful%2032x%20-%2026.3.zip",
|
||||
"zip_bytes": 13116019,
|
||||
"zip_sha512": "e90ec63af7f239dbb99aa20c98b23d830e76898f65d3e31b7f0b53bb36db12dcd8c38d6930c743237c9c3db7bf708423fa1d1b2fd497dd6c281dbe216b779db9",
|
||||
"asset_files": 5063,
|
||||
"assets_uncompressed_bytes": 12524266,
|
||||
"original_ms": 159.827,
|
||||
"cold_ms": 162.711,
|
||||
"hit_ms": 0.707
|
||||
},
|
||||
{
|
||||
"project": "default-hd-128x",
|
||||
"version": "rErHu3BE",
|
||||
"version_name": "Default HD 128x Demo/Alpha 1.8.2.7",
|
||||
"publisher_page": "https://modrinth.com/resourcepack/default-hd-128x/version/rErHu3BE",
|
||||
"download_url": "https://cdn.modrinth.com/data/orfTV6nk/versions/rErHu3BE/Default%20HD%20128x%20Demo%201.8.2.7.zip",
|
||||
"zip_bytes": 16876419,
|
||||
"zip_sha512": "f5f9606e92b986cd9c8b8e5ff2bb52db720cc7b38e013355bdc90089e01975a08d09750ef2fd727f753d88ec3fbcd067355179b490587f667b2995f8be81640f",
|
||||
"asset_files": 2318,
|
||||
"assets_uncompressed_bytes": 17315416,
|
||||
"original_ms": 111.501,
|
||||
"cold_ms": 114.386,
|
||||
"hit_ms": 0.31
|
||||
},
|
||||
{
|
||||
"project": "fpbr",
|
||||
"version": "dynf82xk",
|
||||
"version_name": "support 1.21.9 and newer",
|
||||
"publisher_page": "https://modrinth.com/resourcepack/fpbr/version/dynf82xk",
|
||||
"download_url": "https://cdn.modrinth.com/data/nvEpbd8t/versions/dynf82xk/FPBR-Main-1.21.9-R1.3.zip",
|
||||
"zip_bytes": 46737770,
|
||||
"zip_sha512": "64f1bbd036e205118f1d9c49a79558db2c1356ee988fb939c0023db1967d78e1bd05047f341ce6d65355717ba7ddb1330af57edbb4d5b8713c96ae62987274c5",
|
||||
"asset_files": 7001,
|
||||
"assets_uncompressed_bytes": 56356903,
|
||||
"original_ms": 347.639,
|
||||
"cold_ms": 348.012,
|
||||
"hit_ms": 0.448
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
# Particle culling review measurements — 2026-11-02
|
||||
|
||||
Ordinary-scene captures and measurements for PR #7054. The scene contains 24 mobs, about 9,400–10,100 rain particles, and about 50–100 campfire smoke particles. Two opposite-order passes were run with 2 s warmup and 8 s measurement per condition. Host: Intel Core i7-3770S, Intel HD Graphics 4000, Vulkan/Mesa, 675×727, render distance 4, VSync off, 260 FPS cap.
|
||||
|
||||
These are means of the two samples. CPU is the harness's average CPU time per frame; p99 is frame time. The normal scene is not expected to show large gains because most particles are visible.
|
||||
|
||||
| Condition | FPS | CPU ms/frame | Frame p99 ms |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Main, culling Off | 88.39 | 1.930 | 23.85 |
|
||||
| Particle branch, culling Off | 88.55 | 1.828 | 24.88 |
|
||||
| Main, Entity Culling Synchronous | 89.12 | 1.887 | 23.07 |
|
||||
| Particle branch, Entity Culling Synchronous, Particle Culling Off | 89.06 | 1.897 | 25.18 |
|
||||
| Particle Culling Synchronous | 88.87 | 1.774 | 24.94 |
|
||||
| Particle Culling Asynchronous* | 89.00 | 1.754 | 24.90 |
|
||||
|
||||
*The asynchronous samples predate the final switch to a dedicated particle worker. They are retained only as historical context and are not a measurement of the final worker implementation. No FPS improvement is claimed from these ordinary-scene runs. The Off path delegates directly to `render`; `disabled_culled_render_matches_the_regular_particle_path` checks that it produces the same vertices.
|
||||
|
||||
The FPS and CPU differences are within run-to-run variability for this GPU-limited scene. The first four conditions are the reviewer's requested Main-versus-branch default and existing synchronous-mode comparisons. Particle Sync/Async rows are branch-internal mode comparisons.
|
||||
|
||||
## Captures
|
||||
|
||||
The screenshots show the same ordinary test world and FPS overlay:
|
||||
|
||||
- `main-off.png`
|
||||
- `particle-off.png`
|
||||
- `particle-sync.png`
|
||||
- `particle-async.png`
|
||||
|
Before Width: | Height: | Size: 342 KiB |
|
Before Width: | Height: | Size: 343 KiB |
|
Before Width: | Height: | Size: 341 KiB |
|
Before Width: | Height: | Size: 341 KiB |
@@ -1,870 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T13:00:15Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "nightly-2026-11-04-67dad0d",
|
||||
"commit": "67dad0d"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 24,
|
||||
"os_version": "NixOS 26.05 (Yarara) (kernel 6.18.57)",
|
||||
"cpu": "13th Gen Intel(R) Core(TM) i7-13700KF",
|
||||
"ram_mb": 31904,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 4080",
|
||||
"vendor": "nvidia",
|
||||
"driver": "NVIDIA 595.71.05",
|
||||
"backend": "vulkan",
|
||||
"kind": "discrete"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 12,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 28.408,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 66658.183,
|
||||
"stdev": 61839.502,
|
||||
"min": 1827.42,
|
||||
"max": 124993.694,
|
||||
"ci95": 153630.237
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 74754.411,
|
||||
"stdev": 59189.587,
|
||||
"min": 13600.651,
|
||||
"max": 131761.773,
|
||||
"ci95": 147046.952
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 5571.499,
|
||||
"stdev": 1900.32,
|
||||
"min": 3378.38,
|
||||
"max": 6730.394,
|
||||
"ci95": 4721.037
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 15287.0,
|
||||
"stdev": 527.501,
|
||||
"min": 14788.0,
|
||||
"max": 15839.0,
|
||||
"ci95": 1310.49
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2958.557,
|
||||
"stdev": 376.543,
|
||||
"min": 2526.453,
|
||||
"max": 3216.434,
|
||||
"ci95": 935.46
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 368.457,
|
||||
"stdev": 90.668,
|
||||
"min": 300.631,
|
||||
"max": 471.438,
|
||||
"ci95": 225.25
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 91.04,
|
||||
"stdev": 40.506,
|
||||
"min": 46.124,
|
||||
"max": 124.796,
|
||||
"ci95": 100.63
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 581.0,
|
||||
"stdev": 48.0,
|
||||
"min": 533.0,
|
||||
"max": 629.0,
|
||||
"ci95": 119.248
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1277.531,
|
||||
"stdev": 25.546,
|
||||
"min": 1253.879,
|
||||
"max": 1304.623,
|
||||
"ci95": 63.466
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.529,
|
||||
"stdev": 0.127,
|
||||
"min": 0.396,
|
||||
"max": 0.649,
|
||||
"ci95": 0.315
|
||||
},
|
||||
"cpu.village.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.185,
|
||||
"stdev": 0.034,
|
||||
"min": 0.162,
|
||||
"max": 0.224,
|
||||
"ci95": 0.085
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3318.3,
|
||||
"stdev": 911.608,
|
||||
"min": 2266.627,
|
||||
"max": 3883.075,
|
||||
"ci95": 2264.743
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 16565.333,
|
||||
"stdev": 172.755,
|
||||
"min": 16367.0,
|
||||
"max": 16683.0,
|
||||
"ci95": 429.182
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2333.626,
|
||||
"stdev": 569.124,
|
||||
"min": 1745.365,
|
||||
"max": 2881.457,
|
||||
"ci95": 1413.897
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 336.615,
|
||||
"stdev": 185.666,
|
||||
"min": 208.133,
|
||||
"max": 549.487,
|
||||
"ci95": 461.257
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 160.734,
|
||||
"stdev": 127.586,
|
||||
"min": 39.777,
|
||||
"max": 294.05,
|
||||
"ci95": 316.967
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 666.333,
|
||||
"stdev": 24.44,
|
||||
"min": 645.0,
|
||||
"max": 693.0,
|
||||
"ci95": 60.718
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1346.816,
|
||||
"stdev": 42.279,
|
||||
"min": 1305.547,
|
||||
"max": 1390.037,
|
||||
"ci95": 105.035
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.669,
|
||||
"stdev": 0.084,
|
||||
"min": 0.598,
|
||||
"max": 0.761,
|
||||
"ci95": 0.208
|
||||
},
|
||||
"cpu.forest.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.222,
|
||||
"stdev": 0.032,
|
||||
"min": 0.197,
|
||||
"max": 0.258,
|
||||
"ci95": 0.079
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 2463.434,
|
||||
"stdev": 1056.0,
|
||||
"min": 1527.516,
|
||||
"max": 3608.283,
|
||||
"ci95": 2623.462
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 14226.667,
|
||||
"stdev": 307.077,
|
||||
"min": 14038.0,
|
||||
"max": 14581.0,
|
||||
"ci95": 762.883
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2192.874,
|
||||
"stdev": 1320.904,
|
||||
"min": 673.829,
|
||||
"max": 3071.415,
|
||||
"ci95": 3281.573
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 345.406,
|
||||
"stdev": 294.904,
|
||||
"min": 8.977,
|
||||
"max": 559.232,
|
||||
"ci95": 732.642
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 172.573,
|
||||
"stdev": 149.386,
|
||||
"min": 1.038,
|
||||
"max": 274.089,
|
||||
"ci95": 371.125
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 629.0,
|
||||
"stdev": 32.0,
|
||||
"min": 597.0,
|
||||
"max": 661.0,
|
||||
"ci95": 79.499
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1352.223,
|
||||
"stdev": 51.951,
|
||||
"min": 1301.492,
|
||||
"max": 1405.314,
|
||||
"ci95": 129.065
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.512,
|
||||
"stdev": 0.099,
|
||||
"min": 0.406,
|
||||
"max": 0.603,
|
||||
"ci95": 0.246
|
||||
},
|
||||
"cpu.ocean.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.178,
|
||||
"stdev": 0.038,
|
||||
"min": 0.135,
|
||||
"max": 0.206,
|
||||
"ci95": 0.094
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6260.675,
|
||||
"stdev": 3077.348,
|
||||
"min": 2976.342,
|
||||
"max": 9077.55,
|
||||
"ci95": 7645.173
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 16015.333,
|
||||
"stdev": 209.872,
|
||||
"min": 15826.0,
|
||||
"max": 16241.0,
|
||||
"ci95": 521.393
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1412.095,
|
||||
"stdev": 962.145,
|
||||
"min": 714.773,
|
||||
"max": 2509.775,
|
||||
"ci95": 2390.293
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 182.479,
|
||||
"stdev": 177.563,
|
||||
"min": 13.364,
|
||||
"max": 367.429,
|
||||
"ci95": 441.126
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 88.451,
|
||||
"stdev": 87.578,
|
||||
"min": 1.526,
|
||||
"max": 176.667,
|
||||
"ci95": 217.572
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 799.667,
|
||||
"stdev": 18.475,
|
||||
"min": 789.0,
|
||||
"max": 821.0,
|
||||
"ci95": 45.899
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1491.572,
|
||||
"stdev": 36.719,
|
||||
"min": 1459.775,
|
||||
"max": 1531.76,
|
||||
"ci95": 91.221
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.697,
|
||||
"stdev": 0.155,
|
||||
"min": 0.602,
|
||||
"max": 0.876,
|
||||
"ci95": 0.386
|
||||
},
|
||||
"cpu.mountain.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.325,
|
||||
"stdev": 0.115,
|
||||
"min": 0.239,
|
||||
"max": 0.456,
|
||||
"ci95": 0.286
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1545.896,
|
||||
"stdev": 30.591,
|
||||
"min": 1524.965,
|
||||
"max": 1581.004,
|
||||
"ci95": 75.999
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1348.389,
|
||||
"stdev": 52.5,
|
||||
"min": 1296.172,
|
||||
"max": 1401.168,
|
||||
"ci95": 130.428
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 37594,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3132.783,
|
||||
"low_1pct_fps": 471.438,
|
||||
"low_01pct_fps": 124.796,
|
||||
"p50_ms": 0.271,
|
||||
"p95_ms": 0.494,
|
||||
"p99_ms": 1.127,
|
||||
"p999_ms": 2.15,
|
||||
"max_ms": 155.204,
|
||||
"cpu_p50_ms": 0.168,
|
||||
"gpu_p50_ms": 0.104,
|
||||
"histogram": [
|
||||
37151,
|
||||
394,
|
||||
30,
|
||||
8,
|
||||
5,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 38598,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3216.434,
|
||||
"low_1pct_fps": 300.631,
|
||||
"low_01pct_fps": 46.124,
|
||||
"p50_ms": 0.267,
|
||||
"p95_ms": 0.446,
|
||||
"p99_ms": 1.034,
|
||||
"p999_ms": 1.941,
|
||||
"max_ms": 493.993,
|
||||
"cpu_p50_ms": 0.162,
|
||||
"gpu_p50_ms": 0.104,
|
||||
"histogram": [
|
||||
38177,
|
||||
387,
|
||||
16,
|
||||
8,
|
||||
4,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 30318,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2526.453,
|
||||
"low_1pct_fps": 333.302,
|
||||
"low_01pct_fps": 102.199,
|
||||
"p50_ms": 0.305,
|
||||
"p95_ms": 0.757,
|
||||
"p99_ms": 1.69,
|
||||
"p999_ms": 3.539,
|
||||
"max_ms": 170.856,
|
||||
"cpu_p50_ms": 0.224,
|
||||
"gpu_p50_ms": 0.106,
|
||||
"histogram": [
|
||||
29368,
|
||||
759,
|
||||
139,
|
||||
35,
|
||||
11,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 34578,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2881.457,
|
||||
"low_1pct_fps": 549.487,
|
||||
"low_01pct_fps": 294.05,
|
||||
"p50_ms": 0.32,
|
||||
"p95_ms": 0.483,
|
||||
"p99_ms": 1.213,
|
||||
"p999_ms": 2.5,
|
||||
"max_ms": 5.358,
|
||||
"cpu_p50_ms": 0.197,
|
||||
"gpu_p50_ms": 0.154,
|
||||
"histogram": [
|
||||
34119,
|
||||
379,
|
||||
64,
|
||||
9,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 28489,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2374.055,
|
||||
"low_1pct_fps": 208.133,
|
||||
"low_01pct_fps": 39.777,
|
||||
"p50_ms": 0.313,
|
||||
"p95_ms": 0.937,
|
||||
"p99_ms": 1.863,
|
||||
"p999_ms": 4.318,
|
||||
"max_ms": 571.48,
|
||||
"cpu_p50_ms": 0.211,
|
||||
"gpu_p50_ms": 0.151,
|
||||
"histogram": [
|
||||
27193,
|
||||
1071,
|
||||
140,
|
||||
51,
|
||||
19,
|
||||
9,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 20945,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1745.365,
|
||||
"low_1pct_fps": 252.226,
|
||||
"low_01pct_fps": 148.375,
|
||||
"p50_ms": 0.343,
|
||||
"p95_ms": 1.505,
|
||||
"p99_ms": 2.758,
|
||||
"p999_ms": 5.341,
|
||||
"max_ms": 11.642,
|
||||
"cpu_p50_ms": 0.258,
|
||||
"gpu_p50_ms": 0.162,
|
||||
"histogram": [
|
||||
18145,
|
||||
2293,
|
||||
337,
|
||||
106,
|
||||
38,
|
||||
13,
|
||||
6,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 36856,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3071.415,
|
||||
"low_1pct_fps": 559.232,
|
||||
"low_01pct_fps": 274.089,
|
||||
"p50_ms": 0.286,
|
||||
"p95_ms": 0.492,
|
||||
"p99_ms": 1.179,
|
||||
"p999_ms": 2.711,
|
||||
"max_ms": 6.718,
|
||||
"cpu_p50_ms": 0.135,
|
||||
"gpu_p50_ms": 0.127,
|
||||
"histogram": [
|
||||
36366,
|
||||
405,
|
||||
60,
|
||||
13,
|
||||
10,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 34001,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2833.377,
|
||||
"low_1pct_fps": 468.008,
|
||||
"low_01pct_fps": 242.591,
|
||||
"p50_ms": 0.295,
|
||||
"p95_ms": 0.589,
|
||||
"p99_ms": 1.41,
|
||||
"p999_ms": 3.048,
|
||||
"max_ms": 7.7,
|
||||
"cpu_p50_ms": 0.206,
|
||||
"gpu_p50_ms": 0.126,
|
||||
"histogram": [
|
||||
33314,
|
||||
544,
|
||||
106,
|
||||
23,
|
||||
10,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 8086,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 673.829,
|
||||
"low_1pct_fps": 8.977,
|
||||
"low_01pct_fps": 1.038,
|
||||
"p50_ms": 0.302,
|
||||
"p95_ms": 0.665,
|
||||
"p99_ms": 2.495,
|
||||
"p999_ms": 15.716,
|
||||
"max_ms": 4849.364,
|
||||
"cpu_p50_ms": 0.194,
|
||||
"gpu_p50_ms": 0.128,
|
||||
"histogram": [
|
||||
7808,
|
||||
166,
|
||||
50,
|
||||
26,
|
||||
8,
|
||||
2,
|
||||
3,
|
||||
5,
|
||||
2,
|
||||
5,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 12141,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1011.738,
|
||||
"low_1pct_fps": 166.643,
|
||||
"low_01pct_fps": 87.16,
|
||||
"p50_ms": 0.641,
|
||||
"p95_ms": 2.642,
|
||||
"p99_ms": 4.468,
|
||||
"p999_ms": 7.821,
|
||||
"max_ms": 22.536,
|
||||
"cpu_p50_ms": 0.456,
|
||||
"gpu_p50_ms": 0.138,
|
||||
"histogram": [
|
||||
7840,
|
||||
2996,
|
||||
866,
|
||||
278,
|
||||
87,
|
||||
38,
|
||||
16,
|
||||
11,
|
||||
2,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 30118,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2509.775,
|
||||
"low_1pct_fps": 367.429,
|
||||
"low_01pct_fps": 176.667,
|
||||
"p50_ms": 0.316,
|
||||
"p95_ms": 0.771,
|
||||
"p99_ms": 1.931,
|
||||
"p999_ms": 4.2,
|
||||
"max_ms": 14.633,
|
||||
"cpu_p50_ms": 0.239,
|
||||
"gpu_p50_ms": 0.127,
|
||||
"histogram": [
|
||||
29101,
|
||||
775,
|
||||
173,
|
||||
38,
|
||||
16,
|
||||
8,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 8577,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 714.773,
|
||||
"low_1pct_fps": 13.364,
|
||||
"low_01pct_fps": 1.526,
|
||||
"p50_ms": 0.416,
|
||||
"p95_ms": 2.257,
|
||||
"p99_ms": 4.36,
|
||||
"p999_ms": 212.217,
|
||||
"max_ms": 1051.428,
|
||||
"cpu_p50_ms": 0.28,
|
||||
"gpu_p50_ms": 0.132,
|
||||
"histogram": [
|
||||
7017,
|
||||
978,
|
||||
377,
|
||||
111,
|
||||
39,
|
||||
24,
|
||||
10,
|
||||
6,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
2
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-desktop"
|
||||
}
|
||||
@@ -1,870 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T14:47:19Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "nightly-2026-11-04-67dad0d",
|
||||
"commit": "67dad0d"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 24,
|
||||
"os_version": "NixOS 26.05 (Yarara) (kernel 6.18.57)",
|
||||
"cpu": "13th Gen Intel(R) Core(TM) i7-13700KF",
|
||||
"ram_mb": 31904,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 4080",
|
||||
"vendor": "nvidia",
|
||||
"driver": "NVIDIA 595.71.05",
|
||||
"backend": "vulkan",
|
||||
"kind": "discrete"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 29.665,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 45386.16,
|
||||
"stdev": 38970.921,
|
||||
"min": 1077.276,
|
||||
"max": 74343.156,
|
||||
"ci95": 96816.948
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 86585.608,
|
||||
"stdev": 71331.593,
|
||||
"min": 11201.581,
|
||||
"max": 153020.143,
|
||||
"ci95": 177211.803
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 11082.587,
|
||||
"stdev": 5351.291,
|
||||
"min": 7620.454,
|
||||
"max": 17246.096,
|
||||
"ci95": 13294.417
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 48440.333,
|
||||
"stdev": 656.16,
|
||||
"min": 48060.0,
|
||||
"max": 49198.0,
|
||||
"ci95": 1630.124
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 853.775,
|
||||
"stdev": 345.646,
|
||||
"min": 524.913,
|
||||
"max": 1214.059,
|
||||
"ci95": 858.701
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 130.235,
|
||||
"stdev": 117.39,
|
||||
"min": 9.024,
|
||||
"max": 243.388,
|
||||
"ci95": 291.635
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 70.65,
|
||||
"stdev": 68.628,
|
||||
"min": 1.125,
|
||||
"max": 138.345,
|
||||
"ci95": 170.496
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 2202.333,
|
||||
"stdev": 33.307,
|
||||
"min": 2165.0,
|
||||
"max": 2229.0,
|
||||
"ci95": 82.745
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1652.647,
|
||||
"stdev": 73.452,
|
||||
"min": 1568.063,
|
||||
"max": 1700.344,
|
||||
"ci95": 182.478
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.493,
|
||||
"stdev": 0.169,
|
||||
"min": 0.319,
|
||||
"max": 0.657,
|
||||
"ci95": 0.42
|
||||
},
|
||||
"cpu.village.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.692,
|
||||
"stdev": 0.207,
|
||||
"min": 0.531,
|
||||
"max": 0.925,
|
||||
"ci95": 0.513
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 15019.921,
|
||||
"stdev": 12855.4,
|
||||
"min": 5613.942,
|
||||
"max": 29668.11,
|
||||
"ci95": 31937.162
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 80224.667,
|
||||
"stdev": 678.709,
|
||||
"min": 79626.0,
|
||||
"max": 80962.0,
|
||||
"ci95": 1686.142
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 898.208,
|
||||
"stdev": 446.3,
|
||||
"min": 382.944,
|
||||
"max": 1163.61,
|
||||
"ci95": 1108.759
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 178.513,
|
||||
"stdev": 107.096,
|
||||
"min": 54.933,
|
||||
"max": 244.255,
|
||||
"ci95": 266.064
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 103.369,
|
||||
"stdev": 78.403,
|
||||
"min": 12.974,
|
||||
"max": 152.87,
|
||||
"ci95": 194.779
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 2201.667,
|
||||
"stdev": 34.429,
|
||||
"min": 2163.0,
|
||||
"max": 2229.0,
|
||||
"ci95": 85.532
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1809.063,
|
||||
"stdev": 93.103,
|
||||
"min": 1707.98,
|
||||
"max": 1891.305,
|
||||
"ci95": 231.3
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.585,
|
||||
"stdev": 0.147,
|
||||
"min": 0.493,
|
||||
"max": 0.754,
|
||||
"ci95": 0.365
|
||||
},
|
||||
"cpu.forest.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.989,
|
||||
"stdev": 0.725,
|
||||
"min": 0.57,
|
||||
"max": 1.826,
|
||||
"ci95": 1.802
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 12399.047,
|
||||
"stdev": 15052.073,
|
||||
"min": 3174.115,
|
||||
"max": 29768.486,
|
||||
"ci95": 37394.441
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 64737.0,
|
||||
"stdev": 16149.666,
|
||||
"min": 46089.0,
|
||||
"max": 74089.0,
|
||||
"ci95": 40121.232
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 735.22,
|
||||
"stdev": 601.75,
|
||||
"min": 108.108,
|
||||
"max": 1307.912,
|
||||
"ci95": 1494.952
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 134.654,
|
||||
"stdev": 147.391,
|
||||
"min": 1.252,
|
||||
"max": 292.881,
|
||||
"ci95": 366.169
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 62.062,
|
||||
"stdev": 66.294,
|
||||
"min": 0.202,
|
||||
"max": 132.042,
|
||||
"ci95": 164.697
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 1942.333,
|
||||
"stdev": 251.725,
|
||||
"min": 1657.0,
|
||||
"max": 2133.0,
|
||||
"ci95": 625.369
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1812.661,
|
||||
"stdev": 102.065,
|
||||
"min": 1697.912,
|
||||
"max": 1893.313,
|
||||
"ci95": 253.564
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.421,
|
||||
"stdev": 0.227,
|
||||
"min": 0.193,
|
||||
"max": 0.646,
|
||||
"ci95": 0.563
|
||||
},
|
||||
"cpu.ocean.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.513,
|
||||
"stdev": 0.194,
|
||||
"min": 0.303,
|
||||
"max": 0.686,
|
||||
"ci95": 0.483
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 31815.539,
|
||||
"stdev": 36758.245,
|
||||
"min": 9582.166,
|
||||
"max": 74243.988,
|
||||
"ci95": 91319.913
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 90876.333,
|
||||
"stdev": 1525.588,
|
||||
"min": 89793.0,
|
||||
"max": 92621.0,
|
||||
"ci95": 3790.075
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 712.657,
|
||||
"stdev": 252.815,
|
||||
"min": 450.565,
|
||||
"max": 955.041,
|
||||
"ci95": 628.077
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 117.93,
|
||||
"stdev": 85.922,
|
||||
"min": 24.389,
|
||||
"max": 193.34,
|
||||
"ci95": 213.46
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 72.407,
|
||||
"stdev": 65.468,
|
||||
"min": 3.577,
|
||||
"max": 133.895,
|
||||
"ci95": 162.646
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 2783.667,
|
||||
"stdev": 48.881,
|
||||
"min": 2741.0,
|
||||
"max": 2837.0,
|
||||
"ci95": 121.436
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1931.359,
|
||||
"stdev": 106.681,
|
||||
"min": 1808.184,
|
||||
"max": 1994.242,
|
||||
"ci95": 265.031
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.03,
|
||||
"stdev": 0.685,
|
||||
"min": 0.564,
|
||||
"max": 1.817,
|
||||
"ci95": 1.702
|
||||
},
|
||||
"cpu.mountain.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.025,
|
||||
"stdev": 0.315,
|
||||
"min": 0.765,
|
||||
"max": 1.376,
|
||||
"ci95": 0.783
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2051.333,
|
||||
"stdev": 147.151,
|
||||
"min": 1884.176,
|
||||
"max": 2161.316,
|
||||
"ci95": 365.573
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1810.92,
|
||||
"stdev": 94.623,
|
||||
"min": 1707.342,
|
||||
"max": 1892.828,
|
||||
"ci95": 235.075
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 6301,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 524.913,
|
||||
"low_1pct_fps": 9.024,
|
||||
"low_01pct_fps": 1.125,
|
||||
"p50_ms": 0.555,
|
||||
"p95_ms": 2.072,
|
||||
"p99_ms": 4.067,
|
||||
"p999_ms": 282.455,
|
||||
"max_ms": 3525.74,
|
||||
"cpu_p50_ms": 0.531,
|
||||
"gpu_p50_ms": 0.218,
|
||||
"histogram": [
|
||||
4878,
|
||||
1060,
|
||||
217,
|
||||
86,
|
||||
19,
|
||||
15,
|
||||
6,
|
||||
2,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
4,
|
||||
3,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 9869,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 822.353,
|
||||
"low_1pct_fps": 138.293,
|
||||
"low_01pct_fps": 72.479,
|
||||
"p50_ms": 0.976,
|
||||
"p95_ms": 2.871,
|
||||
"p99_ms": 5.065,
|
||||
"p999_ms": 9.942,
|
||||
"max_ms": 23.337,
|
||||
"cpu_p50_ms": 0.925,
|
||||
"gpu_p50_ms": 0.245,
|
||||
"histogram": [
|
||||
5262,
|
||||
3404,
|
||||
771,
|
||||
248,
|
||||
81,
|
||||
49,
|
||||
23,
|
||||
11,
|
||||
12,
|
||||
3,
|
||||
0,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 14570,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1214.059,
|
||||
"low_1pct_fps": 243.388,
|
||||
"low_01pct_fps": 138.345,
|
||||
"p50_ms": 0.655,
|
||||
"p95_ms": 1.486,
|
||||
"p99_ms": 2.883,
|
||||
"p999_ms": 5.366,
|
||||
"max_ms": 26.145,
|
||||
"cpu_p50_ms": 0.62,
|
||||
"gpu_p50_ms": 0.239,
|
||||
"histogram": [
|
||||
11502,
|
||||
2683,
|
||||
257,
|
||||
77,
|
||||
25,
|
||||
23,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 4595,
|
||||
"seconds": 11.999,
|
||||
"avg_fps": 382.944,
|
||||
"low_1pct_fps": 54.933,
|
||||
"low_01pct_fps": 12.974,
|
||||
"p50_ms": 2.269,
|
||||
"p95_ms": 5.193,
|
||||
"p99_ms": 8.719,
|
||||
"p999_ms": 21.933,
|
||||
"max_ms": 243.247,
|
||||
"cpu_p50_ms": 1.826,
|
||||
"gpu_p50_ms": 0.502,
|
||||
"histogram": [
|
||||
273,
|
||||
1654,
|
||||
1395,
|
||||
836,
|
||||
172,
|
||||
122,
|
||||
52,
|
||||
38,
|
||||
26,
|
||||
10,
|
||||
7,
|
||||
5,
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 13964,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1163.61,
|
||||
"low_1pct_fps": 244.255,
|
||||
"low_01pct_fps": 152.87,
|
||||
"p50_ms": 0.682,
|
||||
"p95_ms": 1.524,
|
||||
"p99_ms": 2.877,
|
||||
"p999_ms": 5.801,
|
||||
"max_ms": 7.977,
|
||||
"cpu_p50_ms": 0.57,
|
||||
"gpu_p50_ms": 0.467,
|
||||
"histogram": [
|
||||
11067,
|
||||
2532,
|
||||
235,
|
||||
82,
|
||||
23,
|
||||
16,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 13777,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1148.071,
|
||||
"low_1pct_fps": 236.351,
|
||||
"low_01pct_fps": 144.264,
|
||||
"p50_ms": 0.691,
|
||||
"p95_ms": 1.637,
|
||||
"p99_ms": 3.131,
|
||||
"p999_ms": 5.794,
|
||||
"max_ms": 9.301,
|
||||
"cpu_p50_ms": 0.57,
|
||||
"gpu_p50_ms": 0.465,
|
||||
"histogram": [
|
||||
10826,
|
||||
2511,
|
||||
284,
|
||||
106,
|
||||
23,
|
||||
16,
|
||||
5,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 1224,
|
||||
"seconds": 11.322,
|
||||
"avg_fps": 108.108,
|
||||
"low_1pct_fps": 1.252,
|
||||
"low_01pct_fps": 0.202,
|
||||
"p50_ms": 0.439,
|
||||
"p95_ms": 3.015,
|
||||
"p99_ms": 7.359,
|
||||
"p999_ms": 2880.23,
|
||||
"max_ms": 7005.436,
|
||||
"cpu_p50_ms": 0.303,
|
||||
"gpu_p50_ms": 0.258,
|
||||
"histogram": [
|
||||
1081,
|
||||
31,
|
||||
49,
|
||||
10,
|
||||
3,
|
||||
7,
|
||||
23,
|
||||
12,
|
||||
4,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 15695,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1307.912,
|
||||
"low_1pct_fps": 292.881,
|
||||
"low_01pct_fps": 132.042,
|
||||
"p50_ms": 0.624,
|
||||
"p95_ms": 1.219,
|
||||
"p99_ms": 2.173,
|
||||
"p999_ms": 4.841,
|
||||
"max_ms": 16.764,
|
||||
"cpu_p50_ms": 0.551,
|
||||
"gpu_p50_ms": 0.401,
|
||||
"histogram": [
|
||||
13558,
|
||||
1932,
|
||||
140,
|
||||
37,
|
||||
14,
|
||||
6,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 9476,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 789.641,
|
||||
"low_1pct_fps": 109.83,
|
||||
"low_01pct_fps": 53.941,
|
||||
"p50_ms": 0.802,
|
||||
"p95_ms": 3.406,
|
||||
"p99_ms": 5.844,
|
||||
"p999_ms": 14.977,
|
||||
"max_ms": 22.481,
|
||||
"cpu_p50_ms": 0.686,
|
||||
"gpu_p50_ms": 0.403,
|
||||
"histogram": [
|
||||
5819,
|
||||
2151,
|
||||
787,
|
||||
455,
|
||||
112,
|
||||
65,
|
||||
36,
|
||||
18,
|
||||
7,
|
||||
7,
|
||||
7,
|
||||
5,
|
||||
4,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 5352,
|
||||
"seconds": 11.878,
|
||||
"avg_fps": 450.565,
|
||||
"low_1pct_fps": 24.389,
|
||||
"low_01pct_fps": 3.577,
|
||||
"p50_ms": 1.431,
|
||||
"p95_ms": 4.548,
|
||||
"p99_ms": 7.601,
|
||||
"p999_ms": 96.086,
|
||||
"max_ms": 714.027,
|
||||
"cpu_p50_ms": 1.376,
|
||||
"gpu_p50_ms": 0.398,
|
||||
"histogram": [
|
||||
1412,
|
||||
2323,
|
||||
811,
|
||||
460,
|
||||
138,
|
||||
84,
|
||||
49,
|
||||
34,
|
||||
13,
|
||||
9,
|
||||
8,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 8789,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 732.365,
|
||||
"low_1pct_fps": 136.06,
|
||||
"low_01pct_fps": 79.749,
|
||||
"p50_ms": 0.972,
|
||||
"p95_ms": 3.329,
|
||||
"p99_ms": 5.68,
|
||||
"p999_ms": 9.7,
|
||||
"max_ms": 18.289,
|
||||
"cpu_p50_ms": 0.935,
|
||||
"gpu_p50_ms": 0.383,
|
||||
"histogram": [
|
||||
4529,
|
||||
3007,
|
||||
715,
|
||||
287,
|
||||
120,
|
||||
61,
|
||||
37,
|
||||
16,
|
||||
12,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 11461,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 955.041,
|
||||
"low_1pct_fps": 193.34,
|
||||
"low_01pct_fps": 133.895,
|
||||
"p50_ms": 0.787,
|
||||
"p95_ms": 2.026,
|
||||
"p99_ms": 3.953,
|
||||
"p999_ms": 6.511,
|
||||
"max_ms": 9.761,
|
||||
"cpu_p50_ms": 0.765,
|
||||
"gpu_p50_ms": 0.379,
|
||||
"histogram": [
|
||||
7754,
|
||||
3114,
|
||||
328,
|
||||
165,
|
||||
46,
|
||||
33,
|
||||
14,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-desktop"
|
||||
}
|
||||
@@ -1,758 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "0.1.0",
|
||||
"commit": "1bd24e4042"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "",
|
||||
"driver": "",
|
||||
"backend": "metal",
|
||||
"kind": "integrated"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 113.978,
|
||||
"window": [
|
||||
1920,
|
||||
1080
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 1524.333,
|
||||
"stdev": 364.142,
|
||||
"min": 1112.127,
|
||||
"max": 1802.295,
|
||||
"ci95": 904.651
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 14001.774,
|
||||
"stdev": 8119.623,
|
||||
"min": 7466.904,
|
||||
"max": 23091.569,
|
||||
"ci95": 20171.889
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8159.696,
|
||||
"stdev": 3897.327,
|
||||
"min": 5313.528,
|
||||
"max": 12601.663,
|
||||
"ci95": 9682.279
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 25431.333,
|
||||
"stdev": 1389.728,
|
||||
"min": 24149.0,
|
||||
"max": 26908.0,
|
||||
"ci95": 3452.555
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 568.391,
|
||||
"stdev": 11.948,
|
||||
"min": 558.517,
|
||||
"max": 581.673,
|
||||
"ci95": 29.684
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 270.644,
|
||||
"stdev": 9.955,
|
||||
"min": 259.156,
|
||||
"max": 276.728,
|
||||
"ci95": 24.732
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 209.951,
|
||||
"stdev": 30.24,
|
||||
"min": 191.819,
|
||||
"max": 244.86,
|
||||
"ci95": 75.126
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8879.707,
|
||||
"stdev": 1758.259,
|
||||
"min": 7205.686,
|
||||
"max": 10711.562,
|
||||
"ci95": 4368.11
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 29366.667,
|
||||
"stdev": 273.35,
|
||||
"min": 29053.0,
|
||||
"max": 29554.0,
|
||||
"ci95": 679.094
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 333.026,
|
||||
"stdev": 1.469,
|
||||
"min": 331.478,
|
||||
"max": 334.4,
|
||||
"ci95": 3.649
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 193.014,
|
||||
"stdev": 11.504,
|
||||
"min": 185.57,
|
||||
"max": 206.264,
|
||||
"ci95": 28.58
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 137.067,
|
||||
"stdev": 28.701,
|
||||
"min": 108.337,
|
||||
"max": 165.738,
|
||||
"ci95": 71.302
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6399.435,
|
||||
"stdev": 2268.592,
|
||||
"min": 4346.111,
|
||||
"max": 8834.786,
|
||||
"ci95": 5635.949
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 25436.0,
|
||||
"stdev": 813.154,
|
||||
"min": 24718.0,
|
||||
"max": 26319.0,
|
||||
"ci95": 2020.149
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 411.986,
|
||||
"stdev": 1.42,
|
||||
"min": 410.981,
|
||||
"max": 413.61,
|
||||
"ci95": 3.527
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 209.307,
|
||||
"stdev": 10.427,
|
||||
"min": 197.391,
|
||||
"max": 216.759,
|
||||
"ci95": 25.905
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 126.88,
|
||||
"stdev": 17.642,
|
||||
"min": 106.534,
|
||||
"max": 137.93,
|
||||
"ci95": 43.829
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 14672.976,
|
||||
"stdev": 9832.9,
|
||||
"min": 8230.723,
|
||||
"max": 25990.951,
|
||||
"ci95": 24428.25
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 27715.0,
|
||||
"stdev": 1706.033,
|
||||
"min": 26572.0,
|
||||
"max": 29676.0,
|
||||
"ci95": 4238.362
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 357.149,
|
||||
"stdev": 2.391,
|
||||
"min": 355.009,
|
||||
"max": 359.73,
|
||||
"ci95": 5.941
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 199.658,
|
||||
"stdev": 12.172,
|
||||
"min": 187.504,
|
||||
"max": 211.847,
|
||||
"ci95": 30.238
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 154.465,
|
||||
"stdev": 13.484,
|
||||
"min": 144.923,
|
||||
"max": 169.891,
|
||||
"ci95": 33.498
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1892.0,
|
||||
"stdev": 49.025,
|
||||
"min": 1835.406,
|
||||
"max": 1921.438,
|
||||
"ci95": 121.794
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1616.755,
|
||||
"stdev": 47.256,
|
||||
"min": 1564.734,
|
||||
"max": 1657.031,
|
||||
"ci95": 117.4
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3083.815,
|
||||
"stdev": 25.002,
|
||||
"min": 3062.456,
|
||||
"max": 3111.315,
|
||||
"ci95": 62.113
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2495.271,
|
||||
"stdev": 36.569,
|
||||
"min": 2453.284,
|
||||
"max": 2520.151,
|
||||
"ci95": 90.85
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 6981,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 581.673,
|
||||
"low_1pct_fps": 276.049,
|
||||
"low_01pct_fps": 191.819,
|
||||
"p50_ms": 1.655,
|
||||
"p95_ms": 2.267,
|
||||
"p99_ms": 3.277,
|
||||
"p999_ms": 4.174,
|
||||
"max_ms": 7.418,
|
||||
"cpu_p50_ms": 0.955,
|
||||
"gpu_p50_ms": 1.646,
|
||||
"histogram": [
|
||||
0,
|
||||
6445,
|
||||
353,
|
||||
176,
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 6703,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 558.517,
|
||||
"low_1pct_fps": 276.728,
|
||||
"low_01pct_fps": 244.86,
|
||||
"p50_ms": 1.725,
|
||||
"p95_ms": 2.341,
|
||||
"p99_ms": 3.396,
|
||||
"p999_ms": 3.939,
|
||||
"max_ms": 4.185,
|
||||
"cpu_p50_ms": 0.767,
|
||||
"gpu_p50_ms": 1.708,
|
||||
"histogram": [
|
||||
17,
|
||||
6041,
|
||||
442,
|
||||
202,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 6780,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 564.982,
|
||||
"low_1pct_fps": 259.156,
|
||||
"low_01pct_fps": 193.174,
|
||||
"p50_ms": 1.707,
|
||||
"p95_ms": 2.311,
|
||||
"p99_ms": 3.407,
|
||||
"p999_ms": 4.984,
|
||||
"max_ms": 5.322,
|
||||
"cpu_p50_ms": 0.923,
|
||||
"gpu_p50_ms": 1.698,
|
||||
"histogram": [
|
||||
5,
|
||||
6118,
|
||||
480,
|
||||
163,
|
||||
8,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 3978,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 331.478,
|
||||
"low_1pct_fps": 187.208,
|
||||
"low_01pct_fps": 137.127,
|
||||
"p50_ms": 2.93,
|
||||
"p95_ms": 3.969,
|
||||
"p99_ms": 4.719,
|
||||
"p999_ms": 6.451,
|
||||
"max_ms": 8.835,
|
||||
"cpu_p50_ms": 0.857,
|
||||
"gpu_p50_ms": 2.92,
|
||||
"histogram": [
|
||||
0,
|
||||
29,
|
||||
2279,
|
||||
1541,
|
||||
109,
|
||||
14,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 3999,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 333.199,
|
||||
"low_1pct_fps": 185.57,
|
||||
"low_01pct_fps": 108.337,
|
||||
"p50_ms": 2.921,
|
||||
"p95_ms": 3.862,
|
||||
"p99_ms": 4.679,
|
||||
"p999_ms": 6.817,
|
||||
"max_ms": 11.683,
|
||||
"cpu_p50_ms": 0.828,
|
||||
"gpu_p50_ms": 2.903,
|
||||
"histogram": [
|
||||
3,
|
||||
16,
|
||||
2356,
|
||||
1511,
|
||||
97,
|
||||
12,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 4013,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 334.4,
|
||||
"low_1pct_fps": 206.264,
|
||||
"low_01pct_fps": 165.738,
|
||||
"p50_ms": 2.915,
|
||||
"p95_ms": 3.809,
|
||||
"p99_ms": 4.525,
|
||||
"p999_ms": 5.078,
|
||||
"max_ms": 8.228,
|
||||
"cpu_p50_ms": 0.861,
|
||||
"gpu_p50_ms": 2.899,
|
||||
"histogram": [
|
||||
1,
|
||||
18,
|
||||
2357,
|
||||
1553,
|
||||
77,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 4932,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 410.981,
|
||||
"low_1pct_fps": 216.759,
|
||||
"low_01pct_fps": 137.93,
|
||||
"p50_ms": 2.353,
|
||||
"p95_ms": 3.181,
|
||||
"p99_ms": 4.01,
|
||||
"p999_ms": 5.767,
|
||||
"max_ms": 9.713,
|
||||
"cpu_p50_ms": 0.888,
|
||||
"gpu_p50_ms": 2.343,
|
||||
"histogram": [
|
||||
0,
|
||||
163,
|
||||
4474,
|
||||
264,
|
||||
23,
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 4937,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 411.366,
|
||||
"low_1pct_fps": 213.772,
|
||||
"low_01pct_fps": 136.177,
|
||||
"p50_ms": 2.349,
|
||||
"p95_ms": 3.258,
|
||||
"p99_ms": 4.015,
|
||||
"p999_ms": 5.985,
|
||||
"max_ms": 8.539,
|
||||
"cpu_p50_ms": 0.871,
|
||||
"gpu_p50_ms": 2.339,
|
||||
"histogram": [
|
||||
0,
|
||||
202,
|
||||
4406,
|
||||
295,
|
||||
25,
|
||||
5,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 4963,
|
||||
"seconds": 11.999,
|
||||
"avg_fps": 413.61,
|
||||
"low_1pct_fps": 197.391,
|
||||
"low_01pct_fps": 106.534,
|
||||
"p50_ms": 2.335,
|
||||
"p95_ms": 3.214,
|
||||
"p99_ms": 4.111,
|
||||
"p999_ms": 7.65,
|
||||
"max_ms": 11.399,
|
||||
"cpu_p50_ms": 0.878,
|
||||
"gpu_p50_ms": 2.323,
|
||||
"histogram": [
|
||||
2,
|
||||
228,
|
||||
4417,
|
||||
274,
|
||||
28,
|
||||
7,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 4317,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 359.73,
|
||||
"low_1pct_fps": 211.847,
|
||||
"low_01pct_fps": 169.891,
|
||||
"p50_ms": 2.7,
|
||||
"p95_ms": 3.753,
|
||||
"p99_ms": 4.366,
|
||||
"p999_ms": 5.041,
|
||||
"max_ms": 8.726,
|
||||
"cpu_p50_ms": 1.113,
|
||||
"gpu_p50_ms": 2.687,
|
||||
"histogram": [
|
||||
0,
|
||||
68,
|
||||
3445,
|
||||
718,
|
||||
80,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 4281,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 356.707,
|
||||
"low_1pct_fps": 199.624,
|
||||
"low_01pct_fps": 144.923,
|
||||
"p50_ms": 2.712,
|
||||
"p95_ms": 3.806,
|
||||
"p99_ms": 4.535,
|
||||
"p999_ms": 5.453,
|
||||
"max_ms": 8.354,
|
||||
"cpu_p50_ms": 1.111,
|
||||
"gpu_p50_ms": 2.694,
|
||||
"histogram": [
|
||||
0,
|
||||
64,
|
||||
3353,
|
||||
717,
|
||||
138,
|
||||
5,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 4261,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 355.009,
|
||||
"low_1pct_fps": 187.504,
|
||||
"low_01pct_fps": 148.582,
|
||||
"p50_ms": 2.727,
|
||||
"p95_ms": 4.083,
|
||||
"p99_ms": 4.744,
|
||||
"p999_ms": 6.091,
|
||||
"max_ms": 7.442,
|
||||
"cpu_p50_ms": 1.126,
|
||||
"gpu_p50_ms": 2.711,
|
||||
"histogram": [
|
||||
0,
|
||||
155,
|
||||
3198,
|
||||
719,
|
||||
165,
|
||||
17,
|
||||
6,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-m4pro-1080p"
|
||||
}
|
||||
@@ -1,758 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T23:17:23Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "0.1.0",
|
||||
"commit": "1bd24e4042"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "",
|
||||
"driver": "",
|
||||
"backend": "metal",
|
||||
"kind": "integrated"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 28.236,
|
||||
"window": [
|
||||
1920,
|
||||
1080
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 2190.186,
|
||||
"stdev": 1780.667,
|
||||
"min": 906.481,
|
||||
"max": 4223.028,
|
||||
"ci95": 4423.779
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 14254.027,
|
||||
"stdev": 4604.903,
|
||||
"min": 10130.899,
|
||||
"max": 19223.339,
|
||||
"ci95": 11440.138
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6509.117,
|
||||
"stdev": 1616.283,
|
||||
"min": 5457.214,
|
||||
"max": 8370.17,
|
||||
"ci95": 4015.394
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 48522.333,
|
||||
"stdev": 1713.943,
|
||||
"min": 46732.0,
|
||||
"max": 50148.0,
|
||||
"ci95": 4258.014
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 326.473,
|
||||
"stdev": 6.811,
|
||||
"min": 319.588,
|
||||
"max": 333.208,
|
||||
"ci95": 16.921
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 152.497,
|
||||
"stdev": 34.142,
|
||||
"min": 116.575,
|
||||
"max": 184.525,
|
||||
"ci95": 84.82
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 122.567,
|
||||
"stdev": 33.914,
|
||||
"min": 87.235,
|
||||
"max": 154.858,
|
||||
"ci95": 84.254
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 10363.339,
|
||||
"stdev": 3122.178,
|
||||
"min": 6760.012,
|
||||
"max": 12265.121,
|
||||
"ci95": 7756.547
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 82591.667,
|
||||
"stdev": 1489.69,
|
||||
"min": 81053.0,
|
||||
"max": 84027.0,
|
||||
"ci95": 3700.895
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 165.414,
|
||||
"stdev": 4.368,
|
||||
"min": 162.757,
|
||||
"max": 170.455,
|
||||
"ci95": 10.851
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 103.992,
|
||||
"stdev": 20.41,
|
||||
"min": 83.527,
|
||||
"max": 124.346,
|
||||
"ci95": 50.705
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 94.785,
|
||||
"stdev": 24.344,
|
||||
"min": 69.796,
|
||||
"max": 118.428,
|
||||
"ci95": 60.478
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 10450.642,
|
||||
"stdev": 2599.832,
|
||||
"min": 7510.454,
|
||||
"max": 12445.71,
|
||||
"ci95": 6458.863
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 76405.667,
|
||||
"stdev": 649.936,
|
||||
"min": 75681.0,
|
||||
"max": 76937.0,
|
||||
"ci95": 1614.662
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 210.179,
|
||||
"stdev": 5.279,
|
||||
"min": 205.559,
|
||||
"max": 215.932,
|
||||
"ci95": 13.114
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 128.777,
|
||||
"stdev": 30.982,
|
||||
"min": 93.017,
|
||||
"max": 147.571,
|
||||
"ci95": 76.97
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 115.916,
|
||||
"stdev": 39.398,
|
||||
"min": 70.443,
|
||||
"max": 139.838,
|
||||
"ci95": 97.879
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 17168.619,
|
||||
"stdev": 3613.606,
|
||||
"min": 13749.902,
|
||||
"max": 20949.796,
|
||||
"ci95": 8977.42
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 91622.667,
|
||||
"stdev": 482.189,
|
||||
"min": 91089.0,
|
||||
"max": 92027.0,
|
||||
"ci95": 1197.921
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 190.088,
|
||||
"stdev": 2.175,
|
||||
"min": 187.78,
|
||||
"max": 192.099,
|
||||
"ci95": 5.403
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 108.92,
|
||||
"stdev": 14.244,
|
||||
"min": 92.641,
|
||||
"max": 119.094,
|
||||
"ci95": 35.388
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 91.132,
|
||||
"stdev": 12.82,
|
||||
"min": 76.343,
|
||||
"max": 99.09,
|
||||
"ci95": 31.849
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2536.536,
|
||||
"stdev": 40.31,
|
||||
"min": 2506.281,
|
||||
"max": 2582.297,
|
||||
"ci95": 100.144
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2195.922,
|
||||
"stdev": 37.757,
|
||||
"min": 2167.078,
|
||||
"max": 2238.656,
|
||||
"ci95": 93.8
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 5559.837,
|
||||
"stdev": 47.18,
|
||||
"min": 5505.457,
|
||||
"max": 5589.863,
|
||||
"ci95": 117.211
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 4373.034,
|
||||
"stdev": 82.743,
|
||||
"min": 4311.909,
|
||||
"max": 4467.191,
|
||||
"ci95": 205.561
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 3920,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 326.623,
|
||||
"low_1pct_fps": 116.575,
|
||||
"low_01pct_fps": 87.235,
|
||||
"p50_ms": 2.938,
|
||||
"p95_ms": 4.356,
|
||||
"p99_ms": 7.397,
|
||||
"p999_ms": 9.497,
|
||||
"max_ms": 13.274,
|
||||
"cpu_p50_ms": 1.611,
|
||||
"gpu_p50_ms": 2.871,
|
||||
"histogram": [
|
||||
0,
|
||||
115,
|
||||
2297,
|
||||
1271,
|
||||
149,
|
||||
33,
|
||||
10,
|
||||
24,
|
||||
18,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 3835,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 319.588,
|
||||
"low_1pct_fps": 156.39,
|
||||
"low_01pct_fps": 125.608,
|
||||
"p50_ms": 3.04,
|
||||
"p95_ms": 4.322,
|
||||
"p99_ms": 5.265,
|
||||
"p999_ms": 7.732,
|
||||
"max_ms": 8.183,
|
||||
"cpu_p50_ms": 1.733,
|
||||
"gpu_p50_ms": 2.936,
|
||||
"histogram": [
|
||||
0,
|
||||
1,
|
||||
1610,
|
||||
2006,
|
||||
142,
|
||||
51,
|
||||
15,
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 3999,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 333.208,
|
||||
"low_1pct_fps": 184.525,
|
||||
"low_01pct_fps": 154.858,
|
||||
"p50_ms": 2.9,
|
||||
"p95_ms": 4.01,
|
||||
"p99_ms": 4.955,
|
||||
"p999_ms": 6.193,
|
||||
"max_ms": 6.805,
|
||||
"cpu_p50_ms": 1.51,
|
||||
"gpu_p50_ms": 2.788,
|
||||
"histogram": [
|
||||
0,
|
||||
8,
|
||||
2499,
|
||||
1328,
|
||||
132,
|
||||
25,
|
||||
7,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 1957,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 163.03,
|
||||
"low_1pct_fps": 83.527,
|
||||
"low_01pct_fps": 69.796,
|
||||
"p50_ms": 6.011,
|
||||
"p95_ms": 8.032,
|
||||
"p99_ms": 10.903,
|
||||
"p999_ms": 14.322,
|
||||
"max_ms": 14.333,
|
||||
"cpu_p50_ms": 1.555,
|
||||
"gpu_p50_ms": 5.857,
|
||||
"histogram": [
|
||||
0,
|
||||
5,
|
||||
26,
|
||||
16,
|
||||
36,
|
||||
883,
|
||||
739,
|
||||
194,
|
||||
29,
|
||||
22,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 1954,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 162.757,
|
||||
"low_1pct_fps": 104.102,
|
||||
"low_01pct_fps": 96.13,
|
||||
"p50_ms": 5.98,
|
||||
"p95_ms": 7.665,
|
||||
"p99_ms": 9.049,
|
||||
"p999_ms": 10.323,
|
||||
"max_ms": 10.482,
|
||||
"cpu_p50_ms": 1.584,
|
||||
"gpu_p50_ms": 5.715,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
9,
|
||||
1028,
|
||||
737,
|
||||
130,
|
||||
46,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 2046,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 170.455,
|
||||
"low_1pct_fps": 124.346,
|
||||
"low_01pct_fps": 118.428,
|
||||
"p50_ms": 5.719,
|
||||
"p95_ms": 7.342,
|
||||
"p99_ms": 7.815,
|
||||
"p999_ms": 8.38,
|
||||
"max_ms": 8.506,
|
||||
"cpu_p50_ms": 1.384,
|
||||
"gpu_p50_ms": 5.572,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
26,
|
||||
1452,
|
||||
396,
|
||||
169,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 2467,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 205.559,
|
||||
"low_1pct_fps": 93.017,
|
||||
"low_01pct_fps": 70.443,
|
||||
"p50_ms": 4.708,
|
||||
"p95_ms": 6.6,
|
||||
"p99_ms": 9.432,
|
||||
"p999_ms": 13.566,
|
||||
"max_ms": 15.228,
|
||||
"cpu_p50_ms": 1.664,
|
||||
"gpu_p50_ms": 4.483,
|
||||
"histogram": [
|
||||
0,
|
||||
18,
|
||||
55,
|
||||
87,
|
||||
1811,
|
||||
290,
|
||||
143,
|
||||
27,
|
||||
20,
|
||||
13,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 2509,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 209.045,
|
||||
"low_1pct_fps": 145.742,
|
||||
"low_01pct_fps": 139.838,
|
||||
"p50_ms": 4.642,
|
||||
"p95_ms": 6.15,
|
||||
"p99_ms": 6.72,
|
||||
"p999_ms": 7.081,
|
||||
"max_ms": 7.254,
|
||||
"cpu_p50_ms": 1.74,
|
||||
"gpu_p50_ms": 4.376,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
78,
|
||||
2008,
|
||||
277,
|
||||
142,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 2591,
|
||||
"seconds": 11.999,
|
||||
"avg_fps": 215.932,
|
||||
"low_1pct_fps": 147.571,
|
||||
"low_01pct_fps": 137.466,
|
||||
"p50_ms": 4.466,
|
||||
"p95_ms": 5.947,
|
||||
"p99_ms": 6.512,
|
||||
"p999_ms": 7.262,
|
||||
"max_ms": 7.283,
|
||||
"cpu_p50_ms": 1.422,
|
||||
"gpu_p50_ms": 4.286,
|
||||
"histogram": [
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
111,
|
||||
2114,
|
||||
248,
|
||||
111,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 2285,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 190.386,
|
||||
"low_1pct_fps": 92.641,
|
||||
"low_01pct_fps": 76.343,
|
||||
"p50_ms": 5.038,
|
||||
"p95_ms": 7.005,
|
||||
"p99_ms": 9.383,
|
||||
"p999_ms": 11.731,
|
||||
"max_ms": 15.266,
|
||||
"cpu_p50_ms": 2.239,
|
||||
"gpu_p50_ms": 4.915,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
54,
|
||||
45,
|
||||
916,
|
||||
985,
|
||||
168,
|
||||
78,
|
||||
22,
|
||||
15,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 2306,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 192.099,
|
||||
"low_1pct_fps": 119.094,
|
||||
"low_01pct_fps": 99.09,
|
||||
"p50_ms": 5.017,
|
||||
"p95_ms": 6.58,
|
||||
"p99_ms": 7.586,
|
||||
"p999_ms": 9.195,
|
||||
"max_ms": 11.428,
|
||||
"cpu_p50_ms": 2.261,
|
||||
"gpu_p50_ms": 4.823,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
12,
|
||||
1070,
|
||||
1003,
|
||||
165,
|
||||
43,
|
||||
9,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 2254,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 187.78,
|
||||
"low_1pct_fps": 115.026,
|
||||
"low_01pct_fps": 97.962,
|
||||
"p50_ms": 5.175,
|
||||
"p95_ms": 6.791,
|
||||
"p99_ms": 7.916,
|
||||
"p999_ms": 9.284,
|
||||
"max_ms": 11.986,
|
||||
"cpu_p50_ms": 2.158,
|
||||
"gpu_p50_ms": 4.942,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
17,
|
||||
774,
|
||||
1199,
|
||||
182,
|
||||
69,
|
||||
12,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-m4pro-1080p"
|
||||
}
|
||||
@@ -1,758 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "0.1.0",
|
||||
"commit": "1bd24e4042"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "",
|
||||
"driver": "",
|
||||
"backend": "metal",
|
||||
"kind": "integrated"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 73.292,
|
||||
"window": [
|
||||
1920,
|
||||
1080
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 7204.239,
|
||||
"stdev": 1586.64,
|
||||
"min": 5409.683,
|
||||
"max": 8421.051,
|
||||
"ci95": 3941.749
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 11407.51,
|
||||
"stdev": 2085.692,
|
||||
"min": 9027.004,
|
||||
"max": 12913.993,
|
||||
"ci95": 5181.563
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 5116.146,
|
||||
"stdev": 744.611,
|
||||
"min": 4548.096,
|
||||
"max": 5959.13,
|
||||
"ci95": 1849.865
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 7220.0,
|
||||
"stdev": 137.292,
|
||||
"min": 7092.0,
|
||||
"max": 7365.0,
|
||||
"ci95": 341.079
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 540.213,
|
||||
"stdev": 182.263,
|
||||
"min": 432.911,
|
||||
"max": 750.659,
|
||||
"ci95": 452.803
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 195.561,
|
||||
"stdev": 75.888,
|
||||
"min": 141.859,
|
||||
"max": 282.38,
|
||||
"ci95": 188.533
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 134.559,
|
||||
"stdev": 74.125,
|
||||
"min": 87.663,
|
||||
"max": 220.016,
|
||||
"ci95": 184.153
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 7185.67,
|
||||
"stdev": 4093.192,
|
||||
"min": 4323.79,
|
||||
"max": 11874.133,
|
||||
"ci95": 10168.874
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 8302.667,
|
||||
"stdev": 538.894,
|
||||
"min": 7853.0,
|
||||
"max": 8900.0,
|
||||
"ci95": 1338.794
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 364.068,
|
||||
"stdev": 8.947,
|
||||
"min": 355.173,
|
||||
"max": 373.067,
|
||||
"ci95": 22.229
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 145.064,
|
||||
"stdev": 21.824,
|
||||
"min": 121.995,
|
||||
"max": 165.382,
|
||||
"ci95": 54.218
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 97.299,
|
||||
"stdev": 15.364,
|
||||
"min": 81.075,
|
||||
"max": 111.627,
|
||||
"ci95": 38.17
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 4944.497,
|
||||
"stdev": 1598.757,
|
||||
"min": 3816.976,
|
||||
"max": 6774.175,
|
||||
"ci95": 3971.854
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 7041.0,
|
||||
"stdev": 276.949,
|
||||
"min": 6821.0,
|
||||
"max": 7352.0,
|
||||
"ci95": 688.036
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 410.281,
|
||||
"stdev": 35.314,
|
||||
"min": 370.881,
|
||||
"max": 439.08,
|
||||
"ci95": 87.731
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 161.057,
|
||||
"stdev": 15.769,
|
||||
"min": 144.003,
|
||||
"max": 175.109,
|
||||
"ci95": 39.175
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 111.852,
|
||||
"stdev": 16.415,
|
||||
"min": 93.045,
|
||||
"max": 123.299,
|
||||
"ci95": 40.78
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8844.497,
|
||||
"stdev": 4291.678,
|
||||
"min": 5269.587,
|
||||
"max": 13604.075,
|
||||
"ci95": 10661.98
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 7381.0,
|
||||
"stdev": 88.606,
|
||||
"min": 7290.0,
|
||||
"max": 7467.0,
|
||||
"ci95": 220.127
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 466.294,
|
||||
"stdev": 2.738,
|
||||
"min": 464.707,
|
||||
"max": 469.455,
|
||||
"ci95": 6.801
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 164.71,
|
||||
"stdev": 21.73,
|
||||
"min": 141.437,
|
||||
"max": 184.468,
|
||||
"ci95": 53.984
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 90.643,
|
||||
"stdev": 14.864,
|
||||
"min": 76.851,
|
||||
"max": 106.387,
|
||||
"ci95": 36.928
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1536.969,
|
||||
"stdev": 19.205,
|
||||
"min": 1516.188,
|
||||
"max": 1554.063,
|
||||
"ci95": 47.711
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1379.422,
|
||||
"stdev": 9.712,
|
||||
"min": 1371.438,
|
||||
"max": 1390.234,
|
||||
"ci95": 24.129
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2093.701,
|
||||
"stdev": 13.714,
|
||||
"min": 2078.862,
|
||||
"max": 2105.909,
|
||||
"ci95": 34.07
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1883.495,
|
||||
"stdev": 10.346,
|
||||
"min": 1871.987,
|
||||
"max": 1892.026,
|
||||
"ci95": 25.702
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 9008,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 750.659,
|
||||
"low_1pct_fps": 282.38,
|
||||
"low_01pct_fps": 220.016,
|
||||
"p50_ms": 1.047,
|
||||
"p95_ms": 2.169,
|
||||
"p99_ms": 3.163,
|
||||
"p999_ms": 4.077,
|
||||
"max_ms": 5.462,
|
||||
"cpu_p50_ms": 0.447,
|
||||
"gpu_p50_ms": 1.021,
|
||||
"histogram": [
|
||||
3979,
|
||||
3877,
|
||||
1033,
|
||||
112,
|
||||
6,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 5245,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 437.07,
|
||||
"low_1pct_fps": 141.859,
|
||||
"low_01pct_fps": 87.663,
|
||||
"p50_ms": 1.822,
|
||||
"p95_ms": 4.165,
|
||||
"p99_ms": 5.399,
|
||||
"p999_ms": 10.052,
|
||||
"max_ms": 12.712,
|
||||
"cpu_p50_ms": 0.652,
|
||||
"gpu_p50_ms": 1.943,
|
||||
"histogram": [
|
||||
831,
|
||||
1968,
|
||||
606,
|
||||
1582,
|
||||
154,
|
||||
82,
|
||||
3,
|
||||
3,
|
||||
10,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 5195,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 432.911,
|
||||
"low_1pct_fps": 162.445,
|
||||
"low_01pct_fps": 95.997,
|
||||
"p50_ms": 1.806,
|
||||
"p95_ms": 4.202,
|
||||
"p99_ms": 5.259,
|
||||
"p999_ms": 7.591,
|
||||
"max_ms": 17.328,
|
||||
"cpu_p50_ms": 0.636,
|
||||
"gpu_p50_ms": 1.876,
|
||||
"histogram": [
|
||||
297,
|
||||
2502,
|
||||
650,
|
||||
1469,
|
||||
192,
|
||||
73,
|
||||
6,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 4262,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 355.173,
|
||||
"low_1pct_fps": 165.382,
|
||||
"low_01pct_fps": 111.627,
|
||||
"p50_ms": 2.917,
|
||||
"p95_ms": 3.854,
|
||||
"p99_ms": 5.022,
|
||||
"p999_ms": 7.808,
|
||||
"max_ms": 9.769,
|
||||
"cpu_p50_ms": 0.59,
|
||||
"gpu_p50_ms": 2.91,
|
||||
"histogram": [
|
||||
98,
|
||||
416,
|
||||
2506,
|
||||
1080,
|
||||
118,
|
||||
29,
|
||||
10,
|
||||
1,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 4477,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 373.067,
|
||||
"low_1pct_fps": 121.995,
|
||||
"low_01pct_fps": 81.075,
|
||||
"p50_ms": 2.243,
|
||||
"p95_ms": 4.687,
|
||||
"p99_ms": 5.835,
|
||||
"p999_ms": 11.831,
|
||||
"max_ms": 13.367,
|
||||
"cpu_p50_ms": 0.541,
|
||||
"gpu_p50_ms": 2.346,
|
||||
"histogram": [
|
||||
183,
|
||||
1975,
|
||||
392,
|
||||
887,
|
||||
903,
|
||||
99,
|
||||
12,
|
||||
6,
|
||||
11,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 4368,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 363.964,
|
||||
"low_1pct_fps": 147.816,
|
||||
"low_01pct_fps": 99.196,
|
||||
"p50_ms": 2.264,
|
||||
"p95_ms": 4.763,
|
||||
"p99_ms": 5.86,
|
||||
"p999_ms": 7.641,
|
||||
"max_ms": 11.427,
|
||||
"cpu_p50_ms": 0.562,
|
||||
"gpu_p50_ms": 2.203,
|
||||
"histogram": [
|
||||
73,
|
||||
1978,
|
||||
472,
|
||||
695,
|
||||
1004,
|
||||
104,
|
||||
35,
|
||||
3,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 4451,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 370.881,
|
||||
"low_1pct_fps": 175.109,
|
||||
"low_01pct_fps": 119.212,
|
||||
"p50_ms": 2.858,
|
||||
"p95_ms": 4.279,
|
||||
"p99_ms": 5.045,
|
||||
"p999_ms": 6.057,
|
||||
"max_ms": 10.866,
|
||||
"cpu_p50_ms": 0.609,
|
||||
"gpu_p50_ms": 2.922,
|
||||
"histogram": [
|
||||
193,
|
||||
1245,
|
||||
964,
|
||||
1732,
|
||||
270,
|
||||
42,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 5269,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 439.08,
|
||||
"low_1pct_fps": 144.003,
|
||||
"low_01pct_fps": 93.045,
|
||||
"p50_ms": 1.767,
|
||||
"p95_ms": 4.188,
|
||||
"p99_ms": 5.191,
|
||||
"p999_ms": 10.375,
|
||||
"max_ms": 11.271,
|
||||
"cpu_p50_ms": 0.545,
|
||||
"gpu_p50_ms": 1.815,
|
||||
"histogram": [
|
||||
1239,
|
||||
1550,
|
||||
644,
|
||||
1555,
|
||||
201,
|
||||
59,
|
||||
1,
|
||||
4,
|
||||
10,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 5051,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 420.881,
|
||||
"low_1pct_fps": 164.058,
|
||||
"low_01pct_fps": 123.299,
|
||||
"p50_ms": 1.872,
|
||||
"p95_ms": 4.455,
|
||||
"p99_ms": 5.38,
|
||||
"p999_ms": 6.923,
|
||||
"max_ms": 11.189,
|
||||
"cpu_p50_ms": 0.548,
|
||||
"gpu_p50_ms": 1.874,
|
||||
"histogram": [
|
||||
519,
|
||||
2114,
|
||||
673,
|
||||
1086,
|
||||
577,
|
||||
65,
|
||||
13,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 5635,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 469.455,
|
||||
"low_1pct_fps": 184.468,
|
||||
"low_01pct_fps": 106.387,
|
||||
"p50_ms": 1.626,
|
||||
"p95_ms": 3.874,
|
||||
"p99_ms": 4.614,
|
||||
"p999_ms": 5.913,
|
||||
"max_ms": 18.185,
|
||||
"cpu_p50_ms": 0.564,
|
||||
"gpu_p50_ms": 1.604,
|
||||
"histogram": [
|
||||
1491,
|
||||
1599,
|
||||
704,
|
||||
1688,
|
||||
128,
|
||||
20,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 5578,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 464.72,
|
||||
"low_1pct_fps": 141.437,
|
||||
"low_01pct_fps": 76.851,
|
||||
"p50_ms": 1.587,
|
||||
"p95_ms": 4.127,
|
||||
"p99_ms": 5.085,
|
||||
"p999_ms": 10.138,
|
||||
"max_ms": 21.644,
|
||||
"cpu_p50_ms": 0.588,
|
||||
"gpu_p50_ms": 1.625,
|
||||
"histogram": [
|
||||
1321,
|
||||
1798,
|
||||
770,
|
||||
1453,
|
||||
173,
|
||||
41,
|
||||
2,
|
||||
5,
|
||||
7,
|
||||
6,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 5576,
|
||||
"seconds": 11.999,
|
||||
"avg_fps": 464.707,
|
||||
"low_1pct_fps": 168.226,
|
||||
"low_01pct_fps": 88.692,
|
||||
"p50_ms": 1.627,
|
||||
"p95_ms": 4.154,
|
||||
"p99_ms": 4.908,
|
||||
"p999_ms": 9.555,
|
||||
"max_ms": 14.784,
|
||||
"cpu_p50_ms": 0.595,
|
||||
"gpu_p50_ms": 1.64,
|
||||
"histogram": [
|
||||
1054,
|
||||
2049,
|
||||
837,
|
||||
1377,
|
||||
217,
|
||||
32,
|
||||
3,
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-m4pro-1080p"
|
||||
}
|
||||
@@ -1,854 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T12:44:40Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "nightly-2026-11-04-67dad0d",
|
||||
"commit": "67dad0d"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "",
|
||||
"driver": "",
|
||||
"backend": "metal",
|
||||
"kind": "integrated"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 12,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 17.39,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 1516.155,
|
||||
"stdev": 34.227,
|
||||
"min": 1476.782,
|
||||
"max": 1538.813,
|
||||
"ci95": 85.032
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 4080.9,
|
||||
"stdev": 748.712,
|
||||
"min": 3273.516,
|
||||
"max": 4752.301,
|
||||
"ci95": 1860.054
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3363.749,
|
||||
"stdev": 224.552,
|
||||
"min": 3105.622,
|
||||
"max": 3514.059,
|
||||
"ci95": 557.864
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 15473.667,
|
||||
"stdev": 339.602,
|
||||
"min": 15123.0,
|
||||
"max": 15801.0,
|
||||
"ci95": 843.686
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 999.753,
|
||||
"stdev": 41.901,
|
||||
"min": 970.527,
|
||||
"max": 1047.758,
|
||||
"ci95": 104.095
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 336.821,
|
||||
"stdev": 17.834,
|
||||
"min": 318.068,
|
||||
"max": 353.566,
|
||||
"ci95": 44.306
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 263.782,
|
||||
"stdev": 31.556,
|
||||
"min": 227.767,
|
||||
"max": 286.582,
|
||||
"ci95": 78.395
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1147.654,
|
||||
"stdev": 31.82,
|
||||
"min": 1116.875,
|
||||
"max": 1180.422,
|
||||
"ci95": 79.052
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.414,
|
||||
"stdev": 0.036,
|
||||
"min": 0.373,
|
||||
"max": 0.44,
|
||||
"ci95": 0.089
|
||||
},
|
||||
"cpu.village.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.52,
|
||||
"stdev": 0.071,
|
||||
"min": 0.44,
|
||||
"max": 0.577,
|
||||
"ci95": 0.177
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3685.368,
|
||||
"stdev": 844.43,
|
||||
"min": 2932.117,
|
||||
"max": 4598.204,
|
||||
"ci95": 2097.85
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 16795.333,
|
||||
"stdev": 437.802,
|
||||
"min": 16325.0,
|
||||
"max": 17191.0,
|
||||
"ci95": 1087.648
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 592.615,
|
||||
"stdev": 20.339,
|
||||
"min": 580.401,
|
||||
"max": 616.094,
|
||||
"ci95": 50.529
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 250.069,
|
||||
"stdev": 31.227,
|
||||
"min": 217.065,
|
||||
"max": 279.149,
|
||||
"ci95": 77.58
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 151.684,
|
||||
"stdev": 77.064,
|
||||
"min": 64.033,
|
||||
"max": 208.811,
|
||||
"ci95": 191.454
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1064.344,
|
||||
"stdev": 148.185,
|
||||
"min": 901.203,
|
||||
"max": 1190.609,
|
||||
"ci95": 368.142
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.424,
|
||||
"stdev": 0.003,
|
||||
"min": 0.422,
|
||||
"max": 0.427,
|
||||
"ci95": 0.007
|
||||
},
|
||||
"cpu.forest.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.617,
|
||||
"stdev": 0.016,
|
||||
"min": 0.599,
|
||||
"max": 0.629,
|
||||
"ci95": 0.039
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3594.311,
|
||||
"stdev": 1381.026,
|
||||
"min": 2011.153,
|
||||
"max": 4551.541,
|
||||
"ci95": 3430.936
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 14527.0,
|
||||
"stdev": 319.629,
|
||||
"min": 14166.0,
|
||||
"max": 14774.0,
|
||||
"ci95": 794.068
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 789.003,
|
||||
"stdev": 25.076,
|
||||
"min": 766.83,
|
||||
"max": 816.216,
|
||||
"ci95": 62.297
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 276.887,
|
||||
"stdev": 51.785,
|
||||
"min": 217.373,
|
||||
"max": 311.665,
|
||||
"ci95": 128.651
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 169.278,
|
||||
"stdev": 29.119,
|
||||
"min": 137.156,
|
||||
"max": 193.944,
|
||||
"ci95": 72.341
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 982.995,
|
||||
"stdev": 287.819,
|
||||
"min": 651.109,
|
||||
"max": 1164.063,
|
||||
"ci95": 715.039
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.397,
|
||||
"stdev": 0.028,
|
||||
"min": 0.38,
|
||||
"max": 0.429,
|
||||
"ci95": 0.069
|
||||
},
|
||||
"cpu.ocean.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.569,
|
||||
"stdev": 0.045,
|
||||
"min": 0.533,
|
||||
"max": 0.62,
|
||||
"ci95": 0.112
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 5682.993,
|
||||
"stdev": 1272.063,
|
||||
"min": 4476.873,
|
||||
"max": 7012.069,
|
||||
"ci95": 3160.234
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 15640.0,
|
||||
"stdev": 204.105,
|
||||
"min": 15507.0,
|
||||
"max": 15875.0,
|
||||
"ci95": 507.067
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 716.475,
|
||||
"stdev": 8.139,
|
||||
"min": 707.613,
|
||||
"max": 723.617,
|
||||
"ci95": 20.221
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 313.736,
|
||||
"stdev": 3.759,
|
||||
"min": 311.007,
|
||||
"max": 318.023,
|
||||
"ci95": 9.338
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 270.042,
|
||||
"stdev": 19.572,
|
||||
"min": 247.802,
|
||||
"max": 284.642,
|
||||
"ci95": 48.624
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 997.474,
|
||||
"stdev": 231.733,
|
||||
"min": 790.266,
|
||||
"max": 1247.703,
|
||||
"ci95": 575.704
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.385,
|
||||
"stdev": 0.023,
|
||||
"min": 0.359,
|
||||
"max": 0.401,
|
||||
"ci95": 0.057
|
||||
},
|
||||
"cpu.mountain.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.609,
|
||||
"stdev": 0.044,
|
||||
"min": 0.56,
|
||||
"max": 0.645,
|
||||
"ci95": 0.109
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1213.255,
|
||||
"stdev": 81.897,
|
||||
"min": 1136.078,
|
||||
"max": 1299.172,
|
||||
"ci95": 203.461
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1034.279,
|
||||
"stdev": 188.802,
|
||||
"min": 816.453,
|
||||
"max": 1150.961,
|
||||
"ci95": 469.049
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2167.747,
|
||||
"stdev": 14.039,
|
||||
"min": 2153.721,
|
||||
"max": 2181.799,
|
||||
"ci95": 34.878
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1889.468,
|
||||
"stdev": 24.444,
|
||||
"min": 1862.799,
|
||||
"max": 1910.807,
|
||||
"ci95": 60.727
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 12573,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1047.758,
|
||||
"low_1pct_fps": 353.566,
|
||||
"low_01pct_fps": 286.582,
|
||||
"p50_ms": 0.921,
|
||||
"p95_ms": 1.077,
|
||||
"p99_ms": 2.675,
|
||||
"p999_ms": 2.946,
|
||||
"max_ms": 5.36,
|
||||
"cpu_p50_ms": 0.44,
|
||||
"gpu_p50_ms": 0.914,
|
||||
"histogram": [
|
||||
11056,
|
||||
1291,
|
||||
218,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 11646,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 970.527,
|
||||
"low_1pct_fps": 318.068,
|
||||
"low_01pct_fps": 227.767,
|
||||
"p50_ms": 0.973,
|
||||
"p95_ms": 1.264,
|
||||
"p99_ms": 2.805,
|
||||
"p999_ms": 3.808,
|
||||
"max_ms": 5.305,
|
||||
"cpu_p50_ms": 0.577,
|
||||
"gpu_p50_ms": 0.969,
|
||||
"histogram": [
|
||||
7035,
|
||||
4334,
|
||||
230,
|
||||
39,
|
||||
6,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 11771,
|
||||
"seconds": 11.999,
|
||||
"avg_fps": 980.973,
|
||||
"low_1pct_fps": 338.828,
|
||||
"low_01pct_fps": 276.996,
|
||||
"p50_ms": 0.985,
|
||||
"p95_ms": 1.157,
|
||||
"p99_ms": 2.779,
|
||||
"p999_ms": 3.068,
|
||||
"max_ms": 4.308,
|
||||
"cpu_p50_ms": 0.542,
|
||||
"gpu_p50_ms": 0.98,
|
||||
"histogram": [
|
||||
6880,
|
||||
4663,
|
||||
208,
|
||||
18,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 7394,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 616.094,
|
||||
"low_1pct_fps": 253.993,
|
||||
"low_01pct_fps": 182.207,
|
||||
"p50_ms": 1.565,
|
||||
"p95_ms": 1.915,
|
||||
"p99_ms": 3.329,
|
||||
"p999_ms": 4.661,
|
||||
"max_ms": 7.32,
|
||||
"cpu_p50_ms": 0.599,
|
||||
"gpu_p50_ms": 1.551,
|
||||
"histogram": [
|
||||
82,
|
||||
6988,
|
||||
144,
|
||||
162,
|
||||
14,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 6965,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 580.401,
|
||||
"low_1pct_fps": 217.065,
|
||||
"low_01pct_fps": 64.033,
|
||||
"p50_ms": 1.654,
|
||||
"p95_ms": 1.983,
|
||||
"p99_ms": 3.233,
|
||||
"p999_ms": 3.893,
|
||||
"max_ms": 81.863,
|
||||
"cpu_p50_ms": 0.629,
|
||||
"gpu_p50_ms": 1.645,
|
||||
"histogram": [
|
||||
11,
|
||||
6622,
|
||||
153,
|
||||
174,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 6977,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 581.35,
|
||||
"low_1pct_fps": 279.149,
|
||||
"low_01pct_fps": 208.811,
|
||||
"p50_ms": 1.659,
|
||||
"p95_ms": 2.006,
|
||||
"p99_ms": 3.273,
|
||||
"p999_ms": 3.982,
|
||||
"max_ms": 5.889,
|
||||
"cpu_p50_ms": 0.623,
|
||||
"gpu_p50_ms": 1.653,
|
||||
"histogram": [
|
||||
17,
|
||||
6606,
|
||||
164,
|
||||
186,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 9793,
|
||||
"seconds": 11.998,
|
||||
"avg_fps": 816.216,
|
||||
"low_1pct_fps": 301.624,
|
||||
"low_01pct_fps": 176.734,
|
||||
"p50_ms": 1.171,
|
||||
"p95_ms": 1.499,
|
||||
"p99_ms": 2.928,
|
||||
"p999_ms": 3.333,
|
||||
"max_ms": 23.472,
|
||||
"cpu_p50_ms": 0.533,
|
||||
"gpu_p50_ms": 1.163,
|
||||
"histogram": [
|
||||
259,
|
||||
9293,
|
||||
182,
|
||||
56,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 9202,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 766.83,
|
||||
"low_1pct_fps": 217.373,
|
||||
"low_01pct_fps": 137.156,
|
||||
"p50_ms": 1.226,
|
||||
"p95_ms": 1.912,
|
||||
"p99_ms": 3.396,
|
||||
"p999_ms": 6.003,
|
||||
"max_ms": 13.562,
|
||||
"cpu_p50_ms": 0.62,
|
||||
"gpu_p50_ms": 1.219,
|
||||
"histogram": [
|
||||
635,
|
||||
8130,
|
||||
261,
|
||||
124,
|
||||
27,
|
||||
15,
|
||||
7,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 9408,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 783.964,
|
||||
"low_1pct_fps": 311.665,
|
||||
"low_01pct_fps": 193.944,
|
||||
"p50_ms": 1.22,
|
||||
"p95_ms": 1.541,
|
||||
"p99_ms": 2.865,
|
||||
"p999_ms": 3.298,
|
||||
"max_ms": 13.861,
|
||||
"cpu_p50_ms": 0.555,
|
||||
"gpu_p50_ms": 1.214,
|
||||
"histogram": [
|
||||
100,
|
||||
9066,
|
||||
204,
|
||||
34,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 8618,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 718.194,
|
||||
"low_1pct_fps": 312.177,
|
||||
"low_01pct_fps": 277.681,
|
||||
"p50_ms": 1.338,
|
||||
"p95_ms": 1.664,
|
||||
"p99_ms": 3.068,
|
||||
"p999_ms": 3.364,
|
||||
"max_ms": 4.008,
|
||||
"cpu_p50_ms": 0.622,
|
||||
"gpu_p50_ms": 1.329,
|
||||
"histogram": [
|
||||
62,
|
||||
8301,
|
||||
130,
|
||||
125,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 8492,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 707.613,
|
||||
"low_1pct_fps": 311.007,
|
||||
"low_01pct_fps": 284.642,
|
||||
"p50_ms": 1.35,
|
||||
"p95_ms": 1.707,
|
||||
"p99_ms": 3.08,
|
||||
"p999_ms": 3.329,
|
||||
"max_ms": 3.796,
|
||||
"cpu_p50_ms": 0.645,
|
||||
"gpu_p50_ms": 1.342,
|
||||
"histogram": [
|
||||
32,
|
||||
8216,
|
||||
111,
|
||||
133,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 8684,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 723.617,
|
||||
"low_1pct_fps": 318.023,
|
||||
"low_01pct_fps": 247.802,
|
||||
"p50_ms": 1.318,
|
||||
"p95_ms": 1.699,
|
||||
"p99_ms": 2.875,
|
||||
"p999_ms": 3.573,
|
||||
"max_ms": 5.186,
|
||||
"cpu_p50_ms": 0.56,
|
||||
"gpu_p50_ms": 1.306,
|
||||
"histogram": [
|
||||
46,
|
||||
8389,
|
||||
199,
|
||||
49,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-macmini"
|
||||
}
|
||||
@@ -1,854 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T13:17:26Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "nightly-2026-11-04-67dad0d",
|
||||
"commit": "67dad0d"
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "",
|
||||
"driver": "",
|
||||
"backend": "metal",
|
||||
"kind": "integrated"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 17.712,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 1528.444,
|
||||
"stdev": 181.21,
|
||||
"min": 1319.58,
|
||||
"max": 1643.783,
|
||||
"ci95": 450.188
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 12368.716,
|
||||
"stdev": 6475.37,
|
||||
"min": 7168.429,
|
||||
"max": 19621.62,
|
||||
"ci95": 16087.01
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6926.208,
|
||||
"stdev": 3712.691,
|
||||
"min": 4208.555,
|
||||
"max": 11156.419,
|
||||
"ci95": 9223.581
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 46790.333,
|
||||
"stdev": 1381.89,
|
||||
"min": 45236.0,
|
||||
"max": 47880.0,
|
||||
"ci95": 3433.082
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 453.505,
|
||||
"stdev": 14.384,
|
||||
"min": 441.517,
|
||||
"max": 469.455,
|
||||
"ci95": 35.735
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 222.897,
|
||||
"stdev": 10.449,
|
||||
"min": 212.173,
|
||||
"max": 233.048,
|
||||
"ci95": 25.96
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 173.55,
|
||||
"stdev": 31.798,
|
||||
"min": 142.967,
|
||||
"max": 206.437,
|
||||
"ci95": 78.996
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1544.565,
|
||||
"stdev": 26.422,
|
||||
"min": 1516.75,
|
||||
"max": 1569.328,
|
||||
"ci95": 65.64
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.528,
|
||||
"stdev": 0.018,
|
||||
"min": 0.511,
|
||||
"max": 0.548,
|
||||
"ci95": 0.045
|
||||
},
|
||||
"cpu.village.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.496,
|
||||
"stdev": 0.049,
|
||||
"min": 1.453,
|
||||
"max": 1.549,
|
||||
"ci95": 0.121
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8297.116,
|
||||
"stdev": 689.909,
|
||||
"min": 7716.447,
|
||||
"max": 9059.776,
|
||||
"ci95": 1713.966
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 78617.667,
|
||||
"stdev": 494.532,
|
||||
"min": 78228.0,
|
||||
"max": 79174.0,
|
||||
"ci95": 1228.586
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 216.265,
|
||||
"stdev": 6.372,
|
||||
"min": 209.501,
|
||||
"max": 222.156,
|
||||
"ci95": 15.831
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 137.027,
|
||||
"stdev": 3.787,
|
||||
"min": 133.07,
|
||||
"max": 140.617,
|
||||
"ci95": 9.408
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 114.683,
|
||||
"stdev": 7.985,
|
||||
"min": 106.585,
|
||||
"max": 122.551,
|
||||
"ci95": 19.839
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1420.638,
|
||||
"stdev": 247.812,
|
||||
"min": 1266.047,
|
||||
"max": 1706.469,
|
||||
"ci95": 615.649
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.423,
|
||||
"stdev": 0.059,
|
||||
"min": 0.355,
|
||||
"max": 0.458,
|
||||
"ci95": 0.148
|
||||
},
|
||||
"cpu.forest.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.605,
|
||||
"stdev": 0.269,
|
||||
"min": 1.295,
|
||||
"max": 1.779,
|
||||
"ci95": 0.668
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8354.659,
|
||||
"stdev": 2877.749,
|
||||
"min": 5454.947,
|
||||
"max": 11209.93,
|
||||
"ci95": 7149.301
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 74315.667,
|
||||
"stdev": 63.106,
|
||||
"min": 74246.0,
|
||||
"max": 74369.0,
|
||||
"ci95": 156.776
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 274.828,
|
||||
"stdev": 4.993,
|
||||
"min": 270.041,
|
||||
"max": 280.004,
|
||||
"ci95": 12.404
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 165.765,
|
||||
"stdev": 7.21,
|
||||
"min": 157.538,
|
||||
"max": 170.985,
|
||||
"ci95": 17.912
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 140.185,
|
||||
"stdev": 9.74,
|
||||
"min": 129.976,
|
||||
"max": 149.377,
|
||||
"ci95": 24.198
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1306.578,
|
||||
"stdev": 97.011,
|
||||
"min": 1199.094,
|
||||
"max": 1387.641,
|
||||
"ci95": 241.007
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.416,
|
||||
"stdev": 0.029,
|
||||
"min": 0.392,
|
||||
"max": 0.448,
|
||||
"ci95": 0.071
|
||||
},
|
||||
"cpu.ocean.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.636,
|
||||
"stdev": 0.121,
|
||||
"min": 1.496,
|
||||
"max": 1.708,
|
||||
"ci95": 0.301
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 17124.873,
|
||||
"stdev": 3461.08,
|
||||
"min": 13599.217,
|
||||
"max": 20517.544,
|
||||
"ci95": 8598.494
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 91909.0,
|
||||
"stdev": 815.603,
|
||||
"min": 91157.0,
|
||||
"max": 92776.0,
|
||||
"ci95": 2026.235
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 242.657,
|
||||
"stdev": 3.405,
|
||||
"min": 240.66,
|
||||
"max": 246.588,
|
||||
"ci95": 8.459
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 110.95,
|
||||
"stdev": 14.622,
|
||||
"min": 99.907,
|
||||
"max": 127.532,
|
||||
"ci95": 36.325
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 51.329,
|
||||
"stdev": 28.253,
|
||||
"min": 30.391,
|
||||
"max": 83.465,
|
||||
"ci95": 70.191
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1451.688,
|
||||
"stdev": 127.471,
|
||||
"min": 1310.969,
|
||||
"max": 1559.43,
|
||||
"ci95": 316.681
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.614,
|
||||
"stdev": 0.017,
|
||||
"min": 0.594,
|
||||
"max": 0.627,
|
||||
"ci95": 0.043
|
||||
},
|
||||
"cpu.mountain.p50_ms": {
|
||||
"n": 3,
|
||||
"mean": 2.233,
|
||||
"stdev": 0.05,
|
||||
"min": 2.194,
|
||||
"max": 2.289,
|
||||
"ci95": 0.124
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1697.984,
|
||||
"stdev": 29.735,
|
||||
"min": 1667.406,
|
||||
"max": 1726.797,
|
||||
"ci95": 73.871
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1428.19,
|
||||
"stdev": 120.658,
|
||||
"min": 1333.0,
|
||||
"max": 1563.891,
|
||||
"ci95": 299.756
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 4921.753,
|
||||
"stdev": 30.436,
|
||||
"min": 4890.971,
|
||||
"max": 4951.831,
|
||||
"ci95": 75.613
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 4079.43,
|
||||
"stdev": 10.978,
|
||||
"min": 4068.049,
|
||||
"max": 4089.956,
|
||||
"ci95": 27.273
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 5634,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 469.455,
|
||||
"low_1pct_fps": 223.469,
|
||||
"low_01pct_fps": 171.246,
|
||||
"p50_ms": 2.054,
|
||||
"p95_ms": 2.492,
|
||||
"p99_ms": 3.993,
|
||||
"p999_ms": 5.425,
|
||||
"max_ms": 6.645,
|
||||
"cpu_p50_ms": 1.453,
|
||||
"gpu_p50_ms": 1.965,
|
||||
"histogram": [
|
||||
0,
|
||||
2082,
|
||||
3324,
|
||||
193,
|
||||
24,
|
||||
9,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 5395,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 449.543,
|
||||
"low_1pct_fps": 233.048,
|
||||
"low_01pct_fps": 206.437,
|
||||
"p50_ms": 2.155,
|
||||
"p95_ms": 2.611,
|
||||
"p99_ms": 4.068,
|
||||
"p999_ms": 4.456,
|
||||
"max_ms": 5.305,
|
||||
"cpu_p50_ms": 1.549,
|
||||
"gpu_p50_ms": 2.043,
|
||||
"histogram": [
|
||||
0,
|
||||
902,
|
||||
4255,
|
||||
206,
|
||||
29,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 5298,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 441.517,
|
||||
"low_1pct_fps": 212.173,
|
||||
"low_01pct_fps": 142.967,
|
||||
"p50_ms": 2.171,
|
||||
"p95_ms": 3.249,
|
||||
"p99_ms": 4.138,
|
||||
"p999_ms": 5.591,
|
||||
"max_ms": 9.676,
|
||||
"cpu_p50_ms": 1.485,
|
||||
"gpu_p50_ms": 2.092,
|
||||
"histogram": [
|
||||
0,
|
||||
709,
|
||||
4314,
|
||||
229,
|
||||
36,
|
||||
6,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 2606,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 217.137,
|
||||
"low_1pct_fps": 140.617,
|
||||
"low_01pct_fps": 106.585,
|
||||
"p50_ms": 4.471,
|
||||
"p95_ms": 5.926,
|
||||
"p99_ms": 6.575,
|
||||
"p999_ms": 7.735,
|
||||
"max_ms": 12.187,
|
||||
"cpu_p50_ms": 1.74,
|
||||
"gpu_p50_ms": 4.238,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
221,
|
||||
2094,
|
||||
172,
|
||||
110,
|
||||
8,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 2514,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 209.501,
|
||||
"low_1pct_fps": 137.393,
|
||||
"low_01pct_fps": 122.551,
|
||||
"p50_ms": 4.627,
|
||||
"p95_ms": 6.304,
|
||||
"p99_ms": 6.93,
|
||||
"p999_ms": 7.971,
|
||||
"max_ms": 8.506,
|
||||
"cpu_p50_ms": 1.779,
|
||||
"gpu_p50_ms": 4.409,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
35,
|
||||
2097,
|
||||
200,
|
||||
162,
|
||||
17,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 2667,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 222.156,
|
||||
"low_1pct_fps": 133.07,
|
||||
"low_01pct_fps": 114.913,
|
||||
"p50_ms": 4.37,
|
||||
"p95_ms": 5.756,
|
||||
"p99_ms": 6.742,
|
||||
"p999_ms": 8.444,
|
||||
"max_ms": 8.984,
|
||||
"cpu_p50_ms": 1.295,
|
||||
"gpu_p50_ms": 4.152,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
440,
|
||||
1978,
|
||||
144,
|
||||
85,
|
||||
16,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 3294,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 274.44,
|
||||
"low_1pct_fps": 157.538,
|
||||
"low_01pct_fps": 129.976,
|
||||
"p50_ms": 3.521,
|
||||
"p95_ms": 4.814,
|
||||
"p99_ms": 5.592,
|
||||
"p999_ms": 7.491,
|
||||
"max_ms": 7.868,
|
||||
"cpu_p50_ms": 1.703,
|
||||
"gpu_p50_ms": 3.277,
|
||||
"histogram": [
|
||||
0,
|
||||
4,
|
||||
55,
|
||||
2967,
|
||||
130,
|
||||
122,
|
||||
10,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 3241,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 270.041,
|
||||
"low_1pct_fps": 168.771,
|
||||
"low_01pct_fps": 141.201,
|
||||
"p50_ms": 3.578,
|
||||
"p95_ms": 4.942,
|
||||
"p99_ms": 5.631,
|
||||
"p999_ms": 6.498,
|
||||
"max_ms": 7.601,
|
||||
"cpu_p50_ms": 1.708,
|
||||
"gpu_p50_ms": 3.323,
|
||||
"histogram": [
|
||||
0,
|
||||
2,
|
||||
8,
|
||||
2970,
|
||||
110,
|
||||
144,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 3360,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 280.004,
|
||||
"low_1pct_fps": 170.985,
|
||||
"low_01pct_fps": 149.377,
|
||||
"p50_ms": 3.477,
|
||||
"p95_ms": 4.678,
|
||||
"p99_ms": 5.462,
|
||||
"p999_ms": 6.626,
|
||||
"max_ms": 6.788,
|
||||
"cpu_p50_ms": 1.496,
|
||||
"gpu_p50_ms": 3.23,
|
||||
"histogram": [
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
3125,
|
||||
129,
|
||||
90,
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 2888,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 240.66,
|
||||
"low_1pct_fps": 127.532,
|
||||
"low_01pct_fps": 83.465,
|
||||
"p50_ms": 3.984,
|
||||
"p95_ms": 5.171,
|
||||
"p99_ms": 6.823,
|
||||
"p999_ms": 9.168,
|
||||
"max_ms": 15.341,
|
||||
"cpu_p50_ms": 2.194,
|
||||
"gpu_p50_ms": 3.786,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
2048,
|
||||
638,
|
||||
144,
|
||||
33,
|
||||
16,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 2889,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 240.722,
|
||||
"low_1pct_fps": 99.907,
|
||||
"low_01pct_fps": 40.132,
|
||||
"p50_ms": 3.961,
|
||||
"p95_ms": 5.706,
|
||||
"p99_ms": 7.364,
|
||||
"p999_ms": 12.597,
|
||||
"max_ms": 49.156,
|
||||
"cpu_p50_ms": 2.289,
|
||||
"gpu_p50_ms": 3.802,
|
||||
"histogram": [
|
||||
0,
|
||||
5,
|
||||
126,
|
||||
1859,
|
||||
599,
|
||||
194,
|
||||
72,
|
||||
22,
|
||||
8,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 2959,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 246.588,
|
||||
"low_1pct_fps": 105.411,
|
||||
"low_01pct_fps": 30.391,
|
||||
"p50_ms": 3.851,
|
||||
"p95_ms": 5.353,
|
||||
"p99_ms": 6.248,
|
||||
"p999_ms": 9.05,
|
||||
"max_ms": 54.378,
|
||||
"cpu_p50_ms": 2.216,
|
||||
"gpu_p50_ms": 3.667,
|
||||
"histogram": [
|
||||
0,
|
||||
2,
|
||||
58,
|
||||
2196,
|
||||
462,
|
||||
196,
|
||||
32,
|
||||
10,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-macmini"
|
||||
}
|
||||
@@ -1,773 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T01:13:01Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "v0.2.97",
|
||||
"commit": null
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080",
|
||||
"vendor": "nvidia",
|
||||
"driver": "NVIDIA 617.42",
|
||||
"backend": "vulkan",
|
||||
"kind": "discrete"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 3158.208,
|
||||
"stdev": 215.77,
|
||||
"min": 3023.046,
|
||||
"max": 3407.049,
|
||||
"ci95": 536.046
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 7170.164,
|
||||
"stdev": 557.958,
|
||||
"min": 6703.242,
|
||||
"max": 7788.08,
|
||||
"ci95": 1386.157
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 1694.647,
|
||||
"stdev": 41.285,
|
||||
"min": 1653.122,
|
||||
"max": 1735.687,
|
||||
"ci95": 102.566
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 23544.0,
|
||||
"stdev": 47.127,
|
||||
"min": 23495.0,
|
||||
"max": 23589.0,
|
||||
"ci95": 117.081
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1711.652,
|
||||
"stdev": 77.412,
|
||||
"min": 1623.403,
|
||||
"max": 1768.093,
|
||||
"ci95": 192.317
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 593.407,
|
||||
"stdev": 32.279,
|
||||
"min": 571.485,
|
||||
"max": 630.473,
|
||||
"ci95": 80.191
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 358.473,
|
||||
"stdev": 27.832,
|
||||
"min": 326.35,
|
||||
"max": 375.353,
|
||||
"ci95": 69.143
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 631.813,
|
||||
"stdev": 8.381,
|
||||
"min": 626.803,
|
||||
"max": 641.489,
|
||||
"ci95": 20.822
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 2521.363,
|
||||
"stdev": 291.624,
|
||||
"min": 2336.881,
|
||||
"max": 2857.57,
|
||||
"ci95": 724.493
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 27346.667,
|
||||
"stdev": 57.934,
|
||||
"min": 27306.0,
|
||||
"max": 27413.0,
|
||||
"ci95": 143.927
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2423.783,
|
||||
"stdev": 55.746,
|
||||
"min": 2386.353,
|
||||
"max": 2487.851,
|
||||
"ci95": 138.493
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 709.165,
|
||||
"stdev": 66.309,
|
||||
"min": 638.666,
|
||||
"max": 770.286,
|
||||
"ci95": 164.734
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 401.039,
|
||||
"stdev": 40.413,
|
||||
"min": 354.472,
|
||||
"max": 426.929,
|
||||
"ci95": 100.399
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 705.008,
|
||||
"stdev": 6.062,
|
||||
"min": 698.466,
|
||||
"max": 710.435,
|
||||
"ci95": 15.06
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 2094.909,
|
||||
"stdev": 521.225,
|
||||
"min": 1758.024,
|
||||
"max": 2695.274,
|
||||
"ci95": 1294.9
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 24312.667,
|
||||
"stdev": 261.934,
|
||||
"min": 24116.0,
|
||||
"max": 24610.0,
|
||||
"ci95": 650.732
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2201.125,
|
||||
"stdev": 73.595,
|
||||
"min": 2153.6,
|
||||
"max": 2285.897,
|
||||
"ci95": 182.834
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 553.968,
|
||||
"stdev": 100.955,
|
||||
"min": 445.599,
|
||||
"max": 645.355,
|
||||
"ci95": 250.806
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 325.078,
|
||||
"stdev": 131.154,
|
||||
"min": 177.4,
|
||||
"max": 427.981,
|
||||
"ci95": 325.831
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 652.944,
|
||||
"stdev": 5.177,
|
||||
"min": 647.51,
|
||||
"max": 657.818,
|
||||
"ci95": 12.862
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3304.58,
|
||||
"stdev": 134.041,
|
||||
"min": 3155.996,
|
||||
"max": 3416.409,
|
||||
"ci95": 333.003
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 26591.0,
|
||||
"stdev": 57.472,
|
||||
"min": 26525.0,
|
||||
"max": 26630.0,
|
||||
"ci95": 142.779
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1961.086,
|
||||
"stdev": 39.725,
|
||||
"min": 1921.241,
|
||||
"max": 2000.69,
|
||||
"ci95": 98.69
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 536.973,
|
||||
"stdev": 38.828,
|
||||
"min": 495.61,
|
||||
"max": 572.635,
|
||||
"ci95": 96.461
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 296.586,
|
||||
"stdev": 30.236,
|
||||
"min": 275.859,
|
||||
"max": 331.281,
|
||||
"ci95": 75.118
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 896.941,
|
||||
"stdev": 5.177,
|
||||
"min": 891.506,
|
||||
"max": 901.814,
|
||||
"ci95": 12.862
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1458.578,
|
||||
"stdev": 3.229,
|
||||
"min": 1455.32,
|
||||
"max": 1461.777,
|
||||
"ci95": 8.022
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1236.28,
|
||||
"stdev": 4.869,
|
||||
"min": 1230.701,
|
||||
"max": 1239.672,
|
||||
"ci95": 12.096
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 21218,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1768.093,
|
||||
"low_1pct_fps": 630.473,
|
||||
"low_01pct_fps": 375.353,
|
||||
"p50_ms": 0.537,
|
||||
"p95_ms": 0.846,
|
||||
"p99_ms": 1.222,
|
||||
"p999_ms": 2.081,
|
||||
"max_ms": 6.256,
|
||||
"cpu_p50_ms": 0.38,
|
||||
"gpu_p50_ms": 0.104,
|
||||
"histogram": [
|
||||
20695,
|
||||
499,
|
||||
22,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 19482,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1623.403,
|
||||
"low_1pct_fps": 578.262,
|
||||
"low_01pct_fps": 373.717,
|
||||
"p50_ms": 0.586,
|
||||
"p95_ms": 0.95,
|
||||
"p99_ms": 1.357,
|
||||
"p999_ms": 2.158,
|
||||
"max_ms": 7.35,
|
||||
"cpu_p50_ms": 0.445,
|
||||
"gpu_p50_ms": 0.104,
|
||||
"histogram": [
|
||||
18729,
|
||||
713,
|
||||
38,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 20922,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1743.46,
|
||||
"low_1pct_fps": 571.485,
|
||||
"low_01pct_fps": 326.35,
|
||||
"p50_ms": 0.526,
|
||||
"p95_ms": 0.883,
|
||||
"p99_ms": 1.313,
|
||||
"p999_ms": 2.14,
|
||||
"max_ms": 12.027,
|
||||
"cpu_p50_ms": 0.379,
|
||||
"gpu_p50_ms": 0.104,
|
||||
"histogram": [
|
||||
20308,
|
||||
582,
|
||||
28,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 29855,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2487.851,
|
||||
"low_1pct_fps": 770.286,
|
||||
"low_01pct_fps": 421.717,
|
||||
"p50_ms": 0.365,
|
||||
"p95_ms": 0.619,
|
||||
"p99_ms": 0.948,
|
||||
"p999_ms": 1.717,
|
||||
"max_ms": 9.446,
|
||||
"cpu_p50_ms": 0.232,
|
||||
"gpu_p50_ms": 0.157,
|
||||
"histogram": [
|
||||
29607,
|
||||
233,
|
||||
13,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 28766,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2397.145,
|
||||
"low_1pct_fps": 718.542,
|
||||
"low_01pct_fps": 426.929,
|
||||
"p50_ms": 0.374,
|
||||
"p95_ms": 0.662,
|
||||
"p99_ms": 1.016,
|
||||
"p999_ms": 1.858,
|
||||
"max_ms": 6.379,
|
||||
"cpu_p50_ms": 0.239,
|
||||
"gpu_p50_ms": 0.157,
|
||||
"histogram": [
|
||||
28457,
|
||||
293,
|
||||
14,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 28637,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2386.353,
|
||||
"low_1pct_fps": 638.666,
|
||||
"low_01pct_fps": 354.472,
|
||||
"p50_ms": 0.373,
|
||||
"p95_ms": 0.704,
|
||||
"p99_ms": 1.159,
|
||||
"p999_ms": 1.952,
|
||||
"max_ms": 14.388,
|
||||
"cpu_p50_ms": 0.233,
|
||||
"gpu_p50_ms": 0.157,
|
||||
"histogram": [
|
||||
28198,
|
||||
415,
|
||||
18,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 25968,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 2163.877,
|
||||
"low_1pct_fps": 570.949,
|
||||
"low_01pct_fps": 369.854,
|
||||
"p50_ms": 0.408,
|
||||
"p95_ms": 0.767,
|
||||
"p99_ms": 1.339,
|
||||
"p999_ms": 2.38,
|
||||
"max_ms": 3.329,
|
||||
"cpu_p50_ms": 0.271,
|
||||
"gpu_p50_ms": 0.141,
|
||||
"histogram": [
|
||||
25383,
|
||||
534,
|
||||
47,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 25843,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2153.6,
|
||||
"low_1pct_fps": 445.599,
|
||||
"low_01pct_fps": 177.4,
|
||||
"p50_ms": 0.413,
|
||||
"p95_ms": 0.725,
|
||||
"p99_ms": 1.309,
|
||||
"p999_ms": 3.451,
|
||||
"max_ms": 12.071,
|
||||
"cpu_p50_ms": 0.275,
|
||||
"gpu_p50_ms": 0.142,
|
||||
"histogram": [
|
||||
25375,
|
||||
373,
|
||||
56,
|
||||
22,
|
||||
1,
|
||||
7,
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 27431,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2285.897,
|
||||
"low_1pct_fps": 645.355,
|
||||
"low_01pct_fps": 427.981,
|
||||
"p50_ms": 0.388,
|
||||
"p95_ms": 0.693,
|
||||
"p99_ms": 1.163,
|
||||
"p999_ms": 2.041,
|
||||
"max_ms": 3.068,
|
||||
"cpu_p50_ms": 0.254,
|
||||
"gpu_p50_ms": 0.141,
|
||||
"histogram": [
|
||||
27036,
|
||||
363,
|
||||
31,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 23536,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1961.326,
|
||||
"low_1pct_fps": 542.675,
|
||||
"low_01pct_fps": 331.281,
|
||||
"p50_ms": 0.436,
|
||||
"p95_ms": 0.856,
|
||||
"p99_ms": 1.425,
|
||||
"p999_ms": 2.22,
|
||||
"max_ms": 9.458,
|
||||
"cpu_p50_ms": 0.296,
|
||||
"gpu_p50_ms": 0.14,
|
||||
"histogram": [
|
||||
22819,
|
||||
671,
|
||||
40,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 23056,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1921.241,
|
||||
"low_1pct_fps": 495.61,
|
||||
"low_01pct_fps": 282.617,
|
||||
"p50_ms": 0.44,
|
||||
"p95_ms": 0.911,
|
||||
"p99_ms": 1.516,
|
||||
"p999_ms": 2.543,
|
||||
"max_ms": 14.342,
|
||||
"cpu_p50_ms": 0.299,
|
||||
"gpu_p50_ms": 0.141,
|
||||
"histogram": [
|
||||
22198,
|
||||
783,
|
||||
65,
|
||||
7,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 24009,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2000.69,
|
||||
"low_1pct_fps": 572.635,
|
||||
"low_01pct_fps": 275.859,
|
||||
"p50_ms": 0.436,
|
||||
"p95_ms": 0.819,
|
||||
"p99_ms": 1.274,
|
||||
"p999_ms": 2.085,
|
||||
"max_ms": 14.003,
|
||||
"cpu_p50_ms": 0.297,
|
||||
"gpu_p50_ms": 0.14,
|
||||
"histogram": [
|
||||
23421,
|
||||
560,
|
||||
22,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,773 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T18:55:59Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "v0.2.97",
|
||||
"commit": null
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080",
|
||||
"vendor": "nvidia",
|
||||
"driver": "NVIDIA 617.42",
|
||||
"backend": "vulkan",
|
||||
"kind": "discrete"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 2897.812,
|
||||
"stdev": 82.455,
|
||||
"min": 2844.677,
|
||||
"max": 2992.8,
|
||||
"ci95": 204.846
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 10503.454,
|
||||
"stdev": 493.592,
|
||||
"min": 9934.491,
|
||||
"max": 10816.992,
|
||||
"ci95": 1226.251
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3717.47,
|
||||
"stdev": 1330.649,
|
||||
"min": 2942.872,
|
||||
"max": 5253.954,
|
||||
"ci95": 3305.783
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 47525.333,
|
||||
"stdev": 1369.122,
|
||||
"min": 46133.0,
|
||||
"max": 48870.0,
|
||||
"ci95": 3401.363
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1163.541,
|
||||
"stdev": 3.485,
|
||||
"min": 1159.52,
|
||||
"max": 1165.693,
|
||||
"ci95": 8.658
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 415.992,
|
||||
"stdev": 15.742,
|
||||
"min": 399.062,
|
||||
"max": 430.188,
|
||||
"ci95": 39.108
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 215.549,
|
||||
"stdev": 34.678,
|
||||
"min": 177.857,
|
||||
"max": 246.101,
|
||||
"ci95": 86.151
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 1833.432,
|
||||
"stdev": 4.415,
|
||||
"min": 1828.334,
|
||||
"max": 1835.997,
|
||||
"ci95": 10.969
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 5455.049,
|
||||
"stdev": 593.897,
|
||||
"min": 4973.659,
|
||||
"max": 6118.723,
|
||||
"ci95": 1475.44
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 82758.0,
|
||||
"stdev": 413.547,
|
||||
"min": 82487.0,
|
||||
"max": 83234.0,
|
||||
"ci95": 1027.39
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1389.46,
|
||||
"stdev": 28.128,
|
||||
"min": 1371.096,
|
||||
"max": 1421.843,
|
||||
"ci95": 69.88
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 504.377,
|
||||
"stdev": 13.251,
|
||||
"min": 492.444,
|
||||
"max": 518.637,
|
||||
"ci95": 32.919
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 329.682,
|
||||
"stdev": 47.451,
|
||||
"min": 294.872,
|
||||
"max": 383.732,
|
||||
"ci95": 117.885
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 1985.175,
|
||||
"stdev": 6.354,
|
||||
"min": 1978.907,
|
||||
"max": 1991.612,
|
||||
"ci95": 15.786
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 4504.145,
|
||||
"stdev": 745.393,
|
||||
"min": 3650.589,
|
||||
"max": 5026.8,
|
||||
"ci95": 1851.809
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 74927.333,
|
||||
"stdev": 399.375,
|
||||
"min": 74476.0,
|
||||
"max": 75235.0,
|
||||
"ci95": 992.182
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1188.639,
|
||||
"stdev": 10.807,
|
||||
"min": 1177.005,
|
||||
"max": 1198.365,
|
||||
"ci95": 26.849
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 154.773,
|
||||
"stdev": 3.712,
|
||||
"min": 151.38,
|
||||
"max": 158.738,
|
||||
"ci95": 9.223
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 67.809,
|
||||
"stdev": 3.032,
|
||||
"min": 65.903,
|
||||
"max": 71.305,
|
||||
"ci95": 7.532
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 2084.845,
|
||||
"stdev": 9.674,
|
||||
"min": 2074.009,
|
||||
"max": 2092.615,
|
||||
"ci95": 24.034
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 9048.431,
|
||||
"stdev": 344.33,
|
||||
"min": 8821.41,
|
||||
"max": 9444.624,
|
||||
"ci95": 855.432
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 89659.667,
|
||||
"stdev": 87.123,
|
||||
"min": 89561.0,
|
||||
"max": 89726.0,
|
||||
"ci95": 216.442
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1085.847,
|
||||
"stdev": 13.819,
|
||||
"min": 1070.378,
|
||||
"max": 1096.974,
|
||||
"ci95": 34.332
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 257.7,
|
||||
"stdev": 31.437,
|
||||
"min": 224.366,
|
||||
"max": 286.814,
|
||||
"ci95": 78.101
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 107.783,
|
||||
"stdev": 14.883,
|
||||
"min": 91.541,
|
||||
"max": 120.768,
|
||||
"ci95": 36.975
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 2708.833,
|
||||
"stdev": 9.674,
|
||||
"min": 2697.997,
|
||||
"max": 2716.603,
|
||||
"ci95": 24.034
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2044.895,
|
||||
"stdev": 10.562,
|
||||
"min": 2032.875,
|
||||
"max": 2052.691,
|
||||
"ci95": 26.238
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1730.107,
|
||||
"stdev": 14.764,
|
||||
"min": 1717.52,
|
||||
"max": 1746.357,
|
||||
"ci95": 36.678
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 13986,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1165.41,
|
||||
"low_1pct_fps": 399.062,
|
||||
"low_01pct_fps": 177.857,
|
||||
"p50_ms": 0.822,
|
||||
"p95_ms": 1.21,
|
||||
"p99_ms": 1.691,
|
||||
"p999_ms": 3.499,
|
||||
"max_ms": 13.089,
|
||||
"cpu_p50_ms": 0.665,
|
||||
"gpu_p50_ms": 0.193,
|
||||
"histogram": [
|
||||
12380,
|
||||
1527,
|
||||
58,
|
||||
13,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 13915,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1159.52,
|
||||
"low_1pct_fps": 430.188,
|
||||
"low_01pct_fps": 246.101,
|
||||
"p50_ms": 0.809,
|
||||
"p95_ms": 1.212,
|
||||
"p99_ms": 1.702,
|
||||
"p999_ms": 3.291,
|
||||
"max_ms": 6.894,
|
||||
"cpu_p50_ms": 0.648,
|
||||
"gpu_p50_ms": 0.192,
|
||||
"histogram": [
|
||||
11996,
|
||||
1839,
|
||||
59,
|
||||
17,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 13989,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1165.693,
|
||||
"low_1pct_fps": 418.725,
|
||||
"low_01pct_fps": 222.688,
|
||||
"p50_ms": 0.816,
|
||||
"p95_ms": 1.22,
|
||||
"p99_ms": 1.692,
|
||||
"p999_ms": 3.264,
|
||||
"max_ms": 7.781,
|
||||
"cpu_p50_ms": 0.669,
|
||||
"gpu_p50_ms": 0.193,
|
||||
"histogram": [
|
||||
12321,
|
||||
1578,
|
||||
72,
|
||||
11,
|
||||
2,
|
||||
4,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 17063,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1421.843,
|
||||
"low_1pct_fps": 502.049,
|
||||
"low_01pct_fps": 294.872,
|
||||
"p50_ms": 0.666,
|
||||
"p95_ms": 0.935,
|
||||
"p99_ms": 1.549,
|
||||
"p999_ms": 2.692,
|
||||
"max_ms": 6.831,
|
||||
"cpu_p50_ms": 0.533,
|
||||
"gpu_p50_ms": 0.362,
|
||||
"histogram": [
|
||||
16417,
|
||||
596,
|
||||
40,
|
||||
7,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 16454,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1371.096,
|
||||
"low_1pct_fps": 492.444,
|
||||
"low_01pct_fps": 310.443,
|
||||
"p50_ms": 0.688,
|
||||
"p95_ms": 0.979,
|
||||
"p99_ms": 1.556,
|
||||
"p999_ms": 2.693,
|
||||
"max_ms": 4.596,
|
||||
"cpu_p50_ms": 0.553,
|
||||
"gpu_p50_ms": 0.36,
|
||||
"histogram": [
|
||||
15692,
|
||||
697,
|
||||
57,
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 16506,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1375.442,
|
||||
"low_1pct_fps": 518.637,
|
||||
"low_01pct_fps": 383.732,
|
||||
"p50_ms": 0.675,
|
||||
"p95_ms": 1.017,
|
||||
"p99_ms": 1.605,
|
||||
"p999_ms": 2.369,
|
||||
"max_ms": 3.201,
|
||||
"cpu_p50_ms": 0.54,
|
||||
"gpu_p50_ms": 0.364,
|
||||
"histogram": [
|
||||
15628,
|
||||
833,
|
||||
44,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 14381,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1198.365,
|
||||
"low_1pct_fps": 154.2,
|
||||
"low_01pct_fps": 66.219,
|
||||
"p50_ms": 0.731,
|
||||
"p95_ms": 1.023,
|
||||
"p99_ms": 3.003,
|
||||
"p999_ms": 12.478,
|
||||
"max_ms": 18.863,
|
||||
"cpu_p50_ms": 0.596,
|
||||
"gpu_p50_ms": 0.315,
|
||||
"histogram": [
|
||||
13586,
|
||||
546,
|
||||
105,
|
||||
60,
|
||||
13,
|
||||
13,
|
||||
8,
|
||||
16,
|
||||
8,
|
||||
11,
|
||||
5,
|
||||
7,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 14287,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1190.548,
|
||||
"low_1pct_fps": 158.738,
|
||||
"low_01pct_fps": 71.305,
|
||||
"p50_ms": 0.741,
|
||||
"p95_ms": 1.041,
|
||||
"p99_ms": 2.9,
|
||||
"p999_ms": 12.0,
|
||||
"max_ms": 17.23,
|
||||
"cpu_p50_ms": 0.602,
|
||||
"gpu_p50_ms": 0.315,
|
||||
"histogram": [
|
||||
13450,
|
||||
591,
|
||||
109,
|
||||
57,
|
||||
13,
|
||||
8,
|
||||
10,
|
||||
11,
|
||||
14,
|
||||
10,
|
||||
7,
|
||||
6,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 14124,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1177.005,
|
||||
"low_1pct_fps": 151.38,
|
||||
"low_01pct_fps": 65.903,
|
||||
"p50_ms": 0.739,
|
||||
"p95_ms": 1.096,
|
||||
"p99_ms": 2.928,
|
||||
"p999_ms": 11.884,
|
||||
"max_ms": 19.375,
|
||||
"cpu_p50_ms": 0.604,
|
||||
"gpu_p50_ms": 0.314,
|
||||
"histogram": [
|
||||
13052,
|
||||
822,
|
||||
114,
|
||||
54,
|
||||
16,
|
||||
8,
|
||||
4,
|
||||
14,
|
||||
11,
|
||||
15,
|
||||
3,
|
||||
8,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 12845,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1070.378,
|
||||
"low_1pct_fps": 224.366,
|
||||
"low_01pct_fps": 91.541,
|
||||
"p50_ms": 0.825,
|
||||
"p95_ms": 1.362,
|
||||
"p99_ms": 2.325,
|
||||
"p999_ms": 9.621,
|
||||
"max_ms": 13.309,
|
||||
"cpu_p50_ms": 0.689,
|
||||
"gpu_p50_ms": 0.307,
|
||||
"histogram": [
|
||||
10937,
|
||||
1699,
|
||||
143,
|
||||
25,
|
||||
5,
|
||||
6,
|
||||
4,
|
||||
8,
|
||||
8,
|
||||
8,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 13083,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1090.188,
|
||||
"low_1pct_fps": 261.921,
|
||||
"low_01pct_fps": 111.039,
|
||||
"p50_ms": 0.816,
|
||||
"p95_ms": 1.335,
|
||||
"p99_ms": 2.14,
|
||||
"p999_ms": 8.222,
|
||||
"max_ms": 11.95,
|
||||
"cpu_p50_ms": 0.681,
|
||||
"gpu_p50_ms": 0.306,
|
||||
"histogram": [
|
||||
11105,
|
||||
1812,
|
||||
112,
|
||||
21,
|
||||
5,
|
||||
5,
|
||||
5,
|
||||
6,
|
||||
11,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 13164,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1096.974,
|
||||
"low_1pct_fps": 286.814,
|
||||
"low_01pct_fps": 120.768,
|
||||
"p50_ms": 0.822,
|
||||
"p95_ms": 1.307,
|
||||
"p99_ms": 1.989,
|
||||
"p999_ms": 7.701,
|
||||
"max_ms": 9.429,
|
||||
"cpu_p50_ms": 0.687,
|
||||
"gpu_p50_ms": 0.307,
|
||||
"histogram": [
|
||||
11280,
|
||||
1758,
|
||||
82,
|
||||
13,
|
||||
5,
|
||||
5,
|
||||
6,
|
||||
8,
|
||||
7,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,773 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T18:37:03Z",
|
||||
"app": {
|
||||
"name": "horizon-client",
|
||||
"version": "v0.2.97",
|
||||
"commit": null
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080",
|
||||
"vendor": "nvidia",
|
||||
"driver": "NVIDIA 617.42",
|
||||
"backend": "vulkan",
|
||||
"kind": "discrete"
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 2950.343,
|
||||
"stdev": 162.732,
|
||||
"min": 2822.925,
|
||||
"max": 3133.657,
|
||||
"ci95": 404.282
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 6135.1,
|
||||
"stdev": 863.831,
|
||||
"min": 5547.861,
|
||||
"max": 7126.98,
|
||||
"ci95": 2146.05
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 985.519,
|
||||
"stdev": 28.184,
|
||||
"min": 956.244,
|
||||
"max": 1012.469,
|
||||
"ci95": 70.019
|
||||
},
|
||||
"chunks.village.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 6908.0,
|
||||
"stdev": 9.849,
|
||||
"min": 6897.0,
|
||||
"max": 6916.0,
|
||||
"ci95": 24.468
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2941.608,
|
||||
"stdev": 79.283,
|
||||
"min": 2850.416,
|
||||
"max": 2994.188,
|
||||
"ci95": 196.965
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 1271.318,
|
||||
"stdev": 58.797,
|
||||
"min": 1203.758,
|
||||
"max": 1310.917,
|
||||
"ci95": 146.072
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 839.261,
|
||||
"stdev": 37.982,
|
||||
"min": 795.415,
|
||||
"max": 862.067,
|
||||
"ci95": 94.36
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 363.984,
|
||||
"stdev": 0.926,
|
||||
"min": 363.449,
|
||||
"max": 365.053,
|
||||
"ci95": 2.299
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 1350.752,
|
||||
"stdev": 293.128,
|
||||
"min": 1106.764,
|
||||
"max": 1675.913,
|
||||
"ci95": 728.23
|
||||
},
|
||||
"chunks.forest.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 8066.0,
|
||||
"stdev": 108.885,
|
||||
"min": 7986.0,
|
||||
"max": 8190.0,
|
||||
"ci95": 270.508
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 3494.693,
|
||||
"stdev": 110.997,
|
||||
"min": 3389.894,
|
||||
"max": 3610.993,
|
||||
"ci95": 275.755
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 1295.14,
|
||||
"stdev": 159.638,
|
||||
"min": 1148.468,
|
||||
"max": 1465.171,
|
||||
"ci95": 396.596
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 859.326,
|
||||
"stdev": 119.845,
|
||||
"min": 721.994,
|
||||
"max": 942.743,
|
||||
"ci95": 297.734
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 381.189,
|
||||
"stdev": 5.222,
|
||||
"min": 376.423,
|
||||
"max": 386.77,
|
||||
"ci95": 12.972
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 1123.386,
|
||||
"stdev": 604.175,
|
||||
"min": 734.302,
|
||||
"max": 1819.414,
|
||||
"ci95": 1500.976
|
||||
},
|
||||
"chunks.ocean.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 6613.0,
|
||||
"stdev": 135.632,
|
||||
"min": 6523.0,
|
||||
"max": 6769.0,
|
||||
"ci95": 336.955
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 3346.003,
|
||||
"stdev": 59.312,
|
||||
"min": 3303.535,
|
||||
"max": 3413.77,
|
||||
"ci95": 147.352
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 1357.991,
|
||||
"stdev": 95.364,
|
||||
"min": 1248.887,
|
||||
"max": 1425.451,
|
||||
"ci95": 236.917
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 911.822,
|
||||
"stdev": 94.717,
|
||||
"min": 802.528,
|
||||
"max": 969.989,
|
||||
"ci95": 235.308
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 391.636,
|
||||
"stdev": 5.435,
|
||||
"min": 387.424,
|
||||
"max": 397.771,
|
||||
"ci95": 13.502
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 1588.954,
|
||||
"stdev": 458.924,
|
||||
"min": 1309.548,
|
||||
"max": 2118.606,
|
||||
"ci95": 1140.123
|
||||
},
|
||||
"chunks.mountain.meshed_count": {
|
||||
"n": 3,
|
||||
"mean": 7887.667,
|
||||
"stdev": 41.041,
|
||||
"min": 7862.0,
|
||||
"max": 7935.0,
|
||||
"ci95": 101.959
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 3375.623,
|
||||
"stdev": 26.82,
|
||||
"min": 3352.309,
|
||||
"max": 3404.933,
|
||||
"ci95": 66.629
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 1383.745,
|
||||
"stdev": 67.628,
|
||||
"min": 1324.071,
|
||||
"max": 1457.203,
|
||||
"ci95": 168.01
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 850.213,
|
||||
"stdev": 103.149,
|
||||
"min": 790.305,
|
||||
"max": 969.318,
|
||||
"ci95": 256.256
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 448.64,
|
||||
"stdev": 5.435,
|
||||
"min": 444.428,
|
||||
"max": 454.775,
|
||||
"ci95": 13.502
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1171.629,
|
||||
"stdev": 0.337,
|
||||
"min": 1171.398,
|
||||
"max": 1172.016,
|
||||
"ci95": 0.837
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1082.078,
|
||||
"stdev": 12.494,
|
||||
"min": 1069.117,
|
||||
"max": 1094.047,
|
||||
"ci95": 31.04
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 35764,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2980.22,
|
||||
"low_1pct_fps": 1310.917,
|
||||
"low_01pct_fps": 860.301,
|
||||
"p50_ms": 0.317,
|
||||
"p95_ms": 0.433,
|
||||
"p99_ms": 0.633,
|
||||
"p999_ms": 0.937,
|
||||
"max_ms": 2.807,
|
||||
"cpu_p50_ms": 0.192,
|
||||
"gpu_p50_ms": 0.063,
|
||||
"histogram": [
|
||||
35741,
|
||||
22,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 35931,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2994.188,
|
||||
"low_1pct_fps": 1299.278,
|
||||
"low_01pct_fps": 795.415,
|
||||
"p50_ms": 0.318,
|
||||
"p95_ms": 0.428,
|
||||
"p99_ms": 0.62,
|
||||
"p999_ms": 0.943,
|
||||
"max_ms": 5.797,
|
||||
"cpu_p50_ms": 0.191,
|
||||
"gpu_p50_ms": 0.063,
|
||||
"histogram": [
|
||||
35906,
|
||||
23,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 34206,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2850.416,
|
||||
"low_1pct_fps": 1203.758,
|
||||
"low_01pct_fps": 862.067,
|
||||
"p50_ms": 0.326,
|
||||
"p95_ms": 0.508,
|
||||
"p99_ms": 0.705,
|
||||
"p999_ms": 1.025,
|
||||
"max_ms": 1.398,
|
||||
"cpu_p50_ms": 0.196,
|
||||
"gpu_p50_ms": 0.063,
|
||||
"histogram": [
|
||||
34167,
|
||||
39,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 41800,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3483.193,
|
||||
"low_1pct_fps": 1271.782,
|
||||
"low_01pct_fps": 913.242,
|
||||
"p50_ms": 0.264,
|
||||
"p95_ms": 0.415,
|
||||
"p99_ms": 0.657,
|
||||
"p999_ms": 0.935,
|
||||
"max_ms": 1.482,
|
||||
"cpu_p50_ms": 0.144,
|
||||
"gpu_p50_ms": 0.075,
|
||||
"histogram": [
|
||||
41768,
|
||||
32,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 43333,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3610.993,
|
||||
"low_1pct_fps": 1465.171,
|
||||
"low_01pct_fps": 942.743,
|
||||
"p50_ms": 0.263,
|
||||
"p95_ms": 0.355,
|
||||
"p99_ms": 0.561,
|
||||
"p999_ms": 0.859,
|
||||
"max_ms": 1.694,
|
||||
"cpu_p50_ms": 0.143,
|
||||
"gpu_p50_ms": 0.074,
|
||||
"histogram": [
|
||||
43310,
|
||||
23,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 40679,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3389.894,
|
||||
"low_1pct_fps": 1148.468,
|
||||
"low_01pct_fps": 721.994,
|
||||
"p50_ms": 0.267,
|
||||
"p95_ms": 0.446,
|
||||
"p99_ms": 0.67,
|
||||
"p999_ms": 1.183,
|
||||
"max_ms": 2.434,
|
||||
"cpu_p50_ms": 0.146,
|
||||
"gpu_p50_ms": 0.076,
|
||||
"histogram": [
|
||||
40590,
|
||||
87,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 39849,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3320.704,
|
||||
"low_1pct_fps": 1399.634,
|
||||
"low_01pct_fps": 969.989,
|
||||
"p50_ms": 0.281,
|
||||
"p95_ms": 0.404,
|
||||
"p99_ms": 0.601,
|
||||
"p999_ms": 0.875,
|
||||
"max_ms": 1.494,
|
||||
"cpu_p50_ms": 0.159,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
39831,
|
||||
18,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 40966,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3413.77,
|
||||
"low_1pct_fps": 1425.451,
|
||||
"low_01pct_fps": 962.948,
|
||||
"p50_ms": 0.278,
|
||||
"p95_ms": 0.372,
|
||||
"p99_ms": 0.581,
|
||||
"p999_ms": 0.857,
|
||||
"max_ms": 1.576,
|
||||
"cpu_p50_ms": 0.157,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
40947,
|
||||
19,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 39643,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3303.535,
|
||||
"low_1pct_fps": 1248.887,
|
||||
"low_01pct_fps": 802.528,
|
||||
"p50_ms": 0.28,
|
||||
"p95_ms": 0.413,
|
||||
"p99_ms": 0.642,
|
||||
"p999_ms": 1.087,
|
||||
"max_ms": 2.215,
|
||||
"cpu_p50_ms": 0.158,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
39582,
|
||||
60,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 40436,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3369.626,
|
||||
"low_1pct_fps": 1369.962,
|
||||
"low_01pct_fps": 790.305,
|
||||
"p50_ms": 0.279,
|
||||
"p95_ms": 0.403,
|
||||
"p99_ms": 0.604,
|
||||
"p999_ms": 0.812,
|
||||
"max_ms": 10.313,
|
||||
"cpu_p50_ms": 0.159,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
40425,
|
||||
8,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 40860,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3404.933,
|
||||
"low_1pct_fps": 1457.203,
|
||||
"low_01pct_fps": 969.318,
|
||||
"p50_ms": 0.278,
|
||||
"p95_ms": 0.389,
|
||||
"p99_ms": 0.574,
|
||||
"p999_ms": 0.814,
|
||||
"max_ms": 2.714,
|
||||
"cpu_p50_ms": 0.158,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
40847,
|
||||
11,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 40229,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3352.309,
|
||||
"low_1pct_fps": 1324.071,
|
||||
"low_01pct_fps": 791.016,
|
||||
"p50_ms": 0.28,
|
||||
"p95_ms": 0.402,
|
||||
"p99_ms": 0.617,
|
||||
"p999_ms": 0.968,
|
||||
"max_ms": 3.746,
|
||||
"cpu_p50_ms": 0.159,
|
||||
"gpu_p50_ms": 0.069,
|
||||
"histogram": [
|
||||
40192,
|
||||
35,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "horizon-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,787 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T13:28:55Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 24,
|
||||
"os_version": "NixOS 26.05 (Yarara) (kernel 6.18.57)",
|
||||
"cpu": "13th Gen Intel(R) Core(TM) i7-13700KF",
|
||||
"ram_mb": 31904,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 4080",
|
||||
"vendor": "NVIDIA",
|
||||
"driver": "1.4.329 NVIDIA 595.71.05",
|
||||
"backend": "vulkan",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 12,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 28.788,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 121075.467,
|
||||
"stdev": 30646.429,
|
||||
"min": 93272.034,
|
||||
"max": 153935.834,
|
||||
"ci95": 76136.094
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 191063.8,
|
||||
"stdev": 34368.16,
|
||||
"min": 153895.533,
|
||||
"max": 221692.034,
|
||||
"ci95": 85382.134
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 18724.322,
|
||||
"stdev": 9639.048,
|
||||
"min": 13107.549,
|
||||
"max": 29854.376,
|
||||
"ci95": 23946.655
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2161.532,
|
||||
"stdev": 287.109,
|
||||
"min": 1830.069,
|
||||
"max": 2332.81,
|
||||
"ci95": 713.276
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 162.575,
|
||||
"stdev": 29.799,
|
||||
"min": 136.023,
|
||||
"max": 194.804,
|
||||
"ci95": 74.03
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 27.752,
|
||||
"stdev": 3.186,
|
||||
"min": 24.403,
|
||||
"max": 30.746,
|
||||
"ci95": 7.916
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 13.0,
|
||||
"stdev": 0.0,
|
||||
"min": 13.0,
|
||||
"max": 13.0,
|
||||
"ci95": 0.0
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2902.054,
|
||||
"stdev": 158.708,
|
||||
"min": 2747.244,
|
||||
"max": 3064.393,
|
||||
"ci95": 394.285
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.691,
|
||||
"stdev": 0.097,
|
||||
"min": 0.601,
|
||||
"max": 0.794,
|
||||
"ci95": 0.241
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8852.332,
|
||||
"stdev": 530.809,
|
||||
"min": 8350.811,
|
||||
"max": 9408.241,
|
||||
"ci95": 1318.709
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1841.581,
|
||||
"stdev": 1186.781,
|
||||
"min": 471.209,
|
||||
"max": 2529.847,
|
||||
"ci95": 2948.365
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 255.087,
|
||||
"stdev": 217.128,
|
||||
"min": 5.798,
|
||||
"max": 402.877,
|
||||
"ci95": 539.419
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 92.882,
|
||||
"stdev": 81.722,
|
||||
"min": 0.61,
|
||||
"max": 156.13,
|
||||
"ci95": 203.024
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 13.0,
|
||||
"stdev": 0.0,
|
||||
"min": 13.0,
|
||||
"max": 13.0,
|
||||
"ci95": 0.0
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3008.178,
|
||||
"stdev": 149.07,
|
||||
"min": 2875.082,
|
||||
"max": 3169.256,
|
||||
"ci95": 370.34
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.687,
|
||||
"stdev": 0.132,
|
||||
"min": 0.562,
|
||||
"max": 0.825,
|
||||
"ci95": 0.327
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 21215.745,
|
||||
"stdev": 22821.547,
|
||||
"min": 8034.077,
|
||||
"max": 47567.797,
|
||||
"ci95": 56696.441
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1525.483,
|
||||
"stdev": 1472.651,
|
||||
"min": 633.984,
|
||||
"max": 3225.275,
|
||||
"ci95": 3658.563
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 191.398,
|
||||
"stdev": 272.942,
|
||||
"min": 10.346,
|
||||
"max": 505.335,
|
||||
"ci95": 678.08
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 49.506,
|
||||
"stdev": 66.145,
|
||||
"min": 1.104,
|
||||
"max": 124.874,
|
||||
"ci95": 164.326
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 13.0,
|
||||
"stdev": 0.0,
|
||||
"min": 13.0,
|
||||
"max": 13.0,
|
||||
"ci95": 0.0
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3062.136,
|
||||
"stdev": 128.594,
|
||||
"min": 2962.541,
|
||||
"max": 3207.313,
|
||||
"ci95": 319.472
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.029,
|
||||
"stdev": 0.573,
|
||||
"min": 0.595,
|
||||
"max": 1.678,
|
||||
"ci95": 1.423
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 33255.15,
|
||||
"stdev": 20451.99,
|
||||
"min": 16655.144,
|
||||
"max": 56102.104,
|
||||
"ci95": 50809.661
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1769.12,
|
||||
"stdev": 996.863,
|
||||
"min": 818.512,
|
||||
"max": 2806.557,
|
||||
"ci95": 2476.544
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 195.916,
|
||||
"stdev": 195.285,
|
||||
"min": 11.586,
|
||||
"max": 400.567,
|
||||
"ci95": 485.154
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 52.202,
|
||||
"stdev": 51.208,
|
||||
"min": 1.461,
|
||||
"max": 103.864,
|
||||
"ci95": 127.217
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 13.0,
|
||||
"stdev": 0.0,
|
||||
"min": 13.0,
|
||||
"max": 13.0,
|
||||
"ci95": 0.0
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2957.948,
|
||||
"stdev": 340.935,
|
||||
"min": 2586.504,
|
||||
"max": 3256.625,
|
||||
"ci95": 846.998
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.436,
|
||||
"stdev": 1.406,
|
||||
"min": 0.462,
|
||||
"max": 3.048,
|
||||
"ci95": 3.494
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3107.953,
|
||||
"stdev": 141.888,
|
||||
"min": 3020.105,
|
||||
"max": 3271.645,
|
||||
"ci95": 352.498
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2985.317,
|
||||
"stdev": 210.327,
|
||||
"min": 2761.164,
|
||||
"max": 3178.35,
|
||||
"ci95": 522.523
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 21963,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1830.069,
|
||||
"low_1pct_fps": 136.023,
|
||||
"low_01pct_fps": 30.746,
|
||||
"p50_ms": 0.331,
|
||||
"p95_ms": 1.153,
|
||||
"p99_ms": 3.001,
|
||||
"p999_ms": 9.997,
|
||||
"max_ms": 326.36,
|
||||
"histogram": [
|
||||
20336,
|
||||
1238,
|
||||
167,
|
||||
108,
|
||||
40,
|
||||
23,
|
||||
12,
|
||||
10,
|
||||
8,
|
||||
7,
|
||||
5,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 27994,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2332.81,
|
||||
"low_1pct_fps": 194.804,
|
||||
"low_01pct_fps": 28.107,
|
||||
"p50_ms": 0.321,
|
||||
"p95_ms": 0.771,
|
||||
"p99_ms": 1.356,
|
||||
"p999_ms": 3.836,
|
||||
"max_ms": 331.931,
|
||||
"histogram": [
|
||||
27270,
|
||||
652,
|
||||
34,
|
||||
13,
|
||||
5,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 27861,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2321.717,
|
||||
"low_1pct_fps": 156.898,
|
||||
"low_01pct_fps": 24.403,
|
||||
"p50_ms": 0.281,
|
||||
"p95_ms": 0.852,
|
||||
"p99_ms": 1.73,
|
||||
"p999_ms": 6.331,
|
||||
"max_ms": 301.991,
|
||||
"histogram": [
|
||||
26932,
|
||||
726,
|
||||
124,
|
||||
42,
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
9,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 30359,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2529.847,
|
||||
"low_1pct_fps": 356.586,
|
||||
"low_01pct_fps": 121.906,
|
||||
"p50_ms": 0.353,
|
||||
"p95_ms": 0.563,
|
||||
"p99_ms": 1.405,
|
||||
"p999_ms": 4.444,
|
||||
"max_ms": 20.302,
|
||||
"histogram": [
|
||||
29756,
|
||||
460,
|
||||
57,
|
||||
52,
|
||||
11,
|
||||
5,
|
||||
3,
|
||||
5,
|
||||
2,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 5781,
|
||||
"seconds": 12.268,
|
||||
"avg_fps": 471.209,
|
||||
"low_1pct_fps": 5.798,
|
||||
"low_01pct_fps": 0.61,
|
||||
"p50_ms": 0.359,
|
||||
"p95_ms": 0.77,
|
||||
"p99_ms": 1.78,
|
||||
"p999_ms": 20.826,
|
||||
"max_ms": 5834.37,
|
||||
"histogram": [
|
||||
5586,
|
||||
158,
|
||||
12,
|
||||
11,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 30285,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2523.687,
|
||||
"low_1pct_fps": 402.877,
|
||||
"low_01pct_fps": 156.13,
|
||||
"p50_ms": 0.351,
|
||||
"p95_ms": 0.539,
|
||||
"p99_ms": 1.574,
|
||||
"p999_ms": 3.683,
|
||||
"max_ms": 16.022,
|
||||
"histogram": [
|
||||
29666,
|
||||
490,
|
||||
74,
|
||||
35,
|
||||
7,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 11685,
|
||||
"seconds": 16.293,
|
||||
"avg_fps": 717.19,
|
||||
"low_1pct_fps": 10.346,
|
||||
"low_01pct_fps": 1.104,
|
||||
"p50_ms": 0.299,
|
||||
"p95_ms": 1.119,
|
||||
"p99_ms": 2.568,
|
||||
"p999_ms": 12.054,
|
||||
"max_ms": 5250.537,
|
||||
"histogram": [
|
||||
10993,
|
||||
502,
|
||||
102,
|
||||
39,
|
||||
14,
|
||||
8,
|
||||
6,
|
||||
4,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
4
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 38704,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 3225.275,
|
||||
"low_1pct_fps": 505.335,
|
||||
"low_01pct_fps": 124.874,
|
||||
"p50_ms": 0.283,
|
||||
"p95_ms": 0.36,
|
||||
"p99_ms": 0.909,
|
||||
"p999_ms": 2.015,
|
||||
"max_ms": 132.801,
|
||||
"histogram": [
|
||||
38385,
|
||||
279,
|
||||
25,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 7609,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 633.984,
|
||||
"low_1pct_fps": 58.513,
|
||||
"low_01pct_fps": 22.539,
|
||||
"p50_ms": 1.141,
|
||||
"p95_ms": 4.438,
|
||||
"p99_ms": 9.113,
|
||||
"p999_ms": 27.496,
|
||||
"max_ms": 64.424,
|
||||
"histogram": [
|
||||
3452,
|
||||
2398,
|
||||
956,
|
||||
368,
|
||||
143,
|
||||
96,
|
||||
61,
|
||||
46,
|
||||
20,
|
||||
29,
|
||||
6,
|
||||
10,
|
||||
6,
|
||||
7,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 10168,
|
||||
"seconds": 12.423,
|
||||
"avg_fps": 818.512,
|
||||
"low_1pct_fps": 11.586,
|
||||
"low_01pct_fps": 1.461,
|
||||
"p50_ms": 0.267,
|
||||
"p95_ms": 0.892,
|
||||
"p99_ms": 3.176,
|
||||
"p999_ms": 198.757,
|
||||
"max_ms": 1882.64,
|
||||
"histogram": [
|
||||
9733,
|
||||
205,
|
||||
121,
|
||||
49,
|
||||
12,
|
||||
9,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 33679,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2806.557,
|
||||
"low_1pct_fps": 400.567,
|
||||
"low_01pct_fps": 103.864,
|
||||
"p50_ms": 0.324,
|
||||
"p95_ms": 0.411,
|
||||
"p99_ms": 1.167,
|
||||
"p999_ms": 3.508,
|
||||
"max_ms": 83.572,
|
||||
"histogram": [
|
||||
33272,
|
||||
315,
|
||||
46,
|
||||
22,
|
||||
2,
|
||||
1,
|
||||
4,
|
||||
2,
|
||||
9,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 20188,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1682.292,
|
||||
"low_1pct_fps": 175.594,
|
||||
"low_01pct_fps": 51.28,
|
||||
"p50_ms": 0.374,
|
||||
"p95_ms": 1.37,
|
||||
"p99_ms": 2.821,
|
||||
"p999_ms": 8.947,
|
||||
"max_ms": 53.494,
|
||||
"histogram": [
|
||||
18109,
|
||||
1592,
|
||||
314,
|
||||
83,
|
||||
36,
|
||||
19,
|
||||
7,
|
||||
6,
|
||||
6,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
4,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-desktop"
|
||||
}
|
||||
@@ -1,787 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T15:46:25Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "linux",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 24,
|
||||
"os_version": "NixOS 26.05 (Yarara) (kernel 6.18.57)",
|
||||
"cpu": "13th Gen Intel(R) Core(TM) i7-13700KF",
|
||||
"ram_mb": 31904,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 4080",
|
||||
"vendor": "NVIDIA",
|
||||
"driver": "1.4.329 NVIDIA 595.71.05",
|
||||
"backend": "vulkan",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 28.799,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 112742.179,
|
||||
"stdev": 27885.804,
|
||||
"min": 81110.692,
|
||||
"max": 133773.748,
|
||||
"ci95": 69277.769
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 235049.179,
|
||||
"stdev": 31461.958,
|
||||
"min": 203486.748,
|
||||
"max": 266409.692,
|
||||
"ci95": 78162.144
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 79828.05,
|
||||
"stdev": 109107.365,
|
||||
"min": 16685.972,
|
||||
"max": 205814.266,
|
||||
"ci95": 271059.597
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 525.667,
|
||||
"stdev": 390.505,
|
||||
"min": 101.073,
|
||||
"max": 869.433,
|
||||
"ci95": 970.146
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 44.209,
|
||||
"stdev": 39.491,
|
||||
"min": 1.644,
|
||||
"max": 79.658,
|
||||
"ci95": 98.109
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 10.635,
|
||||
"stdev": 9.759,
|
||||
"min": 0.686,
|
||||
"max": 20.192,
|
||||
"ci95": 24.244
|
||||
},
|
||||
"memory.village.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 34.333,
|
||||
"stdev": 36.95,
|
||||
"min": 13.0,
|
||||
"max": 77.0,
|
||||
"ci95": 91.797
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3296.229,
|
||||
"stdev": 296.464,
|
||||
"min": 2956.234,
|
||||
"max": 3500.773,
|
||||
"ci95": 736.517
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.23,
|
||||
"stdev": 0.449,
|
||||
"min": 0.897,
|
||||
"max": 1.74,
|
||||
"ci95": 1.114
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 61172.527,
|
||||
"stdev": 17434.762,
|
||||
"min": 46779.931,
|
||||
"max": 80559.429,
|
||||
"ci95": 43313.846
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 599.408,
|
||||
"stdev": 492.96,
|
||||
"min": 64.173,
|
||||
"max": 1034.813,
|
||||
"ci95": 1224.68
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 61.923,
|
||||
"stdev": 56.534,
|
||||
"min": 0.737,
|
||||
"max": 112.221,
|
||||
"ci95": 140.449
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 15.771,
|
||||
"stdev": 14.11,
|
||||
"min": 0.098,
|
||||
"max": 27.463,
|
||||
"ci95": 35.054
|
||||
},
|
||||
"memory.forest.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 34.333,
|
||||
"stdev": 36.95,
|
||||
"min": 13.0,
|
||||
"max": 77.0,
|
||||
"ci95": 91.797
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3278.964,
|
||||
"stdev": 301.465,
|
||||
"min": 2947.268,
|
||||
"max": 3536.27,
|
||||
"ci95": 748.941
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 5.908,
|
||||
"stdev": 8.813,
|
||||
"min": 0.693,
|
||||
"max": 16.084,
|
||||
"ci95": 21.895
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 61762.098,
|
||||
"stdev": 3569.17,
|
||||
"min": 57919.097,
|
||||
"max": 64972.973,
|
||||
"ci95": 8867.026
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1175.044,
|
||||
"stdev": 131.94,
|
||||
"min": 1093.801,
|
||||
"max": 1327.281,
|
||||
"ci95": 327.785
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 119.758,
|
||||
"stdev": 68.419,
|
||||
"min": 77.252,
|
||||
"max": 198.683,
|
||||
"ci95": 169.976
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 24.224,
|
||||
"stdev": 18.982,
|
||||
"min": 12.308,
|
||||
"max": 46.114,
|
||||
"ci95": 47.159
|
||||
},
|
||||
"memory.ocean.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 34.333,
|
||||
"stdev": 36.95,
|
||||
"min": 13.0,
|
||||
"max": 77.0,
|
||||
"ci95": 91.797
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3275.349,
|
||||
"stdev": 317.864,
|
||||
"min": 2924.113,
|
||||
"max": 3543.23,
|
||||
"ci95": 789.681
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.654,
|
||||
"stdev": 0.066,
|
||||
"min": 0.579,
|
||||
"max": 0.699,
|
||||
"ci95": 0.163
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 113439.529,
|
||||
"stdev": 64746.162,
|
||||
"min": 55046.887,
|
||||
"max": 183068.386,
|
||||
"ci95": 160851.363
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 485.832,
|
||||
"stdev": 317.254,
|
||||
"min": 121.312,
|
||||
"max": 699.617,
|
||||
"ci95": 788.165
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 28.612,
|
||||
"stdev": 23.334,
|
||||
"min": 2.229,
|
||||
"max": 46.542,
|
||||
"ci95": 57.97
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.56,
|
||||
"stdev": 3.408,
|
||||
"min": 0.75,
|
||||
"max": 7.318,
|
||||
"ci95": 8.467
|
||||
},
|
||||
"memory.mountain.gpu_mb": {
|
||||
"n": 3,
|
||||
"mean": 34.333,
|
||||
"stdev": 36.95,
|
||||
"min": 13.0,
|
||||
"max": 77.0,
|
||||
"ci95": 91.797
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 3248.708,
|
||||
"stdev": 480.962,
|
||||
"min": 2700.645,
|
||||
"max": 3600.484,
|
||||
"ci95": 1194.873
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.832,
|
||||
"stdev": 2.076,
|
||||
"min": 0.618,
|
||||
"max": 4.229,
|
||||
"ci95": 5.157
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3371.958,
|
||||
"stdev": 280.347,
|
||||
"min": 3059.926,
|
||||
"max": 3602.613,
|
||||
"ci95": 696.476
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 3291.249,
|
||||
"stdev": 316.441,
|
||||
"min": 2935.975,
|
||||
"max": 3542.848,
|
||||
"ci95": 786.147
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 1248,
|
||||
"seconds": 12.348,
|
||||
"avg_fps": 101.073,
|
||||
"low_1pct_fps": 1.644,
|
||||
"low_01pct_fps": 0.686,
|
||||
"p50_ms": 1.225,
|
||||
"p95_ms": 11.161,
|
||||
"p99_ms": 226.597,
|
||||
"p999_ms": 1457.605,
|
||||
"max_ms": 1457.874,
|
||||
"histogram": [
|
||||
548,
|
||||
232,
|
||||
97,
|
||||
118,
|
||||
51,
|
||||
49,
|
||||
24,
|
||||
39,
|
||||
16,
|
||||
17,
|
||||
13,
|
||||
6,
|
||||
3,
|
||||
2,
|
||||
5,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
4,
|
||||
2,
|
||||
3,
|
||||
8,
|
||||
1,
|
||||
3
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 10435,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 869.433,
|
||||
"low_1pct_fps": 79.658,
|
||||
"low_01pct_fps": 20.192,
|
||||
"p50_ms": 0.813,
|
||||
"p95_ms": 2.537,
|
||||
"p99_ms": 5.685,
|
||||
"p999_ms": 13.292,
|
||||
"max_ms": 351.251,
|
||||
"histogram": [
|
||||
7598,
|
||||
2071,
|
||||
393,
|
||||
171,
|
||||
55,
|
||||
53,
|
||||
22,
|
||||
24,
|
||||
20,
|
||||
10,
|
||||
9,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 7278,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 606.495,
|
||||
"low_1pct_fps": 51.326,
|
||||
"low_01pct_fps": 11.026,
|
||||
"p50_ms": 1.105,
|
||||
"p95_ms": 3.854,
|
||||
"p99_ms": 7.067,
|
||||
"p999_ms": 24.484,
|
||||
"max_ms": 443.95,
|
||||
"histogram": [
|
||||
3206,
|
||||
2621,
|
||||
800,
|
||||
360,
|
||||
112,
|
||||
71,
|
||||
34,
|
||||
26,
|
||||
12,
|
||||
13,
|
||||
3,
|
||||
5,
|
||||
2,
|
||||
7,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 975,
|
||||
"seconds": 15.193,
|
||||
"avg_fps": 64.173,
|
||||
"low_1pct_fps": 0.737,
|
||||
"low_01pct_fps": 0.098,
|
||||
"p50_ms": 0.864,
|
||||
"p95_ms": 5.083,
|
||||
"p99_ms": 77.689,
|
||||
"p999_ms": 10225.237,
|
||||
"max_ms": 10225.237,
|
||||
"histogram": [
|
||||
680,
|
||||
99,
|
||||
104,
|
||||
12,
|
||||
30,
|
||||
13,
|
||||
8,
|
||||
4,
|
||||
2,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
2
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 8391,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 699.237,
|
||||
"low_1pct_fps": 72.811,
|
||||
"low_01pct_fps": 19.752,
|
||||
"p50_ms": 1.087,
|
||||
"p95_ms": 2.927,
|
||||
"p99_ms": 5.909,
|
||||
"p999_ms": 15.268,
|
||||
"max_ms": 252.557,
|
||||
"histogram": [
|
||||
3342,
|
||||
3998,
|
||||
656,
|
||||
231,
|
||||
56,
|
||||
26,
|
||||
15,
|
||||
19,
|
||||
12,
|
||||
12,
|
||||
11,
|
||||
6,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 12418,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1034.813,
|
||||
"low_1pct_fps": 112.221,
|
||||
"low_01pct_fps": 27.463,
|
||||
"p50_ms": 0.837,
|
||||
"p95_ms": 1.394,
|
||||
"p99_ms": 3.491,
|
||||
"p999_ms": 13.217,
|
||||
"max_ms": 245.59,
|
||||
"histogram": [
|
||||
11155,
|
||||
1004,
|
||||
100,
|
||||
64,
|
||||
29,
|
||||
16,
|
||||
16,
|
||||
10,
|
||||
2,
|
||||
6,
|
||||
5,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 13126,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1093.801,
|
||||
"low_1pct_fps": 77.252,
|
||||
"low_01pct_fps": 12.308,
|
||||
"p50_ms": 0.714,
|
||||
"p95_ms": 1.402,
|
||||
"p99_ms": 2.875,
|
||||
"p999_ms": 12.067,
|
||||
"max_ms": 238.158,
|
||||
"histogram": [
|
||||
11605,
|
||||
1207,
|
||||
191,
|
||||
54,
|
||||
17,
|
||||
11,
|
||||
7,
|
||||
12,
|
||||
4,
|
||||
4,
|
||||
2,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 15928,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1327.281,
|
||||
"low_1pct_fps": 198.683,
|
||||
"low_01pct_fps": 46.114,
|
||||
"p50_ms": 0.67,
|
||||
"p95_ms": 1.172,
|
||||
"p99_ms": 2.111,
|
||||
"p999_ms": 7.067,
|
||||
"max_ms": 193.743,
|
||||
"histogram": [
|
||||
14891,
|
||||
856,
|
||||
102,
|
||||
42,
|
||||
7,
|
||||
6,
|
||||
8,
|
||||
6,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 13249,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1104.051,
|
||||
"low_1pct_fps": 83.338,
|
||||
"low_01pct_fps": 14.249,
|
||||
"p50_ms": 0.711,
|
||||
"p95_ms": 1.403,
|
||||
"p99_ms": 3.046,
|
||||
"p999_ms": 10.625,
|
||||
"max_ms": 451.869,
|
||||
"histogram": [
|
||||
11824,
|
||||
1165,
|
||||
124,
|
||||
58,
|
||||
13,
|
||||
16,
|
||||
11,
|
||||
14,
|
||||
7,
|
||||
7,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 1469,
|
||||
"seconds": 12.109,
|
||||
"avg_fps": 121.312,
|
||||
"low_1pct_fps": 2.229,
|
||||
"low_01pct_fps": 0.75,
|
||||
"p50_ms": 2.12,
|
||||
"p95_ms": 13.173,
|
||||
"p99_ms": 125.189,
|
||||
"p999_ms": 727.045,
|
||||
"max_ms": 1939.723,
|
||||
"histogram": [
|
||||
196,
|
||||
440,
|
||||
438,
|
||||
136,
|
||||
50,
|
||||
36,
|
||||
24,
|
||||
25,
|
||||
22,
|
||||
17,
|
||||
17,
|
||||
13,
|
||||
6,
|
||||
11,
|
||||
8,
|
||||
4,
|
||||
1,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
7,
|
||||
2,
|
||||
1
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 8396,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 699.617,
|
||||
"low_1pct_fps": 46.542,
|
||||
"low_01pct_fps": 7.318,
|
||||
"p50_ms": 1.022,
|
||||
"p95_ms": 2.433,
|
||||
"p99_ms": 5.528,
|
||||
"p999_ms": 13.993,
|
||||
"max_ms": 305.464,
|
||||
"histogram": [
|
||||
3248,
|
||||
4509,
|
||||
361,
|
||||
113,
|
||||
52,
|
||||
37,
|
||||
21,
|
||||
26,
|
||||
14,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 7639,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 636.566,
|
||||
"low_1pct_fps": 37.064,
|
||||
"low_01pct_fps": 5.612,
|
||||
"p50_ms": 1.023,
|
||||
"p95_ms": 3.0,
|
||||
"p99_ms": 7.11,
|
||||
"p999_ms": 17.521,
|
||||
"max_ms": 268.877,
|
||||
"histogram": [
|
||||
3051,
|
||||
3794,
|
||||
413,
|
||||
158,
|
||||
66,
|
||||
43,
|
||||
35,
|
||||
21,
|
||||
31,
|
||||
12,
|
||||
3,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-desktop"
|
||||
}
|
||||
@@ -1,707 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 75.854,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 19419.646,
|
||||
"stdev": 10653.755,
|
||||
"min": 8240.178,
|
||||
"max": 29455.403,
|
||||
"ci95": 26467.531
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 78944.646,
|
||||
"stdev": 36737.011,
|
||||
"min": 51495.357,
|
||||
"max": 120678.403,
|
||||
"ci95": 91267.16
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 21947.683,
|
||||
"stdev": 10432.774,
|
||||
"min": 10427.451,
|
||||
"max": 30758.368,
|
||||
"ci95": 25918.54
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 45.524,
|
||||
"stdev": 44.352,
|
||||
"min": 15.749,
|
||||
"max": 96.497,
|
||||
"ci95": 110.185
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 9.141,
|
||||
"stdev": 10.812,
|
||||
"min": 1.86,
|
||||
"max": 21.565,
|
||||
"ci95": 26.862
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.727,
|
||||
"stdev": 6.902,
|
||||
"min": 1.785,
|
||||
"max": 14.612,
|
||||
"ci95": 17.146
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 39062.839,
|
||||
"stdev": 21806.234,
|
||||
"min": 15037.908,
|
||||
"max": 57603.235,
|
||||
"ci95": 54174.061
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 23.347,
|
||||
"stdev": 3.693,
|
||||
"min": 20.154,
|
||||
"max": 27.392,
|
||||
"ci95": 9.175
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 2.419,
|
||||
"stdev": 0.269,
|
||||
"min": 2.196,
|
||||
"max": 2.718,
|
||||
"ci95": 0.669
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 1.972,
|
||||
"stdev": 0.438,
|
||||
"min": 1.551,
|
||||
"max": 2.425,
|
||||
"ci95": 1.088
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 22097.713,
|
||||
"stdev": 4463.742,
|
||||
"min": 18053.319,
|
||||
"max": 26887.066,
|
||||
"ci95": 11089.445
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 51.279,
|
||||
"stdev": 6.309,
|
||||
"min": 44.786,
|
||||
"max": 57.386,
|
||||
"ci95": 15.673
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.15,
|
||||
"stdev": 3.128,
|
||||
"min": 3.444,
|
||||
"max": 9.574,
|
||||
"ci95": 7.77
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.161,
|
||||
"stdev": 2.739,
|
||||
"min": 2.487,
|
||||
"max": 7.321,
|
||||
"ci95": 6.803
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 50257.39,
|
||||
"stdev": 34798.619,
|
||||
"min": 25919.598,
|
||||
"max": 90115.595,
|
||||
"ci95": 86451.54
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 44.346,
|
||||
"stdev": 4.882,
|
||||
"min": 39.246,
|
||||
"max": 48.975,
|
||||
"ci95": 12.128
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.637,
|
||||
"stdev": 0.69,
|
||||
"min": 5.888,
|
||||
"max": 7.246,
|
||||
"ci95": 1.714
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.444,
|
||||
"stdev": 0.6,
|
||||
"min": 3.937,
|
||||
"max": 5.107,
|
||||
"ci95": 1.491
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2554.552,
|
||||
"stdev": 218.163,
|
||||
"min": 2328.859,
|
||||
"max": 2764.313,
|
||||
"ci95": 541.991
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2430.854,
|
||||
"stdev": 230.654,
|
||||
"min": 2186.328,
|
||||
"max": 2644.531,
|
||||
"ci95": 573.023
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3713.311,
|
||||
"stdev": 191.61,
|
||||
"min": 3512.331,
|
||||
"max": 3893.925,
|
||||
"ci95": 476.025
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 3450.061,
|
||||
"stdev": 76.233,
|
||||
"min": 3370.253,
|
||||
"max": 3522.128,
|
||||
"ci95": 189.388
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 189,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 15.749,
|
||||
"low_1pct_fps": 1.86,
|
||||
"low_01pct_fps": 1.785,
|
||||
"p50_ms": 22.219,
|
||||
"p95_ms": 254.854,
|
||||
"p99_ms": 515.134,
|
||||
"p999_ms": 560.079,
|
||||
"max_ms": 560.079,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
7,
|
||||
9,
|
||||
10,
|
||||
16,
|
||||
12,
|
||||
11,
|
||||
14,
|
||||
16,
|
||||
22,
|
||||
9,
|
||||
6,
|
||||
5,
|
||||
11,
|
||||
10,
|
||||
15,
|
||||
9,
|
||||
2,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 292,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 24.325,
|
||||
"low_1pct_fps": 3.998,
|
||||
"low_01pct_fps": 3.783,
|
||||
"p50_ms": 15.477,
|
||||
"p95_ms": 165.164,
|
||||
"p99_ms": 242.898,
|
||||
"p999_ms": 264.363,
|
||||
"max_ms": 264.363,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
26,
|
||||
20,
|
||||
32,
|
||||
20,
|
||||
20,
|
||||
17,
|
||||
12,
|
||||
12,
|
||||
10,
|
||||
17,
|
||||
14,
|
||||
20,
|
||||
14,
|
||||
16,
|
||||
16,
|
||||
21,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 1158,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 96.497,
|
||||
"low_1pct_fps": 21.565,
|
||||
"low_01pct_fps": 14.612,
|
||||
"p50_ms": 7.567,
|
||||
"p95_ms": 22.849,
|
||||
"p99_ms": 34.806,
|
||||
"p999_ms": 62.86,
|
||||
"max_ms": 74.011,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
38,
|
||||
452,
|
||||
158,
|
||||
102,
|
||||
94,
|
||||
125,
|
||||
68,
|
||||
34,
|
||||
42,
|
||||
30,
|
||||
7,
|
||||
4,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 271,
|
||||
"seconds": 12.047,
|
||||
"avg_fps": 22.496,
|
||||
"low_1pct_fps": 2.196,
|
||||
"low_01pct_fps": 1.551,
|
||||
"p50_ms": 18.263,
|
||||
"p95_ms": 189.284,
|
||||
"p99_ms": 317.823,
|
||||
"p999_ms": 644.675,
|
||||
"max_ms": 644.675,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
22,
|
||||
23,
|
||||
13,
|
||||
22,
|
||||
22,
|
||||
19,
|
||||
24,
|
||||
22,
|
||||
14,
|
||||
17,
|
||||
12,
|
||||
13,
|
||||
9,
|
||||
16,
|
||||
15,
|
||||
4,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 242,
|
||||
"seconds": 12.007,
|
||||
"avg_fps": 20.154,
|
||||
"low_1pct_fps": 2.343,
|
||||
"low_01pct_fps": 1.939,
|
||||
"p50_ms": 19.762,
|
||||
"p95_ms": 157.949,
|
||||
"p99_ms": 376.292,
|
||||
"p999_ms": 515.678,
|
||||
"max_ms": 515.678,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
13,
|
||||
17,
|
||||
16,
|
||||
26,
|
||||
19,
|
||||
11,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
9,
|
||||
16,
|
||||
17,
|
||||
12,
|
||||
21,
|
||||
19,
|
||||
9,
|
||||
6,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 331,
|
||||
"seconds": 12.084,
|
||||
"avg_fps": 27.392,
|
||||
"low_1pct_fps": 2.718,
|
||||
"low_01pct_fps": 2.425,
|
||||
"p50_ms": 13.0,
|
||||
"p95_ms": 162.797,
|
||||
"p99_ms": 325.827,
|
||||
"p999_ms": 412.349,
|
||||
"max_ms": 412.349,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
5,
|
||||
26,
|
||||
34,
|
||||
42,
|
||||
41,
|
||||
24,
|
||||
27,
|
||||
15,
|
||||
21,
|
||||
22,
|
||||
8,
|
||||
10,
|
||||
11,
|
||||
10,
|
||||
14,
|
||||
10,
|
||||
8,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 620,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 51.664,
|
||||
"low_1pct_fps": 3.444,
|
||||
"low_01pct_fps": 2.487,
|
||||
"p50_ms": 10.358,
|
||||
"p95_ms": 54.808,
|
||||
"p99_ms": 181.112,
|
||||
"p999_ms": 402.152,
|
||||
"max_ms": 402.152,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
30,
|
||||
79,
|
||||
95,
|
||||
86,
|
||||
90,
|
||||
60,
|
||||
54,
|
||||
28,
|
||||
28,
|
||||
19,
|
||||
9,
|
||||
8,
|
||||
8,
|
||||
6,
|
||||
8,
|
||||
7,
|
||||
5,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 689,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 57.386,
|
||||
"low_1pct_fps": 9.574,
|
||||
"low_01pct_fps": 7.321,
|
||||
"p50_ms": 12.76,
|
||||
"p95_ms": 43.737,
|
||||
"p99_ms": 69.357,
|
||||
"p999_ms": 136.592,
|
||||
"max_ms": 136.592,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
23,
|
||||
46,
|
||||
80,
|
||||
80,
|
||||
92,
|
||||
68,
|
||||
74,
|
||||
54,
|
||||
49,
|
||||
51,
|
||||
24,
|
||||
22,
|
||||
16,
|
||||
6,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 538,
|
||||
"seconds": 12.013,
|
||||
"avg_fps": 44.786,
|
||||
"low_1pct_fps": 5.431,
|
||||
"low_01pct_fps": 2.674,
|
||||
"p50_ms": 14.011,
|
||||
"p95_ms": 71.23,
|
||||
"p99_ms": 141.423,
|
||||
"p999_ms": 373.913,
|
||||
"max_ms": 373.913,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
8,
|
||||
38,
|
||||
84,
|
||||
83,
|
||||
53,
|
||||
62,
|
||||
52,
|
||||
54,
|
||||
29,
|
||||
12,
|
||||
15,
|
||||
13,
|
||||
22,
|
||||
10,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 588,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 48.975,
|
||||
"low_1pct_fps": 6.777,
|
||||
"low_01pct_fps": 3.937,
|
||||
"p50_ms": 12.678,
|
||||
"p95_ms": 64.221,
|
||||
"p99_ms": 108.513,
|
||||
"p999_ms": 254.008,
|
||||
"max_ms": 254.008,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
34,
|
||||
21,
|
||||
41,
|
||||
108,
|
||||
62,
|
||||
55,
|
||||
55,
|
||||
40,
|
||||
45,
|
||||
41,
|
||||
21,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
9,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 471,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 39.246,
|
||||
"low_1pct_fps": 5.888,
|
||||
"low_01pct_fps": 4.289,
|
||||
"p50_ms": 17.65,
|
||||
"p95_ms": 73.314,
|
||||
"p99_ms": 135.3,
|
||||
"p999_ms": 233.136,
|
||||
"max_ms": 233.136,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
12,
|
||||
22,
|
||||
29,
|
||||
36,
|
||||
40,
|
||||
43,
|
||||
38,
|
||||
41,
|
||||
46,
|
||||
62,
|
||||
29,
|
||||
20,
|
||||
19,
|
||||
22,
|
||||
5,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 538,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 44.818,
|
||||
"low_1pct_fps": 7.246,
|
||||
"low_01pct_fps": 5.107,
|
||||
"p50_ms": 15.959,
|
||||
"p95_ms": 63.485,
|
||||
"p99_ms": 109.639,
|
||||
"p999_ms": 195.815,
|
||||
"max_ms": 195.815,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
6,
|
||||
21,
|
||||
75,
|
||||
56,
|
||||
54,
|
||||
78,
|
||||
54,
|
||||
69,
|
||||
36,
|
||||
23,
|
||||
22,
|
||||
18,
|
||||
14,
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-m4pro-1080p"
|
||||
}
|
||||
@@ -1,707 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T23:17:23Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 58.672,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 20579.57,
|
||||
"stdev": 13060.035,
|
||||
"min": 10660.541,
|
||||
"max": 35376.471,
|
||||
"ci95": 32445.545
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 124180.237,
|
||||
"stdev": 102723.197,
|
||||
"min": 51510.541,
|
||||
"max": 241702.471,
|
||||
"ci95": 255199.163
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 23389.087,
|
||||
"stdev": 5416.249,
|
||||
"min": 18538.934,
|
||||
"max": 29233.632,
|
||||
"ci95": 13455.795
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 81.421,
|
||||
"stdev": 39.944,
|
||||
"min": 35.32,
|
||||
"max": 105.706,
|
||||
"ci95": 99.234
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 15.288,
|
||||
"stdev": 8.185,
|
||||
"min": 5.907,
|
||||
"max": 20.97,
|
||||
"ci95": 20.334
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 10.544,
|
||||
"stdev": 4.403,
|
||||
"min": 5.804,
|
||||
"max": 14.505,
|
||||
"ci95": 10.938
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 48382.741,
|
||||
"stdev": 32005.955,
|
||||
"min": 26161.003,
|
||||
"max": 85067.56,
|
||||
"ci95": 79513.616
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 67.82,
|
||||
"stdev": 49.16,
|
||||
"min": 12.722,
|
||||
"max": 107.193,
|
||||
"ci95": 122.129
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 17.769,
|
||||
"stdev": 19.765,
|
||||
"min": 2.609,
|
||||
"max": 40.124,
|
||||
"ci95": 49.103
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 13.876,
|
||||
"stdev": 16.851,
|
||||
"min": 2.308,
|
||||
"max": 33.21,
|
||||
"ci95": 41.864
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 37630.797,
|
||||
"stdev": 33094.177,
|
||||
"min": 14901.304,
|
||||
"max": 75599.155,
|
||||
"ci95": 82217.128
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 44.125,
|
||||
"stdev": 32.286,
|
||||
"min": 13.532,
|
||||
"max": 77.872,
|
||||
"ci95": 80.209
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.619,
|
||||
"stdev": 1.694,
|
||||
"min": 3.247,
|
||||
"max": 6.512,
|
||||
"ci95": 4.208
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 2.354,
|
||||
"stdev": 0.44,
|
||||
"min": 1.967,
|
||||
"max": 2.833,
|
||||
"ci95": 1.094
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 67242.203,
|
||||
"stdev": 17886.115,
|
||||
"min": 56354.348,
|
||||
"max": 87884.948,
|
||||
"ci95": 44435.159
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 28.745,
|
||||
"stdev": 7.77,
|
||||
"min": 20.237,
|
||||
"max": 35.466,
|
||||
"ci95": 19.304
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.013,
|
||||
"stdev": 0.849,
|
||||
"min": 2.273,
|
||||
"max": 3.94,
|
||||
"ci95": 2.109
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 2.377,
|
||||
"stdev": 1.031,
|
||||
"min": 1.246,
|
||||
"max": 3.263,
|
||||
"ci95": 2.561
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2958.083,
|
||||
"stdev": 22.425,
|
||||
"min": 2937.734,
|
||||
"max": 2982.125,
|
||||
"ci95": 55.71
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2837.568,
|
||||
"stdev": 165.159,
|
||||
"min": 2648.188,
|
||||
"max": 2951.719,
|
||||
"ci95": 410.31
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 4618.337,
|
||||
"stdev": 95.349,
|
||||
"min": 4543.347,
|
||||
"max": 4725.644,
|
||||
"ci95": 236.878
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 4264.652,
|
||||
"stdev": 87.422,
|
||||
"min": 4173.589,
|
||||
"max": 4347.91,
|
||||
"ci95": 217.185
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 424,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 35.32,
|
||||
"low_1pct_fps": 5.907,
|
||||
"low_01pct_fps": 5.804,
|
||||
"p50_ms": 17.195,
|
||||
"p95_ms": 95.694,
|
||||
"p99_ms": 164.6,
|
||||
"p999_ms": 172.292,
|
||||
"max_ms": 172.292,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
19,
|
||||
39,
|
||||
45,
|
||||
44,
|
||||
52,
|
||||
42,
|
||||
41,
|
||||
38,
|
||||
21,
|
||||
20,
|
||||
21,
|
||||
19,
|
||||
12,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 1239,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 103.238,
|
||||
"low_1pct_fps": 20.97,
|
||||
"low_01pct_fps": 14.505,
|
||||
"p50_ms": 8.073,
|
||||
"p95_ms": 18.618,
|
||||
"p99_ms": 34.704,
|
||||
"p999_ms": 53.789,
|
||||
"max_ms": 84.091,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
275,
|
||||
412,
|
||||
260,
|
||||
117,
|
||||
60,
|
||||
35,
|
||||
25,
|
||||
23,
|
||||
14,
|
||||
7,
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 1271,
|
||||
"seconds": 12.024,
|
||||
"avg_fps": 105.706,
|
||||
"low_1pct_fps": 18.988,
|
||||
"low_01pct_fps": 11.324,
|
||||
"p50_ms": 7.988,
|
||||
"p95_ms": 16.852,
|
||||
"p99_ms": 35.156,
|
||||
"p999_ms": 65.46,
|
||||
"max_ms": 111.155,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
220,
|
||||
500,
|
||||
318,
|
||||
101,
|
||||
43,
|
||||
21,
|
||||
15,
|
||||
19,
|
||||
17,
|
||||
4,
|
||||
4,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 154,
|
||||
"seconds": 12.105,
|
||||
"avg_fps": 12.722,
|
||||
"low_1pct_fps": 2.609,
|
||||
"low_01pct_fps": 2.308,
|
||||
"p50_ms": 54.156,
|
||||
"p95_ms": 216.738,
|
||||
"p99_ms": 333.238,
|
||||
"p999_ms": 433.205,
|
||||
"max_ms": 433.205,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
5,
|
||||
7,
|
||||
9,
|
||||
13,
|
||||
25,
|
||||
5,
|
||||
7,
|
||||
12,
|
||||
17,
|
||||
26,
|
||||
18,
|
||||
5,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 1287,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 107.193,
|
||||
"low_1pct_fps": 40.124,
|
||||
"low_01pct_fps": 33.21,
|
||||
"p50_ms": 8.355,
|
||||
"p95_ms": 14.243,
|
||||
"p99_ms": 22.791,
|
||||
"p999_ms": 29.023,
|
||||
"max_ms": 31.2,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
627,
|
||||
416,
|
||||
130,
|
||||
43,
|
||||
33,
|
||||
16,
|
||||
18,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 1003,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 83.546,
|
||||
"low_1pct_fps": 10.575,
|
||||
"low_01pct_fps": 6.111,
|
||||
"p50_ms": 9.556,
|
||||
"p95_ms": 22.218,
|
||||
"p99_ms": 53.64,
|
||||
"p999_ms": 143.879,
|
||||
"max_ms": 183.38,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
57,
|
||||
515,
|
||||
239,
|
||||
64,
|
||||
45,
|
||||
21,
|
||||
30,
|
||||
12,
|
||||
4,
|
||||
4,
|
||||
5,
|
||||
3,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 163,
|
||||
"seconds": 12.045,
|
||||
"avg_fps": 13.532,
|
||||
"low_1pct_fps": 3.247,
|
||||
"low_01pct_fps": 2.833,
|
||||
"p50_ms": 52.758,
|
||||
"p95_ms": 208.496,
|
||||
"p99_ms": 263.074,
|
||||
"p999_ms": 352.963,
|
||||
"max_ms": 352.963,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
5,
|
||||
5,
|
||||
14,
|
||||
23,
|
||||
10,
|
||||
12,
|
||||
17,
|
||||
30,
|
||||
18,
|
||||
20,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 951,
|
||||
"seconds": 12.212,
|
||||
"avg_fps": 77.872,
|
||||
"low_1pct_fps": 6.512,
|
||||
"low_01pct_fps": 1.967,
|
||||
"p50_ms": 8.895,
|
||||
"p95_ms": 31.377,
|
||||
"p99_ms": 72.053,
|
||||
"p999_ms": 508.284,
|
||||
"max_ms": 508.284,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
359,
|
||||
306,
|
||||
104,
|
||||
47,
|
||||
29,
|
||||
31,
|
||||
16,
|
||||
18,
|
||||
10,
|
||||
9,
|
||||
10,
|
||||
6,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 495,
|
||||
"seconds": 12.082,
|
||||
"avg_fps": 40.97,
|
||||
"low_1pct_fps": 4.097,
|
||||
"low_01pct_fps": 2.261,
|
||||
"p50_ms": 11.995,
|
||||
"p95_ms": 80.625,
|
||||
"p99_ms": 146.758,
|
||||
"p999_ms": 442.316,
|
||||
"max_ms": 442.316,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
80,
|
||||
109,
|
||||
56,
|
||||
31,
|
||||
37,
|
||||
24,
|
||||
30,
|
||||
28,
|
||||
17,
|
||||
17,
|
||||
27,
|
||||
24,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 243,
|
||||
"seconds": 12.008,
|
||||
"avg_fps": 20.237,
|
||||
"low_1pct_fps": 2.827,
|
||||
"low_01pct_fps": 2.623,
|
||||
"p50_ms": 21.487,
|
||||
"p95_ms": 177.814,
|
||||
"p99_ms": 315.716,
|
||||
"p999_ms": 381.289,
|
||||
"max_ms": 381.289,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
20,
|
||||
26,
|
||||
24,
|
||||
32,
|
||||
25,
|
||||
21,
|
||||
8,
|
||||
19,
|
||||
13,
|
||||
18,
|
||||
15,
|
||||
10,
|
||||
7,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 431,
|
||||
"seconds": 12.153,
|
||||
"avg_fps": 35.466,
|
||||
"low_1pct_fps": 2.273,
|
||||
"low_01pct_fps": 1.246,
|
||||
"p50_ms": 12.232,
|
||||
"p95_ms": 106.955,
|
||||
"p99_ms": 249.209,
|
||||
"p999_ms": 802.438,
|
||||
"max_ms": 802.438,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
66,
|
||||
137,
|
||||
62,
|
||||
41,
|
||||
21,
|
||||
23,
|
||||
20,
|
||||
3,
|
||||
14,
|
||||
11,
|
||||
11,
|
||||
10,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 367,
|
||||
"seconds": 12.02,
|
||||
"avg_fps": 30.533,
|
||||
"low_1pct_fps": 3.94,
|
||||
"low_01pct_fps": 3.263,
|
||||
"p50_ms": 21.354,
|
||||
"p95_ms": 104.182,
|
||||
"p99_ms": 218.448,
|
||||
"p999_ms": 306.483,
|
||||
"max_ms": 306.483,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
52,
|
||||
38,
|
||||
32,
|
||||
44,
|
||||
53,
|
||||
47,
|
||||
20,
|
||||
21,
|
||||
19,
|
||||
16,
|
||||
15,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-m4pro-1080p"
|
||||
}
|
||||
@@ -1,707 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 66.477,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 49895.61,
|
||||
"stdev": 37830.08,
|
||||
"min": 27410.441,
|
||||
"max": 93571.631,
|
||||
"ci95": 93982.713
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 89080.61,
|
||||
"stdev": 49418.222,
|
||||
"min": 59243.441,
|
||||
"max": 146123.631,
|
||||
"ci95": 122771.577
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 29280.957,
|
||||
"stdev": 15620.91,
|
||||
"min": 18681.538,
|
||||
"max": 47219.974,
|
||||
"ci95": 38807.625
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 42.245,
|
||||
"stdev": 6.241,
|
||||
"min": 36.416,
|
||||
"max": 48.83,
|
||||
"ci95": 15.506
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.137,
|
||||
"stdev": 1.2,
|
||||
"min": 3.03,
|
||||
"max": 5.412,
|
||||
"ci95": 2.981
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 2.891,
|
||||
"stdev": 0.196,
|
||||
"min": 2.777,
|
||||
"max": 3.118,
|
||||
"ci95": 0.488
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 16212.425,
|
||||
"stdev": 1584.155,
|
||||
"min": 14800.702,
|
||||
"max": 17925.672,
|
||||
"ci95": 3935.576
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 66.392,
|
||||
"stdev": 8.735,
|
||||
"min": 57.65,
|
||||
"max": 75.119,
|
||||
"ci95": 21.699
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 8.327,
|
||||
"stdev": 3.862,
|
||||
"min": 6.012,
|
||||
"max": 12.786,
|
||||
"ci95": 9.595
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.154,
|
||||
"stdev": 3.399,
|
||||
"min": 3.873,
|
||||
"max": 10.06,
|
||||
"ci95": 8.444
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 9054.345,
|
||||
"stdev": 1795.805,
|
||||
"min": 7429.882,
|
||||
"max": 10982.71,
|
||||
"ci95": 4461.386
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 49.891,
|
||||
"stdev": 17.901,
|
||||
"min": 29.637,
|
||||
"max": 63.591,
|
||||
"ci95": 44.472
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.144,
|
||||
"stdev": 5.262,
|
||||
"min": 2.948,
|
||||
"max": 12.218,
|
||||
"ci95": 13.074
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 5.254,
|
||||
"stdev": 4.377,
|
||||
"min": 2.603,
|
||||
"max": 10.306,
|
||||
"ci95": 10.874
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 18171.415,
|
||||
"stdev": 5234.921,
|
||||
"min": 12170.39,
|
||||
"max": 21800.551,
|
||||
"ci95": 13005.314
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 45.9,
|
||||
"stdev": 14.757,
|
||||
"min": 29.055,
|
||||
"max": 56.549,
|
||||
"ci95": 36.661
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.83,
|
||||
"stdev": 2.815,
|
||||
"min": 2.104,
|
||||
"max": 7.727,
|
||||
"ci95": 6.994
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.986,
|
||||
"stdev": 2.385,
|
||||
"min": 1.597,
|
||||
"max": 6.366,
|
||||
"ci95": 5.924
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 1877.276,
|
||||
"stdev": 149.19,
|
||||
"min": 1724.094,
|
||||
"max": 2022.125,
|
||||
"ci95": 370.639
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1810.693,
|
||||
"stdev": 157.376,
|
||||
"min": 1671.984,
|
||||
"max": 1981.719,
|
||||
"ci95": 390.975
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2708.649,
|
||||
"stdev": 200.476,
|
||||
"min": 2538.472,
|
||||
"max": 2929.644,
|
||||
"ci95": 498.051
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2635.498,
|
||||
"stdev": 241.221,
|
||||
"min": 2402.909,
|
||||
"max": 2884.511,
|
||||
"ci95": 599.274
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 586,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 48.83,
|
||||
"low_1pct_fps": 3.03,
|
||||
"low_01pct_fps": 2.779,
|
||||
"p50_ms": 6.298,
|
||||
"p95_ms": 102.59,
|
||||
"p99_ms": 300.171,
|
||||
"p999_ms": 359.883,
|
||||
"max_ms": 359.883,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
30,
|
||||
105,
|
||||
67,
|
||||
75,
|
||||
58,
|
||||
68,
|
||||
43,
|
||||
24,
|
||||
14,
|
||||
15,
|
||||
8,
|
||||
4,
|
||||
8,
|
||||
4,
|
||||
7,
|
||||
8,
|
||||
18,
|
||||
11,
|
||||
11,
|
||||
8,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 498,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 41.489,
|
||||
"low_1pct_fps": 5.412,
|
||||
"low_01pct_fps": 3.118,
|
||||
"p50_ms": 14.331,
|
||||
"p95_ms": 81.666,
|
||||
"p99_ms": 133.706,
|
||||
"p999_ms": 320.73,
|
||||
"max_ms": 320.73,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
15,
|
||||
23,
|
||||
21,
|
||||
37,
|
||||
43,
|
||||
41,
|
||||
55,
|
||||
45,
|
||||
50,
|
||||
45,
|
||||
30,
|
||||
15,
|
||||
18,
|
||||
18,
|
||||
21,
|
||||
13,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 437,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 36.416,
|
||||
"low_1pct_fps": 3.97,
|
||||
"low_01pct_fps": 2.777,
|
||||
"p50_ms": 12.279,
|
||||
"p95_ms": 133.385,
|
||||
"p99_ms": 203.287,
|
||||
"p999_ms": 360.113,
|
||||
"max_ms": 360.113,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
9,
|
||||
28,
|
||||
21,
|
||||
19,
|
||||
41,
|
||||
52,
|
||||
41,
|
||||
31,
|
||||
33,
|
||||
27,
|
||||
25,
|
||||
27,
|
||||
13,
|
||||
13,
|
||||
17,
|
||||
12,
|
||||
14,
|
||||
12,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 797,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 66.407,
|
||||
"low_1pct_fps": 6.184,
|
||||
"low_01pct_fps": 4.528,
|
||||
"p50_ms": 7.208,
|
||||
"p95_ms": 64.408,
|
||||
"p99_ms": 126.005,
|
||||
"p999_ms": 220.846,
|
||||
"max_ms": 220.846,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
22,
|
||||
78,
|
||||
137,
|
||||
123,
|
||||
136,
|
||||
77,
|
||||
58,
|
||||
31,
|
||||
14,
|
||||
13,
|
||||
14,
|
||||
13,
|
||||
10,
|
||||
11,
|
||||
21,
|
||||
20,
|
||||
13,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 692,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 57.65,
|
||||
"low_1pct_fps": 6.012,
|
||||
"low_01pct_fps": 3.873,
|
||||
"p50_ms": 10.783,
|
||||
"p95_ms": 48.101,
|
||||
"p99_ms": 121.963,
|
||||
"p999_ms": 258.167,
|
||||
"max_ms": 258.167,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
13,
|
||||
52,
|
||||
52,
|
||||
41,
|
||||
62,
|
||||
83,
|
||||
88,
|
||||
50,
|
||||
46,
|
||||
40,
|
||||
50,
|
||||
43,
|
||||
20,
|
||||
23,
|
||||
9,
|
||||
11,
|
||||
6,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 902,
|
||||
"seconds": 12.008,
|
||||
"avg_fps": 75.119,
|
||||
"low_1pct_fps": 12.786,
|
||||
"low_01pct_fps": 10.06,
|
||||
"p50_ms": 9.096,
|
||||
"p95_ms": 38.051,
|
||||
"p99_ms": 67.18,
|
||||
"p999_ms": 99.405,
|
||||
"max_ms": 99.405,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
26,
|
||||
115,
|
||||
72,
|
||||
65,
|
||||
100,
|
||||
118,
|
||||
90,
|
||||
66,
|
||||
51,
|
||||
54,
|
||||
50,
|
||||
39,
|
||||
16,
|
||||
17,
|
||||
13,
|
||||
10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 687,
|
||||
"seconds": 12.171,
|
||||
"avg_fps": 56.446,
|
||||
"low_1pct_fps": 3.267,
|
||||
"low_01pct_fps": 2.853,
|
||||
"p50_ms": 4.938,
|
||||
"p95_ms": 103.639,
|
||||
"p99_ms": 257.27,
|
||||
"p999_ms": 350.504,
|
||||
"max_ms": 350.504,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
28,
|
||||
199,
|
||||
125,
|
||||
99,
|
||||
51,
|
||||
35,
|
||||
32,
|
||||
18,
|
||||
5,
|
||||
7,
|
||||
11,
|
||||
10,
|
||||
11,
|
||||
6,
|
||||
2,
|
||||
4,
|
||||
7,
|
||||
14,
|
||||
15,
|
||||
8,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 764,
|
||||
"seconds": 12.014,
|
||||
"avg_fps": 63.591,
|
||||
"low_1pct_fps": 12.218,
|
||||
"low_01pct_fps": 10.306,
|
||||
"p50_ms": 11.549,
|
||||
"p95_ms": 45.214,
|
||||
"p99_ms": 67.493,
|
||||
"p999_ms": 97.034,
|
||||
"max_ms": 97.034,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
9,
|
||||
45,
|
||||
41,
|
||||
59,
|
||||
58,
|
||||
87,
|
||||
101,
|
||||
71,
|
||||
85,
|
||||
42,
|
||||
56,
|
||||
49,
|
||||
15,
|
||||
16,
|
||||
22,
|
||||
8,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 357,
|
||||
"seconds": 12.046,
|
||||
"avg_fps": 29.637,
|
||||
"low_1pct_fps": 2.948,
|
||||
"low_01pct_fps": 2.603,
|
||||
"p50_ms": 10.947,
|
||||
"p95_ms": 173.526,
|
||||
"p99_ms": 311.134,
|
||||
"p999_ms": 384.135,
|
||||
"max_ms": 384.135,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
11,
|
||||
47,
|
||||
31,
|
||||
12,
|
||||
34,
|
||||
32,
|
||||
23,
|
||||
15,
|
||||
26,
|
||||
21,
|
||||
14,
|
||||
15,
|
||||
7,
|
||||
6,
|
||||
16,
|
||||
18,
|
||||
6,
|
||||
15,
|
||||
8,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 355,
|
||||
"seconds": 12.218,
|
||||
"avg_fps": 29.055,
|
||||
"low_1pct_fps": 2.104,
|
||||
"low_01pct_fps": 1.597,
|
||||
"p50_ms": 7.766,
|
||||
"p95_ms": 145.251,
|
||||
"p99_ms": 368.51,
|
||||
"p999_ms": 626.205,
|
||||
"max_ms": 626.205,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
41,
|
||||
53,
|
||||
25,
|
||||
28,
|
||||
15,
|
||||
22,
|
||||
7,
|
||||
16,
|
||||
10,
|
||||
15,
|
||||
17,
|
||||
12,
|
||||
15,
|
||||
11,
|
||||
11,
|
||||
8,
|
||||
14,
|
||||
19,
|
||||
7,
|
||||
7,
|
||||
2,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 680,
|
||||
"seconds": 12.025,
|
||||
"avg_fps": 56.549,
|
||||
"low_1pct_fps": 7.727,
|
||||
"low_01pct_fps": 6.366,
|
||||
"p50_ms": 11.633,
|
||||
"p95_ms": 52.508,
|
||||
"p99_ms": 111.848,
|
||||
"p999_ms": 157.09,
|
||||
"max_ms": 157.09,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
32,
|
||||
38,
|
||||
43,
|
||||
49,
|
||||
71,
|
||||
55,
|
||||
55,
|
||||
54,
|
||||
57,
|
||||
53,
|
||||
41,
|
||||
54,
|
||||
21,
|
||||
19,
|
||||
17,
|
||||
12,
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 632,
|
||||
"seconds": 12.132,
|
||||
"avg_fps": 52.095,
|
||||
"low_1pct_fps": 4.66,
|
||||
"low_01pct_fps": 3.995,
|
||||
"p50_ms": 8.601,
|
||||
"p95_ms": 78.611,
|
||||
"p99_ms": 172.405,
|
||||
"p999_ms": 250.342,
|
||||
"max_ms": 250.342,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
9,
|
||||
75,
|
||||
86,
|
||||
53,
|
||||
32,
|
||||
57,
|
||||
40,
|
||||
41,
|
||||
30,
|
||||
38,
|
||||
25,
|
||||
24,
|
||||
39,
|
||||
16,
|
||||
23,
|
||||
7,
|
||||
12,
|
||||
15,
|
||||
9,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-m4pro-1080p"
|
||||
}
|
||||
@@ -1,771 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T12:54:29Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 12,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 17.628,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 12652.182,
|
||||
"stdev": 3231.342,
|
||||
"min": 9526.004,
|
||||
"max": 15979.309,
|
||||
"ci95": 8027.746
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 31329.516,
|
||||
"stdev": 10016.129,
|
||||
"min": 20777.004,
|
||||
"max": 40705.309,
|
||||
"ci95": 24883.451
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 12623.084,
|
||||
"stdev": 4958.724,
|
||||
"min": 7251.986,
|
||||
"max": 17026.894,
|
||||
"ci95": 12319.147
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 92.729,
|
||||
"stdev": 58.527,
|
||||
"min": 28.713,
|
||||
"max": 143.496,
|
||||
"ci95": 145.402
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 16.52,
|
||||
"stdev": 10.949,
|
||||
"min": 4.001,
|
||||
"max": 24.308,
|
||||
"ci95": 27.2
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 11.515,
|
||||
"stdev": 7.155,
|
||||
"min": 3.549,
|
||||
"max": 17.394,
|
||||
"ci95": 17.774
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1834.469,
|
||||
"stdev": 329.198,
|
||||
"min": 1455.688,
|
||||
"max": 2051.516,
|
||||
"ci95": 817.839
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.903,
|
||||
"stdev": 1.114,
|
||||
"min": 1.131,
|
||||
"max": 3.18,
|
||||
"ci95": 2.767
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 14590.694,
|
||||
"stdev": 3260.615,
|
||||
"min": 10942.613,
|
||||
"max": 17221.108,
|
||||
"ci95": 8100.47
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 106.817,
|
||||
"stdev": 104.558,
|
||||
"min": 43.857,
|
||||
"max": 227.513,
|
||||
"ci95": 259.759
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 23.0,
|
||||
"stdev": 26.394,
|
||||
"min": 7.338,
|
||||
"max": 53.473,
|
||||
"ci95": 65.57
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 14.841,
|
||||
"stdev": 15.773,
|
||||
"min": 5.157,
|
||||
"max": 33.042,
|
||||
"ci95": 39.186
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1814.245,
|
||||
"stdev": 154.974,
|
||||
"min": 1635.453,
|
||||
"max": 1910.125,
|
||||
"ci95": 385.007
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.452,
|
||||
"stdev": 0.542,
|
||||
"min": 0.826,
|
||||
"max": 1.777,
|
||||
"ci95": 1.346
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 13309.049,
|
||||
"stdev": 8088.157,
|
||||
"min": 6394.403,
|
||||
"max": 22203.194,
|
||||
"ci95": 20093.716
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 164.405,
|
||||
"stdev": 141.4,
|
||||
"min": 62.162,
|
||||
"max": 325.77,
|
||||
"ci95": 351.285
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 36.242,
|
||||
"stdev": 37.051,
|
||||
"min": 14.736,
|
||||
"max": 79.024,
|
||||
"ci95": 92.047
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 20.898,
|
||||
"stdev": 17.899,
|
||||
"min": 8.855,
|
||||
"max": 41.466,
|
||||
"ci95": 44.468
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1724.453,
|
||||
"stdev": 347.692,
|
||||
"min": 1323.5,
|
||||
"max": 1942.734,
|
||||
"ci95": 863.784
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.866,
|
||||
"stdev": 0.248,
|
||||
"min": 0.58,
|
||||
"max": 1.03,
|
||||
"ci95": 0.617
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 17989.43,
|
||||
"stdev": 3969.295,
|
||||
"min": 13444.423,
|
||||
"max": 20774.261,
|
||||
"ci95": 9861.07
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 162.084,
|
||||
"stdev": 160.057,
|
||||
"min": 68.44,
|
||||
"max": 346.896,
|
||||
"ci95": 397.635
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 33.74,
|
||||
"stdev": 36.146,
|
||||
"min": 11.158,
|
||||
"max": 75.429,
|
||||
"ci95": 89.798
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 17.194,
|
||||
"stdev": 14.232,
|
||||
"min": 7.903,
|
||||
"max": 33.579,
|
||||
"ci95": 35.357
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 1977.602,
|
||||
"stdev": 108.627,
|
||||
"min": 1872.516,
|
||||
"max": 2089.453,
|
||||
"ci95": 269.866
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.772,
|
||||
"stdev": 0.332,
|
||||
"min": 0.463,
|
||||
"max": 1.123,
|
||||
"ci95": 0.825
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2135.313,
|
||||
"stdev": 54.617,
|
||||
"min": 2072.344,
|
||||
"max": 2169.828,
|
||||
"ci95": 135.686
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1836.44,
|
||||
"stdev": 223.694,
|
||||
"min": 1578.141,
|
||||
"max": 1965.781,
|
||||
"ci95": 555.732
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3253.456,
|
||||
"stdev": 68.323,
|
||||
"min": 3178.409,
|
||||
"max": 3312.05,
|
||||
"ci95": 169.737
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 3144.363,
|
||||
"stdev": 69.868,
|
||||
"min": 3069.394,
|
||||
"max": 3207.66,
|
||||
"ci95": 173.576
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 1272,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 105.979,
|
||||
"low_1pct_fps": 21.25,
|
||||
"low_01pct_fps": 17.394,
|
||||
"p50_ms": 7.527,
|
||||
"p95_ms": 22.34,
|
||||
"p99_ms": 40.461,
|
||||
"p999_ms": 54.28,
|
||||
"max_ms": 60.7,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
56,
|
||||
161,
|
||||
170,
|
||||
180,
|
||||
167,
|
||||
184,
|
||||
118,
|
||||
71,
|
||||
61,
|
||||
26,
|
||||
25,
|
||||
28,
|
||||
12,
|
||||
10,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 1723,
|
||||
"seconds": 12.007,
|
||||
"avg_fps": 143.496,
|
||||
"low_1pct_fps": 24.308,
|
||||
"low_01pct_fps": 13.602,
|
||||
"p50_ms": 5.317,
|
||||
"p95_ms": 16.181,
|
||||
"p99_ms": 29.771,
|
||||
"p999_ms": 56.832,
|
||||
"max_ms": 90.209,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
63,
|
||||
413,
|
||||
271,
|
||||
273,
|
||||
185,
|
||||
148,
|
||||
112,
|
||||
89,
|
||||
47,
|
||||
43,
|
||||
28,
|
||||
22,
|
||||
18,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 346,
|
||||
"seconds": 12.05,
|
||||
"avg_fps": 28.713,
|
||||
"low_1pct_fps": 4.001,
|
||||
"low_01pct_fps": 3.549,
|
||||
"p50_ms": 23.684,
|
||||
"p95_ms": 110.057,
|
||||
"p99_ms": 225.236,
|
||||
"p999_ms": 281.776,
|
||||
"max_ms": 281.776,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
8,
|
||||
6,
|
||||
6,
|
||||
12,
|
||||
21,
|
||||
20,
|
||||
23,
|
||||
25,
|
||||
24,
|
||||
32,
|
||||
50,
|
||||
28,
|
||||
24,
|
||||
27,
|
||||
17,
|
||||
11,
|
||||
6,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 589,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 49.081,
|
||||
"low_1pct_fps": 8.19,
|
||||
"low_01pct_fps": 6.325,
|
||||
"p50_ms": 15.443,
|
||||
"p95_ms": 53.004,
|
||||
"p99_ms": 94.69,
|
||||
"p999_ms": 158.114,
|
||||
"max_ms": 158.114,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
7,
|
||||
20,
|
||||
30,
|
||||
46,
|
||||
53,
|
||||
48,
|
||||
56,
|
||||
62,
|
||||
61,
|
||||
66,
|
||||
63,
|
||||
18,
|
||||
22,
|
||||
20,
|
||||
10,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 2731,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 227.513,
|
||||
"low_1pct_fps": 53.473,
|
||||
"low_01pct_fps": 33.042,
|
||||
"p50_ms": 3.801,
|
||||
"p95_ms": 7.955,
|
||||
"p99_ms": 14.177,
|
||||
"p999_ms": 24.479,
|
||||
"max_ms": 38.218,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
526,
|
||||
1157,
|
||||
432,
|
||||
257,
|
||||
151,
|
||||
88,
|
||||
46,
|
||||
32,
|
||||
13,
|
||||
15,
|
||||
6,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 527,
|
||||
"seconds": 12.016,
|
||||
"avg_fps": 43.857,
|
||||
"low_1pct_fps": 7.338,
|
||||
"low_01pct_fps": 5.157,
|
||||
"p50_ms": 16.784,
|
||||
"p95_ms": 57.353,
|
||||
"p99_ms": 111.984,
|
||||
"p999_ms": 193.905,
|
||||
"max_ms": 193.905,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
9,
|
||||
16,
|
||||
29,
|
||||
40,
|
||||
61,
|
||||
50,
|
||||
54,
|
||||
52,
|
||||
62,
|
||||
57,
|
||||
35,
|
||||
28,
|
||||
11,
|
||||
13,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 746,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 62.162,
|
||||
"low_1pct_fps": 14.965,
|
||||
"low_01pct_fps": 12.372,
|
||||
"p50_ms": 13.76,
|
||||
"p95_ms": 35.144,
|
||||
"p99_ms": 57.63,
|
||||
"p999_ms": 80.827,
|
||||
"max_ms": 80.827,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
13,
|
||||
12,
|
||||
41,
|
||||
37,
|
||||
53,
|
||||
67,
|
||||
82,
|
||||
80,
|
||||
99,
|
||||
82,
|
||||
76,
|
||||
58,
|
||||
17,
|
||||
11,
|
||||
12,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 3910,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 325.77,
|
||||
"low_1pct_fps": 79.024,
|
||||
"low_01pct_fps": 41.466,
|
||||
"p50_ms": 2.685,
|
||||
"p95_ms": 5.125,
|
||||
"p99_ms": 8.342,
|
||||
"p999_ms": 20.782,
|
||||
"max_ms": 30.571,
|
||||
"histogram": [
|
||||
0,
|
||||
78,
|
||||
2526,
|
||||
892,
|
||||
203,
|
||||
95,
|
||||
49,
|
||||
27,
|
||||
13,
|
||||
11,
|
||||
7,
|
||||
3,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 1268,
|
||||
"seconds": 12.044,
|
||||
"avg_fps": 105.282,
|
||||
"low_1pct_fps": 14.736,
|
||||
"low_01pct_fps": 8.855,
|
||||
"p50_ms": 6.542,
|
||||
"p95_ms": 25.245,
|
||||
"p99_ms": 50.465,
|
||||
"p999_ms": 79.065,
|
||||
"max_ms": 146.809,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
171,
|
||||
190,
|
||||
169,
|
||||
167,
|
||||
133,
|
||||
105,
|
||||
93,
|
||||
53,
|
||||
43,
|
||||
35,
|
||||
41,
|
||||
26,
|
||||
13,
|
||||
11,
|
||||
10,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 822,
|
||||
"seconds": 12.011,
|
||||
"avg_fps": 68.44,
|
||||
"low_1pct_fps": 14.632,
|
||||
"low_01pct_fps": 10.101,
|
||||
"p50_ms": 11.396,
|
||||
"p95_ms": 35.387,
|
||||
"p99_ms": 55.24,
|
||||
"p999_ms": 99.005,
|
||||
"max_ms": 99.005,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
10,
|
||||
42,
|
||||
62,
|
||||
55,
|
||||
86,
|
||||
89,
|
||||
97,
|
||||
64,
|
||||
73,
|
||||
74,
|
||||
72,
|
||||
48,
|
||||
21,
|
||||
17,
|
||||
8,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 4165,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 346.896,
|
||||
"low_1pct_fps": 75.429,
|
||||
"low_01pct_fps": 33.579,
|
||||
"p50_ms": 2.541,
|
||||
"p95_ms": 4.838,
|
||||
"p99_ms": 7.998,
|
||||
"p999_ms": 20.209,
|
||||
"max_ms": 53.577,
|
||||
"histogram": [
|
||||
0,
|
||||
640,
|
||||
2307,
|
||||
855,
|
||||
178,
|
||||
93,
|
||||
34,
|
||||
22,
|
||||
15,
|
||||
3,
|
||||
3,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 851,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 70.916,
|
||||
"low_1pct_fps": 11.158,
|
||||
"low_01pct_fps": 7.903,
|
||||
"p50_ms": 10.128,
|
||||
"p95_ms": 36.498,
|
||||
"p99_ms": 68.434,
|
||||
"p999_ms": 126.541,
|
||||
"max_ms": 126.541,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
38,
|
||||
61,
|
||||
87,
|
||||
76,
|
||||
69,
|
||||
84,
|
||||
100,
|
||||
63,
|
||||
53,
|
||||
68,
|
||||
53,
|
||||
48,
|
||||
15,
|
||||
9,
|
||||
16,
|
||||
9,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-macmini"
|
||||
}
|
||||
@@ -1,771 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-04T13:08:37Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 18.159,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 8607.88,
|
||||
"stdev": 949.596,
|
||||
"min": 8010.323,
|
||||
"max": 9702.854,
|
||||
"ci95": 2359.119
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 44182.88,
|
||||
"stdev": 4031.933,
|
||||
"min": 40172.323,
|
||||
"max": 48235.854,
|
||||
"ci95": 10016.685
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 17227.171,
|
||||
"stdev": 5351.234,
|
||||
"min": 13892.279,
|
||||
"max": 23399.566,
|
||||
"ci95": 13294.274
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 76.237,
|
||||
"stdev": 45.661,
|
||||
"min": 28.922,
|
||||
"max": 120.041,
|
||||
"ci95": 113.437
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 17.319,
|
||||
"stdev": 12.99,
|
||||
"min": 5.593,
|
||||
"max": 31.283,
|
||||
"ci95": 32.272
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 12.642,
|
||||
"stdev": 9.463,
|
||||
"min": 4.308,
|
||||
"max": 22.93,
|
||||
"ci95": 23.51
|
||||
},
|
||||
"memory.village.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2674.987,
|
||||
"stdev": 30.71,
|
||||
"min": 2641.352,
|
||||
"max": 2701.531,
|
||||
"ci95": 76.294
|
||||
},
|
||||
"tick.village.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.341,
|
||||
"stdev": 0.407,
|
||||
"min": 0.924,
|
||||
"max": 1.737,
|
||||
"ci95": 1.012
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 34112.389,
|
||||
"stdev": 19305.487,
|
||||
"min": 22633.094,
|
||||
"max": 56401.09,
|
||||
"ci95": 47961.36
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 72.848,
|
||||
"stdev": 51.859,
|
||||
"min": 18.307,
|
||||
"max": 121.528,
|
||||
"ci95": 128.837
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 22.096,
|
||||
"stdev": 20.299,
|
||||
"min": 3.973,
|
||||
"max": 44.03,
|
||||
"ci95": 50.429
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 16.093,
|
||||
"stdev": 14.608,
|
||||
"min": 3.688,
|
||||
"max": 32.194,
|
||||
"ci95": 36.291
|
||||
},
|
||||
"memory.forest.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2519.729,
|
||||
"stdev": 82.097,
|
||||
"min": 2426.297,
|
||||
"max": 2580.328,
|
||||
"ci95": 203.957
|
||||
},
|
||||
"tick.forest.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.115,
|
||||
"stdev": 0.411,
|
||||
"min": 0.726,
|
||||
"max": 1.545,
|
||||
"ci95": 1.02
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 19066.516,
|
||||
"stdev": 9372.33,
|
||||
"min": 13163.781,
|
||||
"max": 29873.383,
|
||||
"ci95": 23284.039
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 69.735,
|
||||
"stdev": 46.656,
|
||||
"min": 16.524,
|
||||
"max": 103.635,
|
||||
"ci95": 115.909
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 17.636,
|
||||
"stdev": 13.616,
|
||||
"min": 3.179,
|
||||
"max": 30.217,
|
||||
"ci95": 33.827
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 12.115,
|
||||
"stdev": 10.798,
|
||||
"min": 2.584,
|
||||
"max": 23.842,
|
||||
"ci95": 26.825
|
||||
},
|
||||
"memory.ocean.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2557.143,
|
||||
"stdev": 84.375,
|
||||
"min": 2463.781,
|
||||
"max": 2627.945,
|
||||
"ci95": 209.616
|
||||
},
|
||||
"tick.ocean.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 1.056,
|
||||
"stdev": 0.233,
|
||||
"min": 0.815,
|
||||
"max": 1.281,
|
||||
"ci95": 0.58
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 62214.712,
|
||||
"stdev": 4884.13,
|
||||
"min": 58937.045,
|
||||
"max": 67828.14,
|
||||
"ci95": 12133.83
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 51.809,
|
||||
"stdev": 7.118,
|
||||
"min": 45.235,
|
||||
"max": 59.369,
|
||||
"ci95": 17.685
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.336,
|
||||
"stdev": 1.097,
|
||||
"min": 5.545,
|
||||
"max": 7.588,
|
||||
"ci95": 2.725
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.458,
|
||||
"stdev": 0.756,
|
||||
"min": 2.827,
|
||||
"max": 4.296,
|
||||
"ci95": 1.878
|
||||
},
|
||||
"memory.mountain.rss_mb": {
|
||||
"n": 3,
|
||||
"mean": 2604.227,
|
||||
"stdev": 15.043,
|
||||
"min": 2588.234,
|
||||
"max": 2618.094,
|
||||
"ci95": 37.371
|
||||
},
|
||||
"tick.mountain.client_ms": {
|
||||
"n": 3,
|
||||
"mean": 0.957,
|
||||
"stdev": 0.03,
|
||||
"min": 0.926,
|
||||
"max": 0.985,
|
||||
"ci95": 0.074
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2731.016,
|
||||
"stdev": 56.767,
|
||||
"min": 2688.516,
|
||||
"max": 2795.484,
|
||||
"ci95": 141.03
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2577.339,
|
||||
"stdev": 77.295,
|
||||
"min": 2488.203,
|
||||
"max": 2625.875,
|
||||
"ci95": 192.028
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 4612.571,
|
||||
"stdev": 20.245,
|
||||
"min": 4595.363,
|
||||
"max": 4634.879,
|
||||
"ci95": 50.296
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 4271.925,
|
||||
"stdev": 26.308,
|
||||
"min": 4246.207,
|
||||
"max": 4298.785,
|
||||
"ci95": 65.357
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 349,
|
||||
"seconds": 12.067,
|
||||
"avg_fps": 28.922,
|
||||
"low_1pct_fps": 5.593,
|
||||
"low_01pct_fps": 4.308,
|
||||
"p50_ms": 24.684,
|
||||
"p95_ms": 92.764,
|
||||
"p99_ms": 150.338,
|
||||
"p999_ms": 232.136,
|
||||
"max_ms": 232.136,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
3,
|
||||
13,
|
||||
17,
|
||||
26,
|
||||
31,
|
||||
40,
|
||||
46,
|
||||
50,
|
||||
32,
|
||||
25,
|
||||
20,
|
||||
30,
|
||||
10,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 1441,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 120.041,
|
||||
"low_1pct_fps": 31.283,
|
||||
"low_01pct_fps": 22.93,
|
||||
"p50_ms": 7.267,
|
||||
"p95_ms": 13.622,
|
||||
"p99_ms": 23.449,
|
||||
"p999_ms": 42.564,
|
||||
"max_ms": 44.657,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
543,
|
||||
397,
|
||||
218,
|
||||
100,
|
||||
54,
|
||||
24,
|
||||
20,
|
||||
7,
|
||||
7,
|
||||
5,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 958,
|
||||
"seconds": 12.013,
|
||||
"avg_fps": 79.749,
|
||||
"low_1pct_fps": 15.082,
|
||||
"low_01pct_fps": 10.689,
|
||||
"p50_ms": 9.138,
|
||||
"p95_ms": 28.848,
|
||||
"p99_ms": 52.247,
|
||||
"p999_ms": 93.55,
|
||||
"max_ms": 93.55,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
19,
|
||||
144,
|
||||
232,
|
||||
148,
|
||||
111,
|
||||
64,
|
||||
56,
|
||||
59,
|
||||
57,
|
||||
32,
|
||||
17,
|
||||
9,
|
||||
6,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 220,
|
||||
"seconds": 12.017,
|
||||
"avg_fps": 18.307,
|
||||
"low_1pct_fps": 3.973,
|
||||
"low_01pct_fps": 3.688,
|
||||
"p50_ms": 40.635,
|
||||
"p95_ms": 157.363,
|
||||
"p99_ms": 235.253,
|
||||
"p999_ms": 271.153,
|
||||
"max_ms": 271.153,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
6,
|
||||
14,
|
||||
17,
|
||||
25,
|
||||
25,
|
||||
17,
|
||||
27,
|
||||
33,
|
||||
24,
|
||||
16,
|
||||
11,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 1459,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 121.528,
|
||||
"low_1pct_fps": 44.03,
|
||||
"low_01pct_fps": 32.194,
|
||||
"p50_ms": 7.381,
|
||||
"p95_ms": 12.386,
|
||||
"p99_ms": 18.354,
|
||||
"p999_ms": 29.428,
|
||||
"max_ms": 32.695,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
357,
|
||||
642,
|
||||
300,
|
||||
80,
|
||||
28,
|
||||
28,
|
||||
14,
|
||||
7,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 945,
|
||||
"seconds": 12.006,
|
||||
"avg_fps": 78.709,
|
||||
"low_1pct_fps": 18.284,
|
||||
"low_01pct_fps": 12.397,
|
||||
"p50_ms": 9.554,
|
||||
"p95_ms": 27.657,
|
||||
"p99_ms": 43.253,
|
||||
"p999_ms": 80.663,
|
||||
"max_ms": 80.663,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
18,
|
||||
304,
|
||||
191,
|
||||
119,
|
||||
67,
|
||||
59,
|
||||
53,
|
||||
70,
|
||||
34,
|
||||
15,
|
||||
10,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 201,
|
||||
"seconds": 12.164,
|
||||
"avg_fps": 16.524,
|
||||
"low_1pct_fps": 3.179,
|
||||
"low_01pct_fps": 2.584,
|
||||
"p50_ms": 44.933,
|
||||
"p95_ms": 155.019,
|
||||
"p99_ms": 263.919,
|
||||
"p999_ms": 387.044,
|
||||
"max_ms": 387.044,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
4,
|
||||
7,
|
||||
20,
|
||||
8,
|
||||
29,
|
||||
18,
|
||||
25,
|
||||
29,
|
||||
29,
|
||||
17,
|
||||
8,
|
||||
4,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 1244,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 103.635,
|
||||
"low_1pct_fps": 30.217,
|
||||
"low_01pct_fps": 23.842,
|
||||
"p50_ms": 8.349,
|
||||
"p95_ms": 17.445,
|
||||
"p99_ms": 28.276,
|
||||
"p999_ms": 38.037,
|
||||
"max_ms": 45.85,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
162,
|
||||
453,
|
||||
312,
|
||||
129,
|
||||
71,
|
||||
47,
|
||||
32,
|
||||
18,
|
||||
16,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 1069,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 89.047,
|
||||
"low_1pct_fps": 19.512,
|
||||
"low_01pct_fps": 9.92,
|
||||
"p50_ms": 9.541,
|
||||
"p95_ms": 20.819,
|
||||
"p99_ms": 31.409,
|
||||
"p999_ms": 99.668,
|
||||
"max_ms": 101.942,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
64,
|
||||
266,
|
||||
283,
|
||||
160,
|
||||
112,
|
||||
74,
|
||||
51,
|
||||
33,
|
||||
17,
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 551,
|
||||
"seconds": 12.181,
|
||||
"avg_fps": 45.235,
|
||||
"low_1pct_fps": 5.545,
|
||||
"low_01pct_fps": 3.252,
|
||||
"p50_ms": 14.921,
|
||||
"p95_ms": 50.78,
|
||||
"p99_ms": 105.154,
|
||||
"p999_ms": 307.476,
|
||||
"max_ms": 307.476,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
42,
|
||||
137,
|
||||
72,
|
||||
58,
|
||||
50,
|
||||
47,
|
||||
57,
|
||||
39,
|
||||
20,
|
||||
15,
|
||||
8,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 718,
|
||||
"seconds": 12.094,
|
||||
"avg_fps": 59.369,
|
||||
"low_1pct_fps": 7.588,
|
||||
"low_01pct_fps": 4.296,
|
||||
"p50_ms": 12.178,
|
||||
"p95_ms": 38.273,
|
||||
"p99_ms": 65.694,
|
||||
"p999_ms": 232.789,
|
||||
"max_ms": 232.789,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
140,
|
||||
202,
|
||||
115,
|
||||
72,
|
||||
48,
|
||||
47,
|
||||
43,
|
||||
19,
|
||||
19,
|
||||
6,
|
||||
4,
|
||||
0,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 610,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 50.822,
|
||||
"low_1pct_fps": 5.875,
|
||||
"low_01pct_fps": 2.827,
|
||||
"p50_ms": 13.894,
|
||||
"p95_ms": 44.208,
|
||||
"p99_ms": 75.023,
|
||||
"p999_ms": 353.686,
|
||||
"max_ms": 353.686,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
67,
|
||||
115,
|
||||
125,
|
||||
88,
|
||||
55,
|
||||
54,
|
||||
43,
|
||||
25,
|
||||
13,
|
||||
15,
|
||||
7,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-macmini"
|
||||
}
|
||||
@@ -1,723 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 69.878,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 23843.039,
|
||||
"stdev": 7524.513,
|
||||
"min": 16643.766,
|
||||
"max": 31655.294,
|
||||
"ci95": 18693.436
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 76908.706,
|
||||
"stdev": 36719.804,
|
||||
"min": 45051.766,
|
||||
"max": 117069.294,
|
||||
"ci95": 91224.412
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 19608.485,
|
||||
"stdev": 9449.035,
|
||||
"min": 13510.149,
|
||||
"max": 30492.958,
|
||||
"ci95": 23474.6
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 46.159,
|
||||
"stdev": 17.954,
|
||||
"min": 31.413,
|
||||
"max": 66.152,
|
||||
"ci95": 44.604
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.544,
|
||||
"stdev": 3.452,
|
||||
"min": 3.225,
|
||||
"max": 10.116,
|
||||
"ci95": 8.577
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.689,
|
||||
"stdev": 1.808,
|
||||
"min": 2.647,
|
||||
"max": 6.085,
|
||||
"ci95": 4.491
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 23344.685,
|
||||
"stdev": 5493.145,
|
||||
"min": 17038.709,
|
||||
"max": 27089.821,
|
||||
"ci95": 13646.83
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 61.892,
|
||||
"stdev": 37.939,
|
||||
"min": 22.354,
|
||||
"max": 98.0,
|
||||
"ci95": 94.254
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 9.736,
|
||||
"stdev": 8.597,
|
||||
"min": 2.296,
|
||||
"max": 19.148,
|
||||
"ci95": 21.359
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 6.651,
|
||||
"stdev": 5.574,
|
||||
"min": 2.202,
|
||||
"max": 12.903,
|
||||
"ci95": 13.847
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 27267.052,
|
||||
"stdev": 21587.34,
|
||||
"min": 10640.097,
|
||||
"max": 51663.797,
|
||||
"ci95": 53630.253
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 75.493,
|
||||
"stdev": 63.885,
|
||||
"min": 25.975,
|
||||
"max": 147.604,
|
||||
"ci95": 158.711
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 13.396,
|
||||
"stdev": 13.366,
|
||||
"min": 4.634,
|
||||
"max": 28.78,
|
||||
"ci95": 33.205
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 7.356,
|
||||
"stdev": 6.609,
|
||||
"min": 3.26,
|
||||
"max": 14.98,
|
||||
"ci95": 16.418
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 38284.867,
|
||||
"stdev": 4237.4,
|
||||
"min": 33922.931,
|
||||
"max": 42385.65,
|
||||
"ci95": 10527.134
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 35.918,
|
||||
"stdev": 17.742,
|
||||
"min": 18.135,
|
||||
"max": 53.619,
|
||||
"ci95": 44.077
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.999,
|
||||
"stdev": 2.132,
|
||||
"min": 2.453,
|
||||
"max": 6.431,
|
||||
"ci95": 5.297
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.017,
|
||||
"stdev": 1.831,
|
||||
"min": 1.775,
|
||||
"max": 5.12,
|
||||
"ci95": 4.549
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2566.339,
|
||||
"stdev": 218.228,
|
||||
"min": 2339.094,
|
||||
"max": 2774.266,
|
||||
"ci95": 542.153
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2354.852,
|
||||
"stdev": 240.105,
|
||||
"min": 2082.984,
|
||||
"max": 2537.867,
|
||||
"ci95": 596.503
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 3430.598,
|
||||
"stdev": 77.063,
|
||||
"min": 3345.395,
|
||||
"max": 3495.426,
|
||||
"ci95": 191.451
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 3211.931,
|
||||
"stdev": 99.984,
|
||||
"min": 3124.098,
|
||||
"max": 3320.738,
|
||||
"ci95": 248.394
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 377,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 31.413,
|
||||
"low_1pct_fps": 3.225,
|
||||
"low_01pct_fps": 2.647,
|
||||
"p50_ms": 15.145,
|
||||
"p95_ms": 128.716,
|
||||
"p99_ms": 276.685,
|
||||
"p999_ms": 377.749,
|
||||
"max_ms": 377.749,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
17,
|
||||
26,
|
||||
21,
|
||||
30,
|
||||
23,
|
||||
43,
|
||||
16,
|
||||
25,
|
||||
28,
|
||||
28,
|
||||
35,
|
||||
16,
|
||||
14,
|
||||
12,
|
||||
15,
|
||||
13,
|
||||
11,
|
||||
4,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 794,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 66.152,
|
||||
"low_1pct_fps": 10.116,
|
||||
"low_01pct_fps": 6.085,
|
||||
"p50_ms": 11.137,
|
||||
"p95_ms": 41.078,
|
||||
"p99_ms": 73.531,
|
||||
"p999_ms": 164.347,
|
||||
"max_ms": 164.347,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
20,
|
||||
57,
|
||||
65,
|
||||
52,
|
||||
70,
|
||||
82,
|
||||
88,
|
||||
80,
|
||||
67,
|
||||
53,
|
||||
48,
|
||||
52,
|
||||
18,
|
||||
20,
|
||||
10,
|
||||
10,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 491,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 40.912,
|
||||
"low_1pct_fps": 6.291,
|
||||
"low_01pct_fps": 5.336,
|
||||
"p50_ms": 15.962,
|
||||
"p95_ms": 71.604,
|
||||
"p99_ms": 137.056,
|
||||
"p999_ms": 187.401,
|
||||
"max_ms": 187.401,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
10,
|
||||
32,
|
||||
54,
|
||||
60,
|
||||
45,
|
||||
49,
|
||||
44,
|
||||
49,
|
||||
50,
|
||||
22,
|
||||
21,
|
||||
20,
|
||||
18,
|
||||
8,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 784,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 65.322,
|
||||
"low_1pct_fps": 7.763,
|
||||
"low_01pct_fps": 4.848,
|
||||
"p50_ms": 10.024,
|
||||
"p95_ms": 43.46,
|
||||
"p99_ms": 94.19,
|
||||
"p999_ms": 206.286,
|
||||
"max_ms": 206.286,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
17,
|
||||
40,
|
||||
69,
|
||||
80,
|
||||
95,
|
||||
88,
|
||||
82,
|
||||
53,
|
||||
58,
|
||||
39,
|
||||
49,
|
||||
52,
|
||||
21,
|
||||
15,
|
||||
14,
|
||||
7,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 1176,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 98.0,
|
||||
"low_1pct_fps": 19.148,
|
||||
"low_01pct_fps": 12.903,
|
||||
"p50_ms": 6.214,
|
||||
"p95_ms": 30.125,
|
||||
"p99_ms": 41.199,
|
||||
"p999_ms": 73.675,
|
||||
"max_ms": 81.328,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
179,
|
||||
205,
|
||||
175,
|
||||
115,
|
||||
111,
|
||||
79,
|
||||
39,
|
||||
21,
|
||||
25,
|
||||
34,
|
||||
79,
|
||||
77,
|
||||
20,
|
||||
10,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 271,
|
||||
"seconds": 12.123,
|
||||
"avg_fps": 22.354,
|
||||
"low_1pct_fps": 2.296,
|
||||
"low_01pct_fps": 2.202,
|
||||
"p50_ms": 14.989,
|
||||
"p95_ms": 214.282,
|
||||
"p99_ms": 404.5,
|
||||
"p999_ms": 454.134,
|
||||
"max_ms": 454.134,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
18,
|
||||
19,
|
||||
19,
|
||||
28,
|
||||
28,
|
||||
13,
|
||||
19,
|
||||
20,
|
||||
12,
|
||||
21,
|
||||
14,
|
||||
5,
|
||||
8,
|
||||
4,
|
||||
9,
|
||||
18,
|
||||
10,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 1772,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 147.604,
|
||||
"low_1pct_fps": 28.78,
|
||||
"low_01pct_fps": 14.98,
|
||||
"p50_ms": 5.328,
|
||||
"p95_ms": 15.261,
|
||||
"p99_ms": 25.961,
|
||||
"p999_ms": 58.586,
|
||||
"max_ms": 74.925,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
34,
|
||||
421,
|
||||
331,
|
||||
290,
|
||||
175,
|
||||
163,
|
||||
122,
|
||||
83,
|
||||
44,
|
||||
33,
|
||||
26,
|
||||
28,
|
||||
16,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 635,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 52.9,
|
||||
"low_1pct_fps": 6.774,
|
||||
"low_01pct_fps": 3.828,
|
||||
"p50_ms": 9.578,
|
||||
"p95_ms": 61.195,
|
||||
"p99_ms": 112.118,
|
||||
"p999_ms": 261.228,
|
||||
"max_ms": 261.228,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
38,
|
||||
49,
|
||||
64,
|
||||
63,
|
||||
63,
|
||||
51,
|
||||
60,
|
||||
27,
|
||||
29,
|
||||
27,
|
||||
17,
|
||||
37,
|
||||
28,
|
||||
30,
|
||||
27,
|
||||
15,
|
||||
8,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 312,
|
||||
"seconds": 12.011,
|
||||
"avg_fps": 25.975,
|
||||
"low_1pct_fps": 4.634,
|
||||
"low_01pct_fps": 3.26,
|
||||
"p50_ms": 24.629,
|
||||
"p95_ms": 115.493,
|
||||
"p99_ms": 169.827,
|
||||
"p999_ms": 306.737,
|
||||
"max_ms": 306.737,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
5,
|
||||
10,
|
||||
10,
|
||||
24,
|
||||
39,
|
||||
33,
|
||||
38,
|
||||
47,
|
||||
16,
|
||||
16,
|
||||
21,
|
||||
23,
|
||||
22,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 218,
|
||||
"seconds": 12.021,
|
||||
"avg_fps": 18.135,
|
||||
"low_1pct_fps": 2.453,
|
||||
"low_01pct_fps": 2.156,
|
||||
"p50_ms": 17.447,
|
||||
"p95_ms": 257.129,
|
||||
"p99_ms": 377.63,
|
||||
"p999_ms": 463.802,
|
||||
"max_ms": 463.802,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
7,
|
||||
13,
|
||||
15,
|
||||
18,
|
||||
11,
|
||||
9,
|
||||
7,
|
||||
16,
|
||||
8,
|
||||
3,
|
||||
11,
|
||||
10,
|
||||
14,
|
||||
7,
|
||||
5,
|
||||
16,
|
||||
8,
|
||||
15,
|
||||
12,
|
||||
13,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 653,
|
||||
"seconds": 12.179,
|
||||
"avg_fps": 53.619,
|
||||
"low_1pct_fps": 6.431,
|
||||
"low_01pct_fps": 5.12,
|
||||
"p50_ms": 8.427,
|
||||
"p95_ms": 58.968,
|
||||
"p99_ms": 141.423,
|
||||
"p999_ms": 195.302,
|
||||
"max_ms": 195.302,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
38,
|
||||
66,
|
||||
76,
|
||||
79,
|
||||
64,
|
||||
45,
|
||||
38,
|
||||
20,
|
||||
29,
|
||||
22,
|
||||
24,
|
||||
46,
|
||||
25,
|
||||
36,
|
||||
17,
|
||||
14,
|
||||
10,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 432,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 35.999,
|
||||
"low_1pct_fps": 3.112,
|
||||
"low_01pct_fps": 1.775,
|
||||
"p50_ms": 16.724,
|
||||
"p95_ms": 83.13,
|
||||
"p99_ms": 220.496,
|
||||
"p999_ms": 563.493,
|
||||
"max_ms": 563.493,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
7,
|
||||
14,
|
||||
17,
|
||||
23,
|
||||
35,
|
||||
35,
|
||||
26,
|
||||
24,
|
||||
33,
|
||||
34,
|
||||
43,
|
||||
43,
|
||||
23,
|
||||
27,
|
||||
20,
|
||||
15,
|
||||
5,
|
||||
4,
|
||||
3,
|
||||
1,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-m4pro-1080p"
|
||||
}
|
||||
@@ -1,723 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T23:17:23Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 37.185,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 13521.661,
|
||||
"stdev": 573.908,
|
||||
"min": 13085.942,
|
||||
"max": 14171.935,
|
||||
"ci95": 1425.783
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 63229.994,
|
||||
"stdev": 6185.388,
|
||||
"min": 56237.942,
|
||||
"max": 67987.935,
|
||||
"ci95": 15366.595
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 14807.746,
|
||||
"stdev": 2020.358,
|
||||
"min": 13414.414,
|
||||
"max": 17124.849,
|
||||
"ci95": 5019.253
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 91.753,
|
||||
"stdev": 11.452,
|
||||
"min": 78.555,
|
||||
"max": 99.067,
|
||||
"ci95": 28.451
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 13.105,
|
||||
"stdev": 2.514,
|
||||
"min": 10.354,
|
||||
"max": 15.282,
|
||||
"ci95": 6.244
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 9.203,
|
||||
"stdev": 1.382,
|
||||
"min": 7.689,
|
||||
"max": 10.396,
|
||||
"ci95": 3.432
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 24180.167,
|
||||
"stdev": 777.711,
|
||||
"min": 23290.973,
|
||||
"max": 24733.555,
|
||||
"ci95": 1932.098
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 113.871,
|
||||
"stdev": 53.305,
|
||||
"min": 56.542,
|
||||
"max": 161.938,
|
||||
"ci95": 132.428
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 28.748,
|
||||
"stdev": 17.633,
|
||||
"min": 12.823,
|
||||
"max": 47.698,
|
||||
"ci95": 43.807
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 20.551,
|
||||
"stdev": 13.547,
|
||||
"min": 8.937,
|
||||
"max": 35.433,
|
||||
"ci95": 33.655
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 19314.547,
|
||||
"stdev": 5853.258,
|
||||
"min": 15068.272,
|
||||
"max": 25991.528,
|
||||
"ci95": 14541.473
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 119.116,
|
||||
"stdev": 71.027,
|
||||
"min": 45.498,
|
||||
"max": 187.231,
|
||||
"ci95": 176.454
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 31.721,
|
||||
"stdev": 26.624,
|
||||
"min": 8.585,
|
||||
"max": 60.822,
|
||||
"ci95": 66.144
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 16.8,
|
||||
"stdev": 14.937,
|
||||
"min": 5.876,
|
||||
"max": 33.821,
|
||||
"ci95": 37.109
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 61290.415,
|
||||
"stdev": 15063.343,
|
||||
"min": 49453.256,
|
||||
"max": 78246.003,
|
||||
"ci95": 37422.439
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 56.905,
|
||||
"stdev": 19.674,
|
||||
"min": 37.807,
|
||||
"max": 77.109,
|
||||
"ci95": 48.878
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 7.384,
|
||||
"stdev": 0.62,
|
||||
"min": 6.67,
|
||||
"max": 7.784,
|
||||
"ci95": 1.539
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.48,
|
||||
"stdev": 1.306,
|
||||
"min": 2.526,
|
||||
"max": 4.968,
|
||||
"ci95": 3.244
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 4078.01,
|
||||
"stdev": 79.593,
|
||||
"min": 4020.391,
|
||||
"max": 4168.828,
|
||||
"ci95": 197.735
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 3705.104,
|
||||
"stdev": 149.415,
|
||||
"min": 3541.375,
|
||||
"max": 3834.078,
|
||||
"ci95": 371.196
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 5250.386,
|
||||
"stdev": 54.229,
|
||||
"min": 5200.662,
|
||||
"max": 5308.208,
|
||||
"ci95": 134.723
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 4647.172,
|
||||
"stdev": 29.179,
|
||||
"min": 4613.552,
|
||||
"max": 4665.911,
|
||||
"ci95": 72.492
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 1172,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 97.637,
|
||||
"low_1pct_fps": 15.282,
|
||||
"low_01pct_fps": 10.396,
|
||||
"p50_ms": 7.394,
|
||||
"p95_ms": 26.126,
|
||||
"p99_ms": 50.505,
|
||||
"p999_ms": 79.614,
|
||||
"max_ms": 112.764,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
24,
|
||||
111,
|
||||
198,
|
||||
193,
|
||||
170,
|
||||
129,
|
||||
109,
|
||||
59,
|
||||
42,
|
||||
43,
|
||||
23,
|
||||
38,
|
||||
10,
|
||||
10,
|
||||
7,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 1189,
|
||||
"seconds": 12.002,
|
||||
"avg_fps": 99.067,
|
||||
"low_1pct_fps": 13.678,
|
||||
"low_01pct_fps": 9.523,
|
||||
"p50_ms": 7.061,
|
||||
"p95_ms": 28.029,
|
||||
"p99_ms": 58.166,
|
||||
"p999_ms": 103.326,
|
||||
"max_ms": 106.682,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
59,
|
||||
132,
|
||||
223,
|
||||
172,
|
||||
171,
|
||||
107,
|
||||
90,
|
||||
59,
|
||||
39,
|
||||
36,
|
||||
28,
|
||||
35,
|
||||
14,
|
||||
9,
|
||||
9,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 943,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 78.555,
|
||||
"low_1pct_fps": 10.354,
|
||||
"low_01pct_fps": 7.689,
|
||||
"p50_ms": 8.817,
|
||||
"p95_ms": 31.62,
|
||||
"p99_ms": 70.58,
|
||||
"p999_ms": 130.049,
|
||||
"max_ms": 130.049,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
8,
|
||||
34,
|
||||
97,
|
||||
118,
|
||||
168,
|
||||
126,
|
||||
106,
|
||||
69,
|
||||
58,
|
||||
49,
|
||||
36,
|
||||
32,
|
||||
8,
|
||||
9,
|
||||
13,
|
||||
8,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 679,
|
||||
"seconds": 12.009,
|
||||
"avg_fps": 56.542,
|
||||
"low_1pct_fps": 12.823,
|
||||
"low_01pct_fps": 8.937,
|
||||
"p50_ms": 14.344,
|
||||
"p95_ms": 42.09,
|
||||
"p99_ms": 65.756,
|
||||
"p999_ms": 111.897,
|
||||
"max_ms": 111.897,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
33,
|
||||
50,
|
||||
62,
|
||||
68,
|
||||
60,
|
||||
48,
|
||||
67,
|
||||
84,
|
||||
76,
|
||||
64,
|
||||
27,
|
||||
18,
|
||||
14,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 1478,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 123.133,
|
||||
"low_1pct_fps": 25.723,
|
||||
"low_01pct_fps": 17.282,
|
||||
"p50_ms": 6.388,
|
||||
"p95_ms": 17.972,
|
||||
"p99_ms": 29.029,
|
||||
"p999_ms": 57.659,
|
||||
"max_ms": 58.069,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
336,
|
||||
298,
|
||||
222,
|
||||
186,
|
||||
144,
|
||||
77,
|
||||
70,
|
||||
57,
|
||||
39,
|
||||
23,
|
||||
13,
|
||||
5,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 1944,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 161.938,
|
||||
"low_1pct_fps": 47.698,
|
||||
"low_01pct_fps": 35.433,
|
||||
"p50_ms": 5.168,
|
||||
"p95_ms": 12.12,
|
||||
"p99_ms": 17.337,
|
||||
"p999_ms": 26.48,
|
||||
"max_ms": 29.965,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
18,
|
||||
793,
|
||||
527,
|
||||
243,
|
||||
125,
|
||||
91,
|
||||
47,
|
||||
41,
|
||||
34,
|
||||
15,
|
||||
7,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 548,
|
||||
"seconds": 12.044,
|
||||
"avg_fps": 45.498,
|
||||
"low_1pct_fps": 8.585,
|
||||
"low_01pct_fps": 5.876,
|
||||
"p50_ms": 15.416,
|
||||
"p95_ms": 62.523,
|
||||
"p99_ms": 98.757,
|
||||
"p999_ms": 170.17,
|
||||
"max_ms": 170.17,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2,
|
||||
15,
|
||||
26,
|
||||
52,
|
||||
53,
|
||||
58,
|
||||
37,
|
||||
56,
|
||||
39,
|
||||
58,
|
||||
60,
|
||||
27,
|
||||
24,
|
||||
18,
|
||||
21,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 1496,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 124.619,
|
||||
"low_1pct_fps": 25.756,
|
||||
"low_01pct_fps": 10.702,
|
||||
"p50_ms": 6.649,
|
||||
"p95_ms": 15.751,
|
||||
"p99_ms": 26.208,
|
||||
"p999_ms": 76.546,
|
||||
"max_ms": 110.33,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
15,
|
||||
250,
|
||||
299,
|
||||
266,
|
||||
216,
|
||||
163,
|
||||
115,
|
||||
68,
|
||||
40,
|
||||
32,
|
||||
13,
|
||||
14,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 2247,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 187.231,
|
||||
"low_1pct_fps": 60.822,
|
||||
"low_01pct_fps": 33.821,
|
||||
"p50_ms": 4.73,
|
||||
"p95_ms": 8.497,
|
||||
"p99_ms": 12.315,
|
||||
"p999_ms": 21.724,
|
||||
"max_ms": 42.26,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
347,
|
||||
987,
|
||||
453,
|
||||
211,
|
||||
122,
|
||||
67,
|
||||
32,
|
||||
15,
|
||||
6,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 670,
|
||||
"seconds": 12.007,
|
||||
"avg_fps": 55.799,
|
||||
"low_1pct_fps": 7.784,
|
||||
"low_01pct_fps": 2.526,
|
||||
"p50_ms": 12.887,
|
||||
"p95_ms": 45.129,
|
||||
"p99_ms": 76.315,
|
||||
"p999_ms": 395.821,
|
||||
"max_ms": 395.821,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
16,
|
||||
54,
|
||||
79,
|
||||
75,
|
||||
81,
|
||||
68,
|
||||
60,
|
||||
53,
|
||||
70,
|
||||
54,
|
||||
17,
|
||||
16,
|
||||
9,
|
||||
17,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 455,
|
||||
"seconds": 12.035,
|
||||
"avg_fps": 37.807,
|
||||
"low_1pct_fps": 6.67,
|
||||
"low_01pct_fps": 4.968,
|
||||
"p50_ms": 15.986,
|
||||
"p95_ms": 82.012,
|
||||
"p99_ms": 117.987,
|
||||
"p999_ms": 201.279,
|
||||
"max_ms": 201.279,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
3,
|
||||
27,
|
||||
37,
|
||||
47,
|
||||
49,
|
||||
37,
|
||||
39,
|
||||
31,
|
||||
39,
|
||||
34,
|
||||
20,
|
||||
24,
|
||||
30,
|
||||
26,
|
||||
10,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 933,
|
||||
"seconds": 12.1,
|
||||
"avg_fps": 77.109,
|
||||
"low_1pct_fps": 7.697,
|
||||
"low_01pct_fps": 2.946,
|
||||
"p50_ms": 8.593,
|
||||
"p95_ms": 34.696,
|
||||
"p99_ms": 79.266,
|
||||
"p999_ms": 339.486,
|
||||
"max_ms": 339.486,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
45,
|
||||
176,
|
||||
209,
|
||||
196,
|
||||
95,
|
||||
45,
|
||||
43,
|
||||
26,
|
||||
19,
|
||||
30,
|
||||
9,
|
||||
9,
|
||||
14,
|
||||
13,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-m4pro-1080p"
|
||||
}
|
||||
@@ -1,723 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-11-01T22:55:52Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "macos",
|
||||
"arch": "aarch64",
|
||||
"cpu_threads": 14,
|
||||
"os_version": "27.0.1",
|
||||
"cpu": "Apple M4 Pro",
|
||||
"ram_mb": 65536,
|
||||
"gpu": {
|
||||
"name": "Apple M4 Pro",
|
||||
"vendor": "Apple",
|
||||
"driver": "4.1 Metal - 91.7",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": true,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"load_avg_1m": 74.321,
|
||||
"window": [
|
||||
1920,
|
||||
930
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 56311.461,
|
||||
"stdev": 26982.658,
|
||||
"min": 36031.835,
|
||||
"max": 86935.815,
|
||||
"ci95": 67034.048
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 97731.794,
|
||||
"stdev": 21691.925,
|
||||
"min": 72951.835,
|
||||
"max": 113284.815,
|
||||
"ci95": 53890.078
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 13954.335,
|
||||
"stdev": 10146.301,
|
||||
"min": 7679.006,
|
||||
"max": 25660.115,
|
||||
"ci95": 25206.843
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 33.239,
|
||||
"stdev": 18.526,
|
||||
"min": 12.03,
|
||||
"max": 46.264,
|
||||
"ci95": 46.026
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.772,
|
||||
"stdev": 2.399,
|
||||
"min": 1.734,
|
||||
"max": 6.416,
|
||||
"ci95": 5.96
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 2.866,
|
||||
"stdev": 1.762,
|
||||
"min": 1.433,
|
||||
"max": 4.834,
|
||||
"ci95": 4.379
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 19803.961,
|
||||
"stdev": 14910.114,
|
||||
"min": 8220.752,
|
||||
"max": 36626.588,
|
||||
"ci95": 37041.766
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 47.303,
|
||||
"stdev": 17.044,
|
||||
"min": 32.698,
|
||||
"max": 66.03,
|
||||
"ci95": 42.343
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.365,
|
||||
"stdev": 0.709,
|
||||
"min": 3.658,
|
||||
"max": 5.076,
|
||||
"ci95": 1.761
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.128,
|
||||
"stdev": 0.564,
|
||||
"min": 2.651,
|
||||
"max": 3.751,
|
||||
"ci95": 1.402
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 18639.188,
|
||||
"stdev": 8912.103,
|
||||
"min": 11960.198,
|
||||
"max": 28758.72,
|
||||
"ci95": 22140.678
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 34.908,
|
||||
"stdev": 6.372,
|
||||
"min": 29.271,
|
||||
"max": 41.822,
|
||||
"ci95": 15.831
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.614,
|
||||
"stdev": 1.558,
|
||||
"min": 2.986,
|
||||
"max": 6.09,
|
||||
"ci95": 3.869
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 4.06,
|
||||
"stdev": 1.662,
|
||||
"min": 2.224,
|
||||
"max": 5.463,
|
||||
"ci95": 4.13
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 19191.558,
|
||||
"stdev": 2902.338,
|
||||
"min": 15845.729,
|
||||
"max": 21030.7,
|
||||
"ci95": 7210.388
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 67.004,
|
||||
"stdev": 13.923,
|
||||
"min": 51.98,
|
||||
"max": 79.471,
|
||||
"ci95": 34.589
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 7.862,
|
||||
"stdev": 1.987,
|
||||
"min": 6.339,
|
||||
"max": 10.109,
|
||||
"ci95": 4.936
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 3.993,
|
||||
"stdev": 1.679,
|
||||
"min": 2.06,
|
||||
"max": 5.088,
|
||||
"ci95": 4.172
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2019.089,
|
||||
"stdev": 53.398,
|
||||
"min": 1960.188,
|
||||
"max": 2064.328,
|
||||
"ci95": 132.657
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1927.195,
|
||||
"stdev": 108.077,
|
||||
"min": 1813.609,
|
||||
"max": 2028.758,
|
||||
"ci95": 268.5
|
||||
},
|
||||
"memory.footprint_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2440.727,
|
||||
"stdev": 72.508,
|
||||
"min": 2375.394,
|
||||
"max": 2518.738,
|
||||
"ci95": 180.134
|
||||
},
|
||||
"memory.footprint_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2395.53,
|
||||
"stdev": 71.597,
|
||||
"min": 2318.504,
|
||||
"max": 2460.05,
|
||||
"ci95": 177.872
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 146,
|
||||
"seconds": 12.136,
|
||||
"avg_fps": 12.03,
|
||||
"low_1pct_fps": 1.734,
|
||||
"low_01pct_fps": 1.433,
|
||||
"p50_ms": 28.465,
|
||||
"p95_ms": 339.625,
|
||||
"p99_ms": 455.663,
|
||||
"p999_ms": 697.859,
|
||||
"max_ms": 697.859,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
4,
|
||||
9,
|
||||
9,
|
||||
5,
|
||||
5,
|
||||
8,
|
||||
6,
|
||||
5,
|
||||
5,
|
||||
1,
|
||||
10,
|
||||
9,
|
||||
6,
|
||||
11,
|
||||
10,
|
||||
5,
|
||||
8,
|
||||
15,
|
||||
13,
|
||||
1,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 556,
|
||||
"seconds": 12.018,
|
||||
"avg_fps": 46.264,
|
||||
"low_1pct_fps": 6.416,
|
||||
"low_01pct_fps": 4.834,
|
||||
"p50_ms": 13.72,
|
||||
"p95_ms": 71.774,
|
||||
"p99_ms": 120.078,
|
||||
"p999_ms": 206.87,
|
||||
"max_ms": 206.87,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
6,
|
||||
5,
|
||||
16,
|
||||
22,
|
||||
57,
|
||||
55,
|
||||
64,
|
||||
62,
|
||||
62,
|
||||
50,
|
||||
38,
|
||||
29,
|
||||
19,
|
||||
23,
|
||||
16,
|
||||
21,
|
||||
9,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 498,
|
||||
"seconds": 12.022,
|
||||
"avg_fps": 41.423,
|
||||
"low_1pct_fps": 3.166,
|
||||
"low_01pct_fps": 2.331,
|
||||
"p50_ms": 7.7,
|
||||
"p95_ms": 114.025,
|
||||
"p99_ms": 246.232,
|
||||
"p999_ms": 428.98,
|
||||
"max_ms": 428.98,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
15,
|
||||
63,
|
||||
55,
|
||||
58,
|
||||
33,
|
||||
38,
|
||||
31,
|
||||
22,
|
||||
23,
|
||||
17,
|
||||
24,
|
||||
24,
|
||||
20,
|
||||
11,
|
||||
9,
|
||||
10,
|
||||
14,
|
||||
15,
|
||||
12,
|
||||
4,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 521,
|
||||
"seconds": 12.065,
|
||||
"avg_fps": 43.182,
|
||||
"low_1pct_fps": 4.362,
|
||||
"low_01pct_fps": 3.751,
|
||||
"p50_ms": 8.121,
|
||||
"p95_ms": 110.621,
|
||||
"p99_ms": 191.925,
|
||||
"p999_ms": 266.575,
|
||||
"max_ms": 266.575,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
63,
|
||||
27,
|
||||
49,
|
||||
61,
|
||||
67,
|
||||
39,
|
||||
45,
|
||||
27,
|
||||
17,
|
||||
13,
|
||||
17,
|
||||
7,
|
||||
11,
|
||||
13,
|
||||
11,
|
||||
18,
|
||||
22,
|
||||
11,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 793,
|
||||
"seconds": 12.01,
|
||||
"avg_fps": 66.03,
|
||||
"low_1pct_fps": 5.076,
|
||||
"low_01pct_fps": 2.651,
|
||||
"p50_ms": 8.218,
|
||||
"p95_ms": 44.767,
|
||||
"p99_ms": 143.139,
|
||||
"p999_ms": 377.207,
|
||||
"max_ms": 377.207,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
60,
|
||||
106,
|
||||
55,
|
||||
58,
|
||||
127,
|
||||
97,
|
||||
64,
|
||||
41,
|
||||
28,
|
||||
32,
|
||||
31,
|
||||
39,
|
||||
12,
|
||||
7,
|
||||
8,
|
||||
14,
|
||||
9,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 395,
|
||||
"seconds": 12.08,
|
||||
"avg_fps": 32.698,
|
||||
"low_1pct_fps": 3.658,
|
||||
"low_01pct_fps": 2.983,
|
||||
"p50_ms": 10.283,
|
||||
"p95_ms": 171.818,
|
||||
"p99_ms": 231.998,
|
||||
"p999_ms": 335.242,
|
||||
"max_ms": 335.242,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
6,
|
||||
19,
|
||||
13,
|
||||
27,
|
||||
42,
|
||||
31,
|
||||
53,
|
||||
36,
|
||||
22,
|
||||
25,
|
||||
20,
|
||||
19,
|
||||
10,
|
||||
8,
|
||||
7,
|
||||
6,
|
||||
11,
|
||||
15,
|
||||
23,
|
||||
2,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 405,
|
||||
"seconds": 12.043,
|
||||
"avg_fps": 33.63,
|
||||
"low_1pct_fps": 4.765,
|
||||
"low_01pct_fps": 4.492,
|
||||
"p50_ms": 14.686,
|
||||
"p95_ms": 115.893,
|
||||
"p99_ms": 196.822,
|
||||
"p999_ms": 222.615,
|
||||
"max_ms": 222.615,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
6,
|
||||
16,
|
||||
18,
|
||||
49,
|
||||
42,
|
||||
36,
|
||||
22,
|
||||
30,
|
||||
35,
|
||||
32,
|
||||
23,
|
||||
10,
|
||||
10,
|
||||
22,
|
||||
22,
|
||||
16,
|
||||
11,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 502,
|
||||
"seconds": 12.003,
|
||||
"avg_fps": 41.822,
|
||||
"low_1pct_fps": 6.09,
|
||||
"low_01pct_fps": 5.463,
|
||||
"p50_ms": 15.264,
|
||||
"p95_ms": 76.822,
|
||||
"p99_ms": 144.7,
|
||||
"p999_ms": 183.045,
|
||||
"max_ms": 183.045,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
9,
|
||||
14,
|
||||
12,
|
||||
13,
|
||||
47,
|
||||
43,
|
||||
52,
|
||||
41,
|
||||
40,
|
||||
52,
|
||||
40,
|
||||
50,
|
||||
15,
|
||||
26,
|
||||
17,
|
||||
17,
|
||||
9,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 353,
|
||||
"seconds": 12.06,
|
||||
"avg_fps": 29.271,
|
||||
"low_1pct_fps": 2.986,
|
||||
"low_01pct_fps": 2.224,
|
||||
"p50_ms": 10.806,
|
||||
"p95_ms": 150.281,
|
||||
"p99_ms": 268.607,
|
||||
"p999_ms": 449.56,
|
||||
"max_ms": 449.56,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
29,
|
||||
16,
|
||||
24,
|
||||
36,
|
||||
35,
|
||||
23,
|
||||
31,
|
||||
13,
|
||||
16,
|
||||
12,
|
||||
18,
|
||||
14,
|
||||
9,
|
||||
8,
|
||||
16,
|
||||
18,
|
||||
17,
|
||||
12,
|
||||
6,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 624,
|
||||
"seconds": 12.005,
|
||||
"avg_fps": 51.98,
|
||||
"low_1pct_fps": 7.137,
|
||||
"low_01pct_fps": 5.088,
|
||||
"p50_ms": 12.033,
|
||||
"p95_ms": 75.22,
|
||||
"p99_ms": 115.345,
|
||||
"p999_ms": 196.553,
|
||||
"max_ms": 196.553,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
29,
|
||||
48,
|
||||
34,
|
||||
38,
|
||||
40,
|
||||
61,
|
||||
56,
|
||||
50,
|
||||
57,
|
||||
54,
|
||||
41,
|
||||
33,
|
||||
13,
|
||||
15,
|
||||
15,
|
||||
28,
|
||||
6,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 835,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 69.562,
|
||||
"low_1pct_fps": 6.339,
|
||||
"low_01pct_fps": 2.06,
|
||||
"p50_ms": 9.818,
|
||||
"p95_ms": 37.917,
|
||||
"p99_ms": 81.491,
|
||||
"p999_ms": 485.481,
|
||||
"max_ms": 485.481,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
6,
|
||||
62,
|
||||
63,
|
||||
59,
|
||||
75,
|
||||
84,
|
||||
75,
|
||||
94,
|
||||
59,
|
||||
77,
|
||||
55,
|
||||
31,
|
||||
36,
|
||||
27,
|
||||
10,
|
||||
10,
|
||||
5,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 954,
|
||||
"seconds": 12.004,
|
||||
"avg_fps": 79.471,
|
||||
"low_1pct_fps": 10.109,
|
||||
"low_01pct_fps": 4.832,
|
||||
"p50_ms": 7.91,
|
||||
"p95_ms": 38.672,
|
||||
"p99_ms": 79.104,
|
||||
"p999_ms": 206.935,
|
||||
"max_ms": 206.935,
|
||||
"histogram": [
|
||||
0,
|
||||
0,
|
||||
13,
|
||||
55,
|
||||
70,
|
||||
136,
|
||||
119,
|
||||
109,
|
||||
93,
|
||||
98,
|
||||
52,
|
||||
49,
|
||||
48,
|
||||
21,
|
||||
30,
|
||||
17,
|
||||
14,
|
||||
11,
|
||||
17,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-m4pro-1080p"
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T01:25:53Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 10777.756,
|
||||
"stdev": 129.67,
|
||||
"min": 10636.92,
|
||||
"max": 10892.2,
|
||||
"ci95": 322.144
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 23477.423,
|
||||
"stdev": 346.614,
|
||||
"min": 23130.92,
|
||||
"max": 23824.148,
|
||||
"ci95": 861.106
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6007.033,
|
||||
"stdev": 104.227,
|
||||
"min": 5891.431,
|
||||
"max": 6093.825,
|
||||
"ci95": 258.936
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1282.11,
|
||||
"stdev": 65.207,
|
||||
"min": 1228.13,
|
||||
"max": 1354.56,
|
||||
"ci95": 161.997
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 343.465,
|
||||
"stdev": 9.96,
|
||||
"min": 335.223,
|
||||
"max": 354.532,
|
||||
"ci95": 24.744
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 131.669,
|
||||
"stdev": 4.692,
|
||||
"min": 126.427,
|
||||
"max": 135.476,
|
||||
"ci95": 11.656
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8669.311,
|
||||
"stdev": 434.39,
|
||||
"min": 8280.854,
|
||||
"max": 9138.35,
|
||||
"ci95": 1079.173
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1745.757,
|
||||
"stdev": 13.014,
|
||||
"min": 1734.41,
|
||||
"max": 1759.963,
|
||||
"ci95": 32.332
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 460.958,
|
||||
"stdev": 10.859,
|
||||
"min": 449.051,
|
||||
"max": 470.316,
|
||||
"ci95": 26.978
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 178.955,
|
||||
"stdev": 3.777,
|
||||
"min": 175.213,
|
||||
"max": 182.766,
|
||||
"ci95": 9.383
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 7056.368,
|
||||
"stdev": 117.329,
|
||||
"min": 6986.912,
|
||||
"max": 7191.833,
|
||||
"ci95": 291.485
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1815.056,
|
||||
"stdev": 47.875,
|
||||
"min": 1759.788,
|
||||
"max": 1843.745,
|
||||
"ci95": 118.937
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 514.215,
|
||||
"stdev": 57.205,
|
||||
"min": 452.445,
|
||||
"max": 565.368,
|
||||
"ci95": 142.117
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 191.842,
|
||||
"stdev": 23.217,
|
||||
"min": 175.546,
|
||||
"max": 218.426,
|
||||
"ci95": 57.68
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 14094.582,
|
||||
"stdev": 399.624,
|
||||
"min": 13641.534,
|
||||
"max": 14397.0,
|
||||
"ci95": 992.801
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1499.768,
|
||||
"stdev": 22.197,
|
||||
"min": 1477.269,
|
||||
"max": 1521.651,
|
||||
"ci95": 55.146
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 408.466,
|
||||
"stdev": 16.114,
|
||||
"min": 395.097,
|
||||
"max": 426.358,
|
||||
"ci95": 40.032
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 139.743,
|
||||
"stdev": 3.969,
|
||||
"min": 136.465,
|
||||
"max": 144.156,
|
||||
"ci95": 9.86
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2495.607,
|
||||
"stdev": 75.339,
|
||||
"min": 2412.738,
|
||||
"max": 2559.965,
|
||||
"ci95": 187.166
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2326.611,
|
||||
"stdev": 15.702,
|
||||
"min": 2314.98,
|
||||
"max": 2344.473,
|
||||
"ci95": 39.01
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 14738,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1228.13,
|
||||
"low_1pct_fps": 335.223,
|
||||
"low_01pct_fps": 133.103,
|
||||
"p50_ms": 0.722,
|
||||
"p95_ms": 1.384,
|
||||
"p99_ms": 2.043,
|
||||
"p999_ms": 5.224,
|
||||
"max_ms": 11.459,
|
||||
"histogram": [
|
||||
12159,
|
||||
2421,
|
||||
128,
|
||||
14,
|
||||
1,
|
||||
5,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 16255,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1354.56,
|
||||
"low_1pct_fps": 354.532,
|
||||
"low_01pct_fps": 135.476,
|
||||
"p50_ms": 0.672,
|
||||
"p95_ms": 1.136,
|
||||
"p99_ms": 1.841,
|
||||
"p999_ms": 4.913,
|
||||
"max_ms": 16.94,
|
||||
"histogram": [
|
||||
14841,
|
||||
1298,
|
||||
86,
|
||||
13,
|
||||
2,
|
||||
5,
|
||||
4,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 15164,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1263.64,
|
||||
"low_1pct_fps": 340.639,
|
||||
"low_01pct_fps": 126.427,
|
||||
"p50_ms": 0.708,
|
||||
"p95_ms": 1.299,
|
||||
"p99_ms": 1.895,
|
||||
"p999_ms": 5.173,
|
||||
"max_ms": 16.748,
|
||||
"histogram": [
|
||||
13026,
|
||||
2014,
|
||||
94,
|
||||
13,
|
||||
1,
|
||||
3,
|
||||
3,
|
||||
6,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 20915,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1742.897,
|
||||
"low_1pct_fps": 470.316,
|
||||
"low_01pct_fps": 182.766,
|
||||
"p50_ms": 0.5,
|
||||
"p95_ms": 0.936,
|
||||
"p99_ms": 1.437,
|
||||
"p999_ms": 2.77,
|
||||
"max_ms": 13.414,
|
||||
"histogram": [
|
||||
20067,
|
||||
788,
|
||||
44,
|
||||
4,
|
||||
0,
|
||||
4,
|
||||
3,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 21120,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1759.963,
|
||||
"low_1pct_fps": 449.051,
|
||||
"low_01pct_fps": 178.887,
|
||||
"p50_ms": 0.49,
|
||||
"p95_ms": 0.901,
|
||||
"p99_ms": 1.531,
|
||||
"p999_ms": 3.005,
|
||||
"max_ms": 12.907,
|
||||
"histogram": [
|
||||
20414,
|
||||
644,
|
||||
40,
|
||||
10,
|
||||
1,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 20813,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1734.41,
|
||||
"low_1pct_fps": 463.506,
|
||||
"low_01pct_fps": 175.213,
|
||||
"p50_ms": 0.496,
|
||||
"p95_ms": 0.924,
|
||||
"p99_ms": 1.414,
|
||||
"p999_ms": 2.733,
|
||||
"max_ms": 16.832,
|
||||
"histogram": [
|
||||
20049,
|
||||
707,
|
||||
41,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
5,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 22100,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1841.634,
|
||||
"low_1pct_fps": 565.368,
|
||||
"low_01pct_fps": 218.426,
|
||||
"p50_ms": 0.483,
|
||||
"p95_ms": 0.835,
|
||||
"p99_ms": 1.209,
|
||||
"p999_ms": 2.082,
|
||||
"max_ms": 14.627,
|
||||
"histogram": [
|
||||
21540,
|
||||
532,
|
||||
18,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 21118,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1759.788,
|
||||
"low_1pct_fps": 452.445,
|
||||
"low_01pct_fps": 175.546,
|
||||
"p50_ms": 0.489,
|
||||
"p95_ms": 0.915,
|
||||
"p99_ms": 1.532,
|
||||
"p999_ms": 2.811,
|
||||
"max_ms": 11.846,
|
||||
"histogram": [
|
||||
20308,
|
||||
755,
|
||||
36,
|
||||
9,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
3,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 22125,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1843.745,
|
||||
"low_1pct_fps": 524.832,
|
||||
"low_01pct_fps": 181.555,
|
||||
"p50_ms": 0.477,
|
||||
"p95_ms": 0.855,
|
||||
"p99_ms": 1.241,
|
||||
"p999_ms": 2.236,
|
||||
"max_ms": 12.478,
|
||||
"histogram": [
|
||||
21487,
|
||||
608,
|
||||
18,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 18005,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1500.383,
|
||||
"low_1pct_fps": 403.944,
|
||||
"low_01pct_fps": 136.465,
|
||||
"p50_ms": 0.591,
|
||||
"p95_ms": 1.058,
|
||||
"p99_ms": 1.592,
|
||||
"p999_ms": 3.186,
|
||||
"max_ms": 12.608,
|
||||
"histogram": [
|
||||
16864,
|
||||
1084,
|
||||
32,
|
||||
8,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
5,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 17728,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1477.269,
|
||||
"low_1pct_fps": 395.097,
|
||||
"low_01pct_fps": 138.609,
|
||||
"p50_ms": 0.598,
|
||||
"p95_ms": 1.042,
|
||||
"p99_ms": 1.561,
|
||||
"p999_ms": 5.033,
|
||||
"max_ms": 11.462,
|
||||
"histogram": [
|
||||
16612,
|
||||
1051,
|
||||
39,
|
||||
7,
|
||||
1,
|
||||
6,
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 18260,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1521.651,
|
||||
"low_1pct_fps": 426.358,
|
||||
"low_01pct_fps": 144.156,
|
||||
"p50_ms": 0.585,
|
||||
"p95_ms": 1.015,
|
||||
"p99_ms": 1.458,
|
||||
"p999_ms": 3.609,
|
||||
"max_ms": 11.945,
|
||||
"histogram": [
|
||||
17267,
|
||||
943,
|
||||
26,
|
||||
6,
|
||||
5,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T19:27:56Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 11038.922,
|
||||
"stdev": 118.058,
|
||||
"min": 10935.424,
|
||||
"max": 11167.506,
|
||||
"ci95": 293.295
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 39248.588,
|
||||
"stdev": 479.755,
|
||||
"min": 38964.834,
|
||||
"max": 39802.506,
|
||||
"ci95": 1191.875
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 11176.953,
|
||||
"stdev": 356.144,
|
||||
"min": 10836.65,
|
||||
"max": 11547.064,
|
||||
"ci95": 884.781
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 925.977,
|
||||
"stdev": 6.727,
|
||||
"min": 918.832,
|
||||
"max": 932.189,
|
||||
"ci95": 16.713
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 250.092,
|
||||
"stdev": 1.868,
|
||||
"min": 248.431,
|
||||
"max": 252.114,
|
||||
"ci95": 4.64
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 92.692,
|
||||
"stdev": 4.466,
|
||||
"min": 88.423,
|
||||
"max": 97.332,
|
||||
"ci95": 11.095
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 17335.638,
|
||||
"stdev": 687.588,
|
||||
"min": 16544.168,
|
||||
"max": 17785.772,
|
||||
"ci95": 1708.201
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 929.034,
|
||||
"stdev": 3.11,
|
||||
"min": 926.32,
|
||||
"max": 932.428,
|
||||
"ci95": 7.727
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 312.69,
|
||||
"stdev": 16.386,
|
||||
"min": 297.667,
|
||||
"max": 330.163,
|
||||
"ci95": 40.708
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 129.331,
|
||||
"stdev": 12.786,
|
||||
"min": 115.486,
|
||||
"max": 140.694,
|
||||
"ci95": 31.765
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 12601.063,
|
||||
"stdev": 148.042,
|
||||
"min": 12430.182,
|
||||
"max": 12690.506,
|
||||
"ci95": 367.785
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1016.598,
|
||||
"stdev": 5.481,
|
||||
"min": 1010.482,
|
||||
"max": 1021.068,
|
||||
"ci95": 13.618
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 325.361,
|
||||
"stdev": 15.112,
|
||||
"min": 315.682,
|
||||
"max": 342.774,
|
||||
"ci95": 37.543
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 117.042,
|
||||
"stdev": 11.095,
|
||||
"min": 107.807,
|
||||
"max": 129.349,
|
||||
"ci95": 27.563
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 38513.008,
|
||||
"stdev": 958.119,
|
||||
"min": 37447.333,
|
||||
"max": 39303.226,
|
||||
"ci95": 2380.292
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 644.782,
|
||||
"stdev": 3.94,
|
||||
"min": 640.866,
|
||||
"max": 648.745,
|
||||
"ci95": 9.788
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 166.029,
|
||||
"stdev": 4.758,
|
||||
"min": 162.326,
|
||||
"max": 171.395,
|
||||
"ci95": 11.819
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 86.231,
|
||||
"stdev": 8.587,
|
||||
"min": 76.632,
|
||||
"max": 93.184,
|
||||
"ci95": 21.334
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2964.911,
|
||||
"stdev": 8.27,
|
||||
"min": 2959.813,
|
||||
"max": 2974.453,
|
||||
"ci95": 20.545
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2894.541,
|
||||
"stdev": 12.847,
|
||||
"min": 2879.928,
|
||||
"max": 2904.059,
|
||||
"ci95": 31.917
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 11123,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 926.911,
|
||||
"low_1pct_fps": 249.732,
|
||||
"low_01pct_fps": 92.322,
|
||||
"p50_ms": 0.989,
|
||||
"p95_ms": 1.492,
|
||||
"p99_ms": 2.33,
|
||||
"p999_ms": 7.409,
|
||||
"max_ms": 15.258,
|
||||
"histogram": [
|
||||
6224,
|
||||
4701,
|
||||
147,
|
||||
28,
|
||||
3,
|
||||
2,
|
||||
5,
|
||||
3,
|
||||
3,
|
||||
3,
|
||||
1,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 11187,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 932.189,
|
||||
"low_1pct_fps": 252.114,
|
||||
"low_01pct_fps": 88.423,
|
||||
"p50_ms": 0.984,
|
||||
"p95_ms": 1.496,
|
||||
"p99_ms": 2.328,
|
||||
"p999_ms": 7.858,
|
||||
"max_ms": 16.843,
|
||||
"histogram": [
|
||||
6518,
|
||||
4486,
|
||||
138,
|
||||
20,
|
||||
9,
|
||||
1,
|
||||
1,
|
||||
6,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 11026,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 918.832,
|
||||
"low_1pct_fps": 248.431,
|
||||
"low_01pct_fps": 97.332,
|
||||
"p50_ms": 0.989,
|
||||
"p95_ms": 1.524,
|
||||
"p99_ms": 2.37,
|
||||
"p999_ms": 7.446,
|
||||
"max_ms": 16.573,
|
||||
"histogram": [
|
||||
6075,
|
||||
4740,
|
||||
162,
|
||||
23,
|
||||
5,
|
||||
2,
|
||||
4,
|
||||
7,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 11117,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 926.32,
|
||||
"low_1pct_fps": 310.239,
|
||||
"low_01pct_fps": 131.814,
|
||||
"p50_ms": 1.011,
|
||||
"p95_ms": 1.34,
|
||||
"p99_ms": 2.045,
|
||||
"p999_ms": 4.711,
|
||||
"max_ms": 14.077,
|
||||
"histogram": [
|
||||
3849,
|
||||
7150,
|
||||
78,
|
||||
26,
|
||||
5,
|
||||
1,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 11190,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 932.428,
|
||||
"low_1pct_fps": 330.163,
|
||||
"low_01pct_fps": 140.694,
|
||||
"p50_ms": 1.008,
|
||||
"p95_ms": 1.307,
|
||||
"p99_ms": 1.869,
|
||||
"p999_ms": 4.341,
|
||||
"max_ms": 13.489,
|
||||
"histogram": [
|
||||
4273,
|
||||
6822,
|
||||
60,
|
||||
20,
|
||||
7,
|
||||
0,
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 11141,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 928.354,
|
||||
"low_1pct_fps": 297.667,
|
||||
"low_01pct_fps": 115.486,
|
||||
"p50_ms": 1.005,
|
||||
"p95_ms": 1.352,
|
||||
"p99_ms": 2.054,
|
||||
"p999_ms": 5.292,
|
||||
"max_ms": 14.339,
|
||||
"histogram": [
|
||||
4901,
|
||||
6118,
|
||||
83,
|
||||
23,
|
||||
3,
|
||||
2,
|
||||
4,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 12126,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1010.482,
|
||||
"low_1pct_fps": 317.626,
|
||||
"low_01pct_fps": 113.971,
|
||||
"p50_ms": 0.933,
|
||||
"p95_ms": 1.23,
|
||||
"p99_ms": 1.935,
|
||||
"p999_ms": 4.393,
|
||||
"max_ms": 14.824,
|
||||
"histogram": [
|
||||
9183,
|
||||
2830,
|
||||
82,
|
||||
17,
|
||||
3,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 12219,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1018.243,
|
||||
"low_1pct_fps": 342.774,
|
||||
"low_01pct_fps": 129.349,
|
||||
"p50_ms": 0.929,
|
||||
"p95_ms": 1.222,
|
||||
"p99_ms": 1.867,
|
||||
"p999_ms": 4.329,
|
||||
"max_ms": 10.33,
|
||||
"histogram": [
|
||||
9421,
|
||||
2710,
|
||||
60,
|
||||
15,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 12253,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1021.068,
|
||||
"low_1pct_fps": 315.682,
|
||||
"low_01pct_fps": 107.807,
|
||||
"p50_ms": 0.923,
|
||||
"p95_ms": 1.225,
|
||||
"p99_ms": 1.969,
|
||||
"p999_ms": 5.235,
|
||||
"max_ms": 19.524,
|
||||
"histogram": [
|
||||
9231,
|
||||
2904,
|
||||
92,
|
||||
10,
|
||||
2,
|
||||
5,
|
||||
0,
|
||||
4,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 7691,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 640.866,
|
||||
"low_1pct_fps": 164.367,
|
||||
"low_01pct_fps": 93.184,
|
||||
"p50_ms": 1.454,
|
||||
"p95_ms": 1.95,
|
||||
"p99_ms": 3.4,
|
||||
"p999_ms": 9.754,
|
||||
"max_ms": 14.995,
|
||||
"histogram": [
|
||||
36,
|
||||
7331,
|
||||
233,
|
||||
26,
|
||||
17,
|
||||
13,
|
||||
20,
|
||||
3,
|
||||
6,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 7737,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 644.736,
|
||||
"low_1pct_fps": 162.326,
|
||||
"low_01pct_fps": 76.632,
|
||||
"p50_ms": 1.454,
|
||||
"p95_ms": 1.905,
|
||||
"p99_ms": 3.676,
|
||||
"p999_ms": 9.926,
|
||||
"max_ms": 18.459,
|
||||
"histogram": [
|
||||
46,
|
||||
7399,
|
||||
199,
|
||||
24,
|
||||
21,
|
||||
24,
|
||||
10,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 7785,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 648.745,
|
||||
"low_1pct_fps": 171.395,
|
||||
"low_01pct_fps": 88.876,
|
||||
"p50_ms": 1.439,
|
||||
"p95_ms": 1.886,
|
||||
"p99_ms": 3.562,
|
||||
"p999_ms": 10.342,
|
||||
"max_ms": 12.927,
|
||||
"histogram": [
|
||||
57,
|
||||
7432,
|
||||
186,
|
||||
44,
|
||||
23,
|
||||
20,
|
||||
9,
|
||||
3,
|
||||
3,
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,706 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T18:49:40Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
},
|
||||
{
|
||||
"name": "sodium",
|
||||
"version": "mc26.3-0.9.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "lithium",
|
||||
"version": "mc26.3-0.26.2-fabric"
|
||||
},
|
||||
{
|
||||
"name": "ferrite-core",
|
||||
"version": "9.0.0-fabric"
|
||||
},
|
||||
{
|
||||
"name": "immediatelyfast",
|
||||
"version": "1.17.1+26.3-fabric"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 11089.831,
|
||||
"stdev": 46.336,
|
||||
"min": 11036.36,
|
||||
"max": 11118.192,
|
||||
"ci95": 115.114
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 17643.831,
|
||||
"stdev": 47.672,
|
||||
"min": 17589.192,
|
||||
"max": 17676.942,
|
||||
"ci95": 118.433
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3603.773,
|
||||
"stdev": 161.342,
|
||||
"min": 3488.106,
|
||||
"max": 3788.086,
|
||||
"ci95": 400.828
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2103.54,
|
||||
"stdev": 40.465,
|
||||
"min": 2078.464,
|
||||
"max": 2150.222,
|
||||
"ci95": 100.529
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 577.326,
|
||||
"stdev": 33.693,
|
||||
"min": 557.613,
|
||||
"max": 616.23,
|
||||
"ci95": 83.704
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 195.53,
|
||||
"stdev": 18.899,
|
||||
"min": 181.495,
|
||||
"max": 217.019,
|
||||
"ci95": 46.951
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3282.612,
|
||||
"stdev": 48.569,
|
||||
"min": 3233.16,
|
||||
"max": 3330.246,
|
||||
"ci95": 120.661
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2424.739,
|
||||
"stdev": 26.074,
|
||||
"min": 2394.789,
|
||||
"max": 2442.383,
|
||||
"ci95": 64.777
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 732.987,
|
||||
"stdev": 11.926,
|
||||
"min": 724.144,
|
||||
"max": 746.55,
|
||||
"ci95": 29.627
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 249.926,
|
||||
"stdev": 8.826,
|
||||
"min": 241.293,
|
||||
"max": 258.934,
|
||||
"ci95": 21.928
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 2705.954,
|
||||
"stdev": 173.487,
|
||||
"min": 2538.486,
|
||||
"max": 2884.891,
|
||||
"ci95": 431.0
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2431.99,
|
||||
"stdev": 33.071,
|
||||
"min": 2394.02,
|
||||
"max": 2454.493,
|
||||
"ci95": 82.159
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 764.065,
|
||||
"stdev": 14.782,
|
||||
"min": 747.287,
|
||||
"max": 775.168,
|
||||
"ci95": 36.723
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 261.954,
|
||||
"stdev": 14.724,
|
||||
"min": 252.457,
|
||||
"max": 278.916,
|
||||
"ci95": 36.58
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 4982.865,
|
||||
"stdev": 115.523,
|
||||
"min": 4849.837,
|
||||
"max": 5057.932,
|
||||
"ci95": 286.997
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2538.05,
|
||||
"stdev": 67.405,
|
||||
"min": 2462.815,
|
||||
"max": 2592.938,
|
||||
"ci95": 167.458
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 760.16,
|
||||
"stdev": 13.503,
|
||||
"min": 746.001,
|
||||
"max": 772.895,
|
||||
"ci95": 33.547
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 240.897,
|
||||
"stdev": 17.872,
|
||||
"min": 224.391,
|
||||
"max": 259.878,
|
||||
"ci95": 44.401
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2052.982,
|
||||
"stdev": 57.756,
|
||||
"min": 1992.574,
|
||||
"max": 2107.66,
|
||||
"ci95": 143.487
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1903.921,
|
||||
"stdev": 62.254,
|
||||
"min": 1838.307,
|
||||
"max": 1962.156,
|
||||
"ci95": 154.659
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 25803,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2150.222,
|
||||
"low_1pct_fps": 616.23,
|
||||
"low_01pct_fps": 217.019,
|
||||
"p50_ms": 0.433,
|
||||
"p95_ms": 0.642,
|
||||
"p99_ms": 1.04,
|
||||
"p999_ms": 2.307,
|
||||
"max_ms": 7.466,
|
||||
"histogram": [
|
||||
25503,
|
||||
269,
|
||||
8,
|
||||
6,
|
||||
7,
|
||||
6,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 24942,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2078.464,
|
||||
"low_1pct_fps": 557.613,
|
||||
"low_01pct_fps": 181.495,
|
||||
"p50_ms": 0.45,
|
||||
"p95_ms": 0.665,
|
||||
"p99_ms": 1.1,
|
||||
"p999_ms": 2.305,
|
||||
"max_ms": 9.819,
|
||||
"histogram": [
|
||||
24615,
|
||||
288,
|
||||
17,
|
||||
2,
|
||||
4,
|
||||
9,
|
||||
2,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 24984,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2081.934,
|
||||
"low_1pct_fps": 558.135,
|
||||
"low_01pct_fps": 188.076,
|
||||
"p50_ms": 0.444,
|
||||
"p95_ms": 0.682,
|
||||
"p99_ms": 1.101,
|
||||
"p999_ms": 2.412,
|
||||
"max_ms": 11.567,
|
||||
"histogram": [
|
||||
24645,
|
||||
308,
|
||||
9,
|
||||
3,
|
||||
5,
|
||||
5,
|
||||
7,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 29245,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2437.044,
|
||||
"low_1pct_fps": 728.266,
|
||||
"low_01pct_fps": 249.55,
|
||||
"p50_ms": 0.38,
|
||||
"p95_ms": 0.555,
|
||||
"p99_ms": 0.892,
|
||||
"p999_ms": 1.851,
|
||||
"max_ms": 6.973,
|
||||
"histogram": [
|
||||
29066,
|
||||
154,
|
||||
4,
|
||||
6,
|
||||
7,
|
||||
6,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 28738,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2394.789,
|
||||
"low_1pct_fps": 724.144,
|
||||
"low_01pct_fps": 241.293,
|
||||
"p50_ms": 0.384,
|
||||
"p95_ms": 0.571,
|
||||
"p99_ms": 0.907,
|
||||
"p999_ms": 1.833,
|
||||
"max_ms": 8.35,
|
||||
"histogram": [
|
||||
28573,
|
||||
140,
|
||||
6,
|
||||
3,
|
||||
6,
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 29309,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2442.383,
|
||||
"low_1pct_fps": 746.55,
|
||||
"low_01pct_fps": 258.934,
|
||||
"p50_ms": 0.378,
|
||||
"p95_ms": 0.566,
|
||||
"p99_ms": 0.876,
|
||||
"p999_ms": 1.744,
|
||||
"max_ms": 10.291,
|
||||
"histogram": [
|
||||
29138,
|
||||
148,
|
||||
5,
|
||||
6,
|
||||
5,
|
||||
2,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 29454,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2454.493,
|
||||
"low_1pct_fps": 769.741,
|
||||
"low_01pct_fps": 252.457,
|
||||
"p50_ms": 0.378,
|
||||
"p95_ms": 0.55,
|
||||
"p99_ms": 0.853,
|
||||
"p999_ms": 1.471,
|
||||
"max_ms": 6.629,
|
||||
"histogram": [
|
||||
29323,
|
||||
110,
|
||||
2,
|
||||
2,
|
||||
7,
|
||||
7,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 28729,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2394.02,
|
||||
"low_1pct_fps": 747.287,
|
||||
"low_01pct_fps": 254.49,
|
||||
"p50_ms": 0.383,
|
||||
"p95_ms": 0.579,
|
||||
"p99_ms": 0.896,
|
||||
"p999_ms": 1.56,
|
||||
"max_ms": 7.367,
|
||||
"histogram": [
|
||||
28567,
|
||||
141,
|
||||
3,
|
||||
5,
|
||||
4,
|
||||
4,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 29370,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2447.458,
|
||||
"low_1pct_fps": 775.168,
|
||||
"low_01pct_fps": 278.916,
|
||||
"p50_ms": 0.376,
|
||||
"p95_ms": 0.559,
|
||||
"p99_ms": 0.887,
|
||||
"p999_ms": 1.567,
|
||||
"max_ms": 9.65,
|
||||
"histogram": [
|
||||
29209,
|
||||
141,
|
||||
3,
|
||||
9,
|
||||
0,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 31116,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2592.938,
|
||||
"low_1pct_fps": 761.584,
|
||||
"low_01pct_fps": 224.391,
|
||||
"p50_ms": 0.356,
|
||||
"p95_ms": 0.511,
|
||||
"p99_ms": 0.767,
|
||||
"p999_ms": 1.843,
|
||||
"max_ms": 8.478,
|
||||
"histogram": [
|
||||
31011,
|
||||
76,
|
||||
4,
|
||||
3,
|
||||
13,
|
||||
4,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 29554,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2462.815,
|
||||
"low_1pct_fps": 746.001,
|
||||
"low_01pct_fps": 238.423,
|
||||
"p50_ms": 0.366,
|
||||
"p95_ms": 0.579,
|
||||
"p99_ms": 0.849,
|
||||
"p999_ms": 1.75,
|
||||
"max_ms": 7.607,
|
||||
"histogram": [
|
||||
29430,
|
||||
101,
|
||||
2,
|
||||
3,
|
||||
9,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 30701,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2558.396,
|
||||
"low_1pct_fps": 772.895,
|
||||
"low_01pct_fps": 259.878,
|
||||
"p50_ms": 0.357,
|
||||
"p95_ms": 0.537,
|
||||
"p99_ms": 0.81,
|
||||
"p999_ms": 1.702,
|
||||
"max_ms": 6.682,
|
||||
"histogram": [
|
||||
30568,
|
||||
112,
|
||||
1,
|
||||
6,
|
||||
5,
|
||||
3,
|
||||
6,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-mods-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,690 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T01:19:23Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 16,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 7681.834,
|
||||
"stdev": 189.48,
|
||||
"min": 7538.777,
|
||||
"max": 7896.728,
|
||||
"ci95": 470.732
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 19898.834,
|
||||
"stdev": 192.981,
|
||||
"min": 19695.728,
|
||||
"max": 20079.777,
|
||||
"ci95": 479.431
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6127.947,
|
||||
"stdev": 26.756,
|
||||
"min": 6097.19,
|
||||
"max": 6145.854,
|
||||
"ci95": 66.471
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1218.486,
|
||||
"stdev": 26.337,
|
||||
"min": 1188.13,
|
||||
"max": 1235.248,
|
||||
"ci95": 65.43
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 318.468,
|
||||
"stdev": 6.292,
|
||||
"min": 313.2,
|
||||
"max": 325.435,
|
||||
"ci95": 15.632
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 126.59,
|
||||
"stdev": 1.844,
|
||||
"min": 124.744,
|
||||
"max": 128.431,
|
||||
"ci95": 4.58
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 8548.814,
|
||||
"stdev": 152.302,
|
||||
"min": 8380.912,
|
||||
"max": 8678.071,
|
||||
"ci95": 378.37
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1912.359,
|
||||
"stdev": 130.238,
|
||||
"min": 1791.386,
|
||||
"max": 2050.215,
|
||||
"ci95": 323.555
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 401.907,
|
||||
"stdev": 35.911,
|
||||
"min": 379.849,
|
||||
"max": 443.345,
|
||||
"ci95": 89.216
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 149.26,
|
||||
"stdev": 9.983,
|
||||
"min": 139.809,
|
||||
"max": 159.701,
|
||||
"ci95": 24.801
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6953.478,
|
||||
"stdev": 276.636,
|
||||
"min": 6635.649,
|
||||
"max": 7140.072,
|
||||
"ci95": 687.258
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1860.512,
|
||||
"stdev": 116.512,
|
||||
"min": 1726.149,
|
||||
"max": 1933.597,
|
||||
"ci95": 289.454
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 446.336,
|
||||
"stdev": 56.993,
|
||||
"min": 382.26,
|
||||
"max": 491.369,
|
||||
"ci95": 141.589
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 164.934,
|
||||
"stdev": 11.839,
|
||||
"min": 152.493,
|
||||
"max": 176.062,
|
||||
"ci95": 29.413
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 15211.386,
|
||||
"stdev": 256.348,
|
||||
"min": 14938.008,
|
||||
"max": 15446.375,
|
||||
"ci95": 636.856
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1653.223,
|
||||
"stdev": 61.705,
|
||||
"min": 1584.652,
|
||||
"max": 1704.273,
|
||||
"ci95": 153.297
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 331.929,
|
||||
"stdev": 10.858,
|
||||
"min": 319.394,
|
||||
"max": 338.396,
|
||||
"ci95": 26.974
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 113.436,
|
||||
"stdev": 3.255,
|
||||
"min": 110.869,
|
||||
"max": 117.097,
|
||||
"ci95": 8.086
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2540.129,
|
||||
"stdev": 152.057,
|
||||
"min": 2373.152,
|
||||
"max": 2670.633,
|
||||
"ci95": 377.761
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2299.514,
|
||||
"stdev": 81.451,
|
||||
"min": 2207.129,
|
||||
"max": 2360.973,
|
||||
"ci95": 202.352
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 14785,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1232.081,
|
||||
"low_1pct_fps": 325.435,
|
||||
"low_01pct_fps": 128.431,
|
||||
"p50_ms": 0.742,
|
||||
"p95_ms": 1.265,
|
||||
"p99_ms": 2.032,
|
||||
"p999_ms": 5.653,
|
||||
"max_ms": 12.791,
|
||||
"histogram": [
|
||||
12845,
|
||||
1784,
|
||||
127,
|
||||
7,
|
||||
1,
|
||||
8,
|
||||
4,
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 14258,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1188.13,
|
||||
"low_1pct_fps": 313.2,
|
||||
"low_01pct_fps": 126.595,
|
||||
"p50_ms": 0.757,
|
||||
"p95_ms": 1.349,
|
||||
"p99_ms": 2.12,
|
||||
"p999_ms": 5.541,
|
||||
"max_ms": 13.998,
|
||||
"histogram": [
|
||||
11994,
|
||||
2076,
|
||||
157,
|
||||
9,
|
||||
2,
|
||||
8,
|
||||
2,
|
||||
4,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 14823,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1235.248,
|
||||
"low_1pct_fps": 316.768,
|
||||
"low_01pct_fps": 124.744,
|
||||
"p50_ms": 0.744,
|
||||
"p95_ms": 1.199,
|
||||
"p99_ms": 2.047,
|
||||
"p999_ms": 5.628,
|
||||
"max_ms": 15.519,
|
||||
"histogram": [
|
||||
13214,
|
||||
1453,
|
||||
118,
|
||||
16,
|
||||
2,
|
||||
8,
|
||||
6,
|
||||
3,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 21497,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1791.386,
|
||||
"low_1pct_fps": 382.527,
|
||||
"low_01pct_fps": 139.809,
|
||||
"p50_ms": 0.474,
|
||||
"p95_ms": 0.931,
|
||||
"p99_ms": 1.646,
|
||||
"p999_ms": 5.274,
|
||||
"max_ms": 13.459,
|
||||
"histogram": [
|
||||
20598,
|
||||
799,
|
||||
66,
|
||||
9,
|
||||
3,
|
||||
8,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 24603,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2050.215,
|
||||
"low_1pct_fps": 443.345,
|
||||
"low_01pct_fps": 159.701,
|
||||
"p50_ms": 0.426,
|
||||
"p95_ms": 0.752,
|
||||
"p99_ms": 1.442,
|
||||
"p999_ms": 3.134,
|
||||
"max_ms": 13.282,
|
||||
"histogram": [
|
||||
24041,
|
||||
487,
|
||||
48,
|
||||
6,
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
3,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 22746,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1895.476,
|
||||
"low_1pct_fps": 379.849,
|
||||
"low_01pct_fps": 148.269,
|
||||
"p50_ms": 0.456,
|
||||
"p95_ms": 0.829,
|
||||
"p99_ms": 1.561,
|
||||
"p999_ms": 4.176,
|
||||
"max_ms": 10.671,
|
||||
"histogram": [
|
||||
22092,
|
||||
523,
|
||||
91,
|
||||
17,
|
||||
4,
|
||||
7,
|
||||
3,
|
||||
4,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 23062,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1921.791,
|
||||
"low_1pct_fps": 465.379,
|
||||
"low_01pct_fps": 166.247,
|
||||
"p50_ms": 0.463,
|
||||
"p95_ms": 0.809,
|
||||
"p99_ms": 1.45,
|
||||
"p999_ms": 2.398,
|
||||
"max_ms": 11.808,
|
||||
"histogram": [
|
||||
22454,
|
||||
561,
|
||||
27,
|
||||
3,
|
||||
2,
|
||||
6,
|
||||
0,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 23204,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1933.597,
|
||||
"low_1pct_fps": 491.369,
|
||||
"low_01pct_fps": 176.062,
|
||||
"p50_ms": 0.466,
|
||||
"p95_ms": 0.766,
|
||||
"p99_ms": 1.406,
|
||||
"p999_ms": 2.229,
|
||||
"max_ms": 15.102,
|
||||
"histogram": [
|
||||
22699,
|
||||
469,
|
||||
19,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
4,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 20714,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1726.149,
|
||||
"low_1pct_fps": 382.26,
|
||||
"low_01pct_fps": 152.493,
|
||||
"p50_ms": 0.5,
|
||||
"p95_ms": 0.956,
|
||||
"p99_ms": 1.742,
|
||||
"p999_ms": 3.852,
|
||||
"max_ms": 12.888,
|
||||
"histogram": [
|
||||
19814,
|
||||
787,
|
||||
83,
|
||||
11,
|
||||
2,
|
||||
7,
|
||||
3,
|
||||
5,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 20049,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1670.745,
|
||||
"low_1pct_fps": 338.396,
|
||||
"low_01pct_fps": 117.097,
|
||||
"p50_ms": 0.502,
|
||||
"p95_ms": 0.949,
|
||||
"p99_ms": 1.673,
|
||||
"p999_ms": 6.456,
|
||||
"max_ms": 16.791,
|
||||
"histogram": [
|
||||
19187,
|
||||
753,
|
||||
70,
|
||||
8,
|
||||
1,
|
||||
6,
|
||||
12,
|
||||
4,
|
||||
3,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 19016,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1584.652,
|
||||
"low_1pct_fps": 337.998,
|
||||
"low_01pct_fps": 112.343,
|
||||
"p50_ms": 0.531,
|
||||
"p95_ms": 1.082,
|
||||
"p99_ms": 1.717,
|
||||
"p999_ms": 5.939,
|
||||
"max_ms": 12.958,
|
||||
"histogram": [
|
||||
17849,
|
||||
1069,
|
||||
63,
|
||||
7,
|
||||
3,
|
||||
6,
|
||||
2,
|
||||
7,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 20452,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1704.273,
|
||||
"low_1pct_fps": 319.394,
|
||||
"low_01pct_fps": 110.869,
|
||||
"p50_ms": 0.496,
|
||||
"p95_ms": 0.911,
|
||||
"p99_ms": 1.706,
|
||||
"p999_ms": 5.938,
|
||||
"max_ms": 24.863,
|
||||
"histogram": [
|
||||
19694,
|
||||
626,
|
||||
82,
|
||||
14,
|
||||
3,
|
||||
14,
|
||||
5,
|
||||
4,
|
||||
5,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,690 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T19:06:49Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 32,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 7518.874,
|
||||
"stdev": 42.968,
|
||||
"min": 7469.532,
|
||||
"max": 7548.049,
|
||||
"ci95": 106.748
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 35424.207,
|
||||
"stdev": 144.711,
|
||||
"min": 35318.049,
|
||||
"max": 35589.041,
|
||||
"ci95": 359.511
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 11146.828,
|
||||
"stdev": 49.683,
|
||||
"min": 11094.798,
|
||||
"max": 11193.773,
|
||||
"ci95": 123.43
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 882.053,
|
||||
"stdev": 19.433,
|
||||
"min": 866.126,
|
||||
"max": 903.706,
|
||||
"ci95": 48.279
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 183.995,
|
||||
"stdev": 4.924,
|
||||
"min": 178.512,
|
||||
"max": 188.041,
|
||||
"ci95": 12.234
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 83.193,
|
||||
"stdev": 6.797,
|
||||
"min": 77.734,
|
||||
"max": 90.806,
|
||||
"ci95": 16.886
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 18184.002,
|
||||
"stdev": 266.879,
|
||||
"min": 17880.667,
|
||||
"max": 18382.735,
|
||||
"ci95": 663.017
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1202.907,
|
||||
"stdev": 20.426,
|
||||
"min": 1179.9,
|
||||
"max": 1218.906,
|
||||
"ci95": 50.744
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 228.139,
|
||||
"stdev": 5.166,
|
||||
"min": 222.394,
|
||||
"max": 232.401,
|
||||
"ci95": 12.833
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 107.956,
|
||||
"stdev": 4.675,
|
||||
"min": 105.185,
|
||||
"max": 113.354,
|
||||
"ci95": 11.614
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 13146.632,
|
||||
"stdev": 507.943,
|
||||
"min": 12572.118,
|
||||
"max": 13536.145,
|
||||
"ci95": 1261.902
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 1223.169,
|
||||
"stdev": 13.11,
|
||||
"min": 1208.837,
|
||||
"max": 1234.556,
|
||||
"ci95": 32.569
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 236.27,
|
||||
"stdev": 6.77,
|
||||
"min": 228.686,
|
||||
"max": 241.702,
|
||||
"ci95": 16.818
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 99.089,
|
||||
"stdev": 8.354,
|
||||
"min": 91.897,
|
||||
"max": 108.253,
|
||||
"ci95": 20.755
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 41846.641,
|
||||
"stdev": 661.649,
|
||||
"min": 41435.666,
|
||||
"max": 42609.895,
|
||||
"ci95": 1643.76
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 815.008,
|
||||
"stdev": 24.644,
|
||||
"min": 797.565,
|
||||
"max": 843.201,
|
||||
"ci95": 61.224
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 55.371,
|
||||
"stdev": 5.128,
|
||||
"min": 50.389,
|
||||
"max": 60.633,
|
||||
"ci95": 12.739
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 7.966,
|
||||
"stdev": 1.103,
|
||||
"min": 6.848,
|
||||
"max": 9.053,
|
||||
"ci95": 2.74
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2892.492,
|
||||
"stdev": 29.54,
|
||||
"min": 2859.574,
|
||||
"max": 2916.691,
|
||||
"ci95": 73.387
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 2799.159,
|
||||
"stdev": 12.256,
|
||||
"min": 2786.234,
|
||||
"max": 2810.613,
|
||||
"ci95": 30.447
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 10845,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 903.706,
|
||||
"low_1pct_fps": 185.432,
|
||||
"low_01pct_fps": 81.039,
|
||||
"p50_ms": 0.98,
|
||||
"p95_ms": 1.708,
|
||||
"p99_ms": 3.082,
|
||||
"p999_ms": 9.304,
|
||||
"max_ms": 15.487,
|
||||
"histogram": [
|
||||
6030,
|
||||
4403,
|
||||
297,
|
||||
49,
|
||||
25,
|
||||
16,
|
||||
8,
|
||||
2,
|
||||
6,
|
||||
2,
|
||||
4,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 10516,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 876.328,
|
||||
"low_1pct_fps": 188.041,
|
||||
"low_01pct_fps": 90.806,
|
||||
"p50_ms": 1.012,
|
||||
"p95_ms": 1.806,
|
||||
"p99_ms": 3.354,
|
||||
"p999_ms": 8.714,
|
||||
"max_ms": 14.39,
|
||||
"histogram": [
|
||||
4927,
|
||||
5158,
|
||||
292,
|
||||
70,
|
||||
33,
|
||||
13,
|
||||
6,
|
||||
5,
|
||||
6,
|
||||
2,
|
||||
3,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 10394,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 866.126,
|
||||
"low_1pct_fps": 178.512,
|
||||
"low_01pct_fps": 77.734,
|
||||
"p50_ms": 1.026,
|
||||
"p95_ms": 1.789,
|
||||
"p99_ms": 3.399,
|
||||
"p999_ms": 10.6,
|
||||
"max_ms": 15.389,
|
||||
"histogram": [
|
||||
4437,
|
||||
5552,
|
||||
273,
|
||||
65,
|
||||
18,
|
||||
28,
|
||||
8,
|
||||
1,
|
||||
1,
|
||||
3,
|
||||
5,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 14519,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1209.916,
|
||||
"low_1pct_fps": 232.401,
|
||||
"low_01pct_fps": 105.185,
|
||||
"p50_ms": 0.726,
|
||||
"p95_ms": 1.306,
|
||||
"p99_ms": 2.25,
|
||||
"p999_ms": 7.033,
|
||||
"max_ms": 13.303,
|
||||
"histogram": [
|
||||
13121,
|
||||
1197,
|
||||
103,
|
||||
36,
|
||||
24,
|
||||
19,
|
||||
4,
|
||||
3,
|
||||
8,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 14159,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1179.9,
|
||||
"low_1pct_fps": 222.394,
|
||||
"low_01pct_fps": 105.33,
|
||||
"p50_ms": 0.732,
|
||||
"p95_ms": 1.366,
|
||||
"p99_ms": 2.499,
|
||||
"p999_ms": 8.061,
|
||||
"max_ms": 11.797,
|
||||
"histogram": [
|
||||
12501,
|
||||
1356,
|
||||
195,
|
||||
45,
|
||||
25,
|
||||
14,
|
||||
6,
|
||||
3,
|
||||
9,
|
||||
5,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 14627,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1218.906,
|
||||
"low_1pct_fps": 229.622,
|
||||
"low_01pct_fps": 113.354,
|
||||
"p50_ms": 0.713,
|
||||
"p95_ms": 1.292,
|
||||
"p99_ms": 2.317,
|
||||
"p999_ms": 7.136,
|
||||
"max_ms": 12.041,
|
||||
"histogram": [
|
||||
13194,
|
||||
1224,
|
||||
97,
|
||||
47,
|
||||
27,
|
||||
21,
|
||||
2,
|
||||
6,
|
||||
6,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 14714,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1226.113,
|
||||
"low_1pct_fps": 238.423,
|
||||
"low_01pct_fps": 97.117,
|
||||
"p50_ms": 0.722,
|
||||
"p95_ms": 1.223,
|
||||
"p99_ms": 2.243,
|
||||
"p999_ms": 7.032,
|
||||
"max_ms": 13.21,
|
||||
"histogram": [
|
||||
13490,
|
||||
1027,
|
||||
115,
|
||||
29,
|
||||
18,
|
||||
13,
|
||||
7,
|
||||
3,
|
||||
3,
|
||||
5,
|
||||
4,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 14507,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 1208.837,
|
||||
"low_1pct_fps": 228.686,
|
||||
"low_01pct_fps": 91.897,
|
||||
"p50_ms": 0.719,
|
||||
"p95_ms": 1.256,
|
||||
"p99_ms": 2.354,
|
||||
"p999_ms": 7.473,
|
||||
"max_ms": 15.432,
|
||||
"histogram": [
|
||||
13124,
|
||||
1112,
|
||||
180,
|
||||
35,
|
||||
23,
|
||||
9,
|
||||
8,
|
||||
4,
|
||||
2,
|
||||
6,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 14815,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 1234.556,
|
||||
"low_1pct_fps": 241.702,
|
||||
"low_01pct_fps": 108.253,
|
||||
"p50_ms": 0.721,
|
||||
"p95_ms": 1.2,
|
||||
"p99_ms": 2.197,
|
||||
"p999_ms": 6.689,
|
||||
"max_ms": 12.791,
|
||||
"histogram": [
|
||||
13565,
|
||||
1055,
|
||||
107,
|
||||
29,
|
||||
23,
|
||||
15,
|
||||
8,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 10119,
|
||||
"seconds": 12.001,
|
||||
"avg_fps": 843.201,
|
||||
"low_1pct_fps": 60.633,
|
||||
"low_01pct_fps": 9.053,
|
||||
"p50_ms": 0.891,
|
||||
"p95_ms": 1.845,
|
||||
"p99_ms": 3.91,
|
||||
"p999_ms": 8.209,
|
||||
"max_ms": 316.409,
|
||||
"histogram": [
|
||||
6956,
|
||||
2747,
|
||||
240,
|
||||
83,
|
||||
45,
|
||||
22,
|
||||
8,
|
||||
8,
|
||||
5,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 9693,
|
||||
"seconds": 12.052,
|
||||
"avg_fps": 804.258,
|
||||
"low_1pct_fps": 50.389,
|
||||
"low_01pct_fps": 6.848,
|
||||
"p50_ms": 0.906,
|
||||
"p95_ms": 1.924,
|
||||
"p99_ms": 4.157,
|
||||
"p999_ms": 8.578,
|
||||
"max_ms": 297.695,
|
||||
"histogram": [
|
||||
6578,
|
||||
2678,
|
||||
248,
|
||||
94,
|
||||
45,
|
||||
18,
|
||||
16,
|
||||
5,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
5,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 9571,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 797.565,
|
||||
"low_1pct_fps": 55.09,
|
||||
"low_01pct_fps": 7.997,
|
||||
"p50_ms": 0.929,
|
||||
"p95_ms": 1.944,
|
||||
"p99_ms": 4.495,
|
||||
"p999_ms": 7.764,
|
||||
"max_ms": 321.994,
|
||||
"histogram": [
|
||||
5954,
|
||||
3172,
|
||||
230,
|
||||
103,
|
||||
39,
|
||||
34,
|
||||
19,
|
||||
11,
|
||||
4,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
4,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,690 +0,0 @@
|
||||
{
|
||||
"format": "horizon-benchmark-report",
|
||||
"version": 1,
|
||||
"kind": "game",
|
||||
"created": "2026-10-29T18:43:17Z",
|
||||
"app": {
|
||||
"name": "minecraft",
|
||||
"version": "26.3",
|
||||
"mods": [
|
||||
{
|
||||
"name": "fabric-loader",
|
||||
"version": "0.19.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
"hardware": {
|
||||
"os": "windows",
|
||||
"arch": "x86_64",
|
||||
"cpu_threads": 16,
|
||||
"os_version": "Microsoft Windows [Version 10.0.26200.8037]",
|
||||
"cpu": "AMD Ryzen 7 9800X3D 8-Core Processor",
|
||||
"ram_mb": 95943,
|
||||
"gpu": {
|
||||
"name": "NVIDIA GeForce RTX 5080/PCIe/SSE2",
|
||||
"vendor": "NVIDIA Corporation",
|
||||
"driver": "3.3.0 NVIDIA 617.42",
|
||||
"backend": "opengl",
|
||||
"kind": ""
|
||||
}
|
||||
},
|
||||
"conditions": {
|
||||
"scenario": "perf_bench:village,forest,ocean,mountain",
|
||||
"seed": "1234",
|
||||
"render_distance": 8,
|
||||
"simulation_distance": 12,
|
||||
"vsync": false,
|
||||
"offscreen": false,
|
||||
"repeats": 3,
|
||||
"warmup_s": 2.0,
|
||||
"window": [
|
||||
1280,
|
||||
720
|
||||
]
|
||||
},
|
||||
"metrics": {
|
||||
"startup.title_ms": {
|
||||
"n": 3,
|
||||
"mean": 7676.526,
|
||||
"stdev": 305.763,
|
||||
"min": 7426.024,
|
||||
"max": 8017.247,
|
||||
"ci95": 759.617
|
||||
},
|
||||
"startup.world_ms": {
|
||||
"n": 3,
|
||||
"mean": 13862.526,
|
||||
"stdev": 284.577,
|
||||
"min": 13569.024,
|
||||
"max": 14137.247,
|
||||
"ci95": 706.985
|
||||
},
|
||||
"chunks.village.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3808.014,
|
||||
"stdev": 61.275,
|
||||
"min": 3737.989,
|
||||
"max": 3851.799,
|
||||
"ci95": 152.227
|
||||
},
|
||||
"fps.village.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2216.576,
|
||||
"stdev": 45.247,
|
||||
"min": 2166.285,
|
||||
"max": 2253.985,
|
||||
"ci95": 112.409
|
||||
},
|
||||
"fps.village.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 545.307,
|
||||
"stdev": 14.876,
|
||||
"min": 528.15,
|
||||
"max": 554.607,
|
||||
"ci95": 36.957
|
||||
},
|
||||
"fps.village.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 215.412,
|
||||
"stdev": 5.692,
|
||||
"min": 209.522,
|
||||
"max": 220.882,
|
||||
"ci95": 14.14
|
||||
},
|
||||
"chunks.forest.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 3212.958,
|
||||
"stdev": 151.722,
|
||||
"min": 3076.655,
|
||||
"max": 3376.428,
|
||||
"ci95": 376.928
|
||||
},
|
||||
"fps.forest.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2456.542,
|
||||
"stdev": 336.369,
|
||||
"min": 2068.162,
|
||||
"max": 2654.549,
|
||||
"ci95": 835.654
|
||||
},
|
||||
"fps.forest.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 624.759,
|
||||
"stdev": 90.0,
|
||||
"min": 521.303,
|
||||
"max": 685.008,
|
||||
"ci95": 223.59
|
||||
},
|
||||
"fps.forest.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 252.469,
|
||||
"stdev": 21.044,
|
||||
"min": 229.228,
|
||||
"max": 270.233,
|
||||
"ci95": 52.28
|
||||
},
|
||||
"chunks.ocean.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 2983.236,
|
||||
"stdev": 168.416,
|
||||
"min": 2788.777,
|
||||
"max": 3082.249,
|
||||
"ci95": 418.403
|
||||
},
|
||||
"fps.ocean.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2469.831,
|
||||
"stdev": 333.258,
|
||||
"min": 2085.121,
|
||||
"max": 2669.9,
|
||||
"ci95": 827.925
|
||||
},
|
||||
"fps.ocean.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 688.684,
|
||||
"stdev": 96.943,
|
||||
"min": 576.803,
|
||||
"max": 747.759,
|
||||
"ci95": 240.839
|
||||
},
|
||||
"fps.ocean.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 286.444,
|
||||
"stdev": 21.36,
|
||||
"min": 262.183,
|
||||
"max": 302.422,
|
||||
"ci95": 53.066
|
||||
},
|
||||
"chunks.mountain.load_ms": {
|
||||
"n": 3,
|
||||
"mean": 6079.869,
|
||||
"stdev": 719.864,
|
||||
"min": 5542.196,
|
||||
"max": 6897.69,
|
||||
"ci95": 1788.385
|
||||
},
|
||||
"fps.mountain.avg_fps": {
|
||||
"n": 3,
|
||||
"mean": 2605.12,
|
||||
"stdev": 326.424,
|
||||
"min": 2228.824,
|
||||
"max": 2812.075,
|
||||
"ci95": 810.948
|
||||
},
|
||||
"fps.mountain.low_1pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 699.63,
|
||||
"stdev": 87.846,
|
||||
"min": 599.44,
|
||||
"max": 763.45,
|
||||
"ci95": 218.239
|
||||
},
|
||||
"fps.mountain.low_01pct_fps": {
|
||||
"n": 3,
|
||||
"mean": 264.461,
|
||||
"stdev": 28.459,
|
||||
"min": 239.602,
|
||||
"max": 295.503,
|
||||
"ci95": 70.701
|
||||
},
|
||||
"memory.rss_peak_mb": {
|
||||
"n": 3,
|
||||
"mean": 2120.426,
|
||||
"stdev": 116.406,
|
||||
"min": 2046.93,
|
||||
"max": 2254.637,
|
||||
"ci95": 289.191
|
||||
},
|
||||
"memory.rss_steady_mb": {
|
||||
"n": 3,
|
||||
"mean": 1912.642,
|
||||
"stdev": 38.925,
|
||||
"min": 1889.766,
|
||||
"max": 1957.586,
|
||||
"ci95": 96.702
|
||||
}
|
||||
},
|
||||
"frames": [
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 0,
|
||||
"frames": 27048,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2253.985,
|
||||
"low_1pct_fps": 553.164,
|
||||
"low_01pct_fps": 215.833,
|
||||
"p50_ms": 0.412,
|
||||
"p95_ms": 0.617,
|
||||
"p99_ms": 1.187,
|
||||
"p999_ms": 2.238,
|
||||
"max_ms": 9.792,
|
||||
"histogram": [
|
||||
26716,
|
||||
296,
|
||||
15,
|
||||
4,
|
||||
7,
|
||||
5,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 1,
|
||||
"frames": 26754,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2229.458,
|
||||
"low_1pct_fps": 554.607,
|
||||
"low_01pct_fps": 220.882,
|
||||
"p50_ms": 0.417,
|
||||
"p95_ms": 0.626,
|
||||
"p99_ms": 1.212,
|
||||
"p999_ms": 2.448,
|
||||
"max_ms": 8.388,
|
||||
"histogram": [
|
||||
26423,
|
||||
293,
|
||||
16,
|
||||
9,
|
||||
4,
|
||||
5,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "village",
|
||||
"repeat": 2,
|
||||
"frames": 25996,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2166.285,
|
||||
"low_1pct_fps": 528.15,
|
||||
"low_01pct_fps": 209.522,
|
||||
"p50_ms": 0.43,
|
||||
"p95_ms": 0.662,
|
||||
"p99_ms": 1.308,
|
||||
"p999_ms": 2.477,
|
||||
"max_ms": 11.033,
|
||||
"histogram": [
|
||||
25615,
|
||||
338,
|
||||
23,
|
||||
5,
|
||||
5,
|
||||
5,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 0,
|
||||
"frames": 31855,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2654.549,
|
||||
"low_1pct_fps": 667.966,
|
||||
"low_01pct_fps": 257.945,
|
||||
"p50_ms": 0.341,
|
||||
"p95_ms": 0.519,
|
||||
"p99_ms": 0.932,
|
||||
"p999_ms": 1.761,
|
||||
"max_ms": 10.944,
|
||||
"histogram": [
|
||||
31558,
|
||||
275,
|
||||
6,
|
||||
2,
|
||||
7,
|
||||
0,
|
||||
4,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 1,
|
||||
"frames": 31763,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2646.916,
|
||||
"low_1pct_fps": 685.008,
|
||||
"low_01pct_fps": 270.233,
|
||||
"p50_ms": 0.344,
|
||||
"p95_ms": 0.52,
|
||||
"p99_ms": 0.94,
|
||||
"p999_ms": 1.685,
|
||||
"max_ms": 11.406,
|
||||
"histogram": [
|
||||
31474,
|
||||
272,
|
||||
3,
|
||||
4,
|
||||
2,
|
||||
2,
|
||||
1,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "forest",
|
||||
"repeat": 2,
|
||||
"frames": 24818,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2068.162,
|
||||
"low_1pct_fps": 521.303,
|
||||
"low_01pct_fps": 229.228,
|
||||
"p50_ms": 0.439,
|
||||
"p95_ms": 0.767,
|
||||
"p99_ms": 1.284,
|
||||
"p999_ms": 2.351,
|
||||
"max_ms": 11.468,
|
||||
"histogram": [
|
||||
24356,
|
||||
410,
|
||||
36,
|
||||
4,
|
||||
4,
|
||||
3,
|
||||
2,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 0,
|
||||
"frames": 32039,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2669.9,
|
||||
"low_1pct_fps": 741.491,
|
||||
"low_01pct_fps": 294.727,
|
||||
"p50_ms": 0.345,
|
||||
"p95_ms": 0.501,
|
||||
"p99_ms": 0.86,
|
||||
"p999_ms": 1.431,
|
||||
"max_ms": 9.257,
|
||||
"histogram": [
|
||||
31771,
|
||||
250,
|
||||
3,
|
||||
2,
|
||||
4,
|
||||
6,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 1,
|
||||
"frames": 31854,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2654.471,
|
||||
"low_1pct_fps": 747.759,
|
||||
"low_01pct_fps": 302.422,
|
||||
"p50_ms": 0.347,
|
||||
"p95_ms": 0.503,
|
||||
"p99_ms": 0.853,
|
||||
"p999_ms": 1.404,
|
||||
"max_ms": 13.925,
|
||||
"histogram": [
|
||||
31580,
|
||||
261,
|
||||
3,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
3,
|
||||
3,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "ocean",
|
||||
"repeat": 2,
|
||||
"frames": 25022,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2085.121,
|
||||
"low_1pct_fps": 576.803,
|
||||
"low_01pct_fps": 262.183,
|
||||
"p50_ms": 0.428,
|
||||
"p95_ms": 0.758,
|
||||
"p99_ms": 1.214,
|
||||
"p999_ms": 2.109,
|
||||
"max_ms": 9.206,
|
||||
"histogram": [
|
||||
24600,
|
||||
390,
|
||||
20,
|
||||
3,
|
||||
2,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 0,
|
||||
"frames": 33745,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2812.075,
|
||||
"low_1pct_fps": 736.0,
|
||||
"low_01pct_fps": 258.279,
|
||||
"p50_ms": 0.327,
|
||||
"p95_ms": 0.471,
|
||||
"p99_ms": 0.808,
|
||||
"p999_ms": 1.689,
|
||||
"max_ms": 10.07,
|
||||
"histogram": [
|
||||
33516,
|
||||
205,
|
||||
7,
|
||||
0,
|
||||
7,
|
||||
4,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 1,
|
||||
"frames": 33294,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2774.461,
|
||||
"low_1pct_fps": 763.45,
|
||||
"low_01pct_fps": 295.503,
|
||||
"p50_ms": 0.334,
|
||||
"p95_ms": 0.471,
|
||||
"p99_ms": 0.813,
|
||||
"p999_ms": 1.63,
|
||||
"max_ms": 8.512,
|
||||
"histogram": [
|
||||
33056,
|
||||
221,
|
||||
3,
|
||||
5,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
2,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
},
|
||||
{
|
||||
"phase": "mountain",
|
||||
"repeat": 2,
|
||||
"frames": 26747,
|
||||
"seconds": 12.0,
|
||||
"avg_fps": 2228.824,
|
||||
"low_1pct_fps": 599.44,
|
||||
"low_01pct_fps": 239.602,
|
||||
"p50_ms": 0.403,
|
||||
"p95_ms": 0.678,
|
||||
"p99_ms": 1.107,
|
||||
"p999_ms": 2.054,
|
||||
"max_ms": 9.178,
|
||||
"histogram": [
|
||||
26418,
|
||||
298,
|
||||
13,
|
||||
6,
|
||||
2,
|
||||
8,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
],
|
||||
"label": "vanilla-win-9800x3d-5080"
|
||||
}
|
||||
@@ -1,106 +0,0 @@
|
||||
# Horizon v0.2.97 vs vanilla 26.3 on Windows 11: Ryzen 7 9800X3D + RTX 5080 (2026-10-29, RD 8 and 32 rerun 2026-10-30)
|
||||
|
||||
The first `tools/perf_bench.py` run on Windows ([docs/benchmark.md](../../docs/benchmark.md)): Horizon, vanilla 26.3 and
|
||||
vanilla with performance mods, render distances 8, 16 and 32, 1280x720, three games each, every game from a fresh
|
||||
world. The reports are the `*-win-9800x3d-5080-rd*.json` files next to this page.
|
||||
|
||||
```sh
|
||||
python tools/perf_bench.py --table horizon-win-9800x3d-5080 vanilla-win-9800x3d-5080 vanilla-mods-win-9800x3d-5080
|
||||
```
|
||||
|
||||
## Setup
|
||||
|
||||
- **Machine:** AMD Ryzen 7 9800X3D (8 cores, 16 threads), 94 GB RAM (DDR5, EXPO off), NVIDIA GeForce RTX 5080
|
||||
(driver 617.42), Windows 11 Pro 26200, Balanced power plan, desktop. One 1920x1080 120 Hz display. The game windows
|
||||
were on the desktop of an unlocked session.
|
||||
- **Horizon:** release v0.2.97 as the launcher installs it (`--build %APPDATA%\horizon-launcher\versions\v0.2.97`,
|
||||
`--resources` its `.local\horizon-client\26.3`), Vulkan.
|
||||
- **Vanilla:** the 26.3 client jar with Fabric Loader 0.19.5 and the driver mod, Java 25.0.5 (Temurin), `-Xmx2G`
|
||||
with the launcher's G1 flags and the manifest's `-XX:StackShadowPages=32`, OpenGL 3.3.
|
||||
- **Vanilla + mods:** the same with Sodium mc26.3-0.9.2, Lithium mc26.3-0.26.2, FerriteCore 9.0.0 and
|
||||
ImmediatelyFast 1.17.1 (`tools/benchmark-deps/mods.lock.json`).
|
||||
- **Commands:** `python tools/perf_bench.py --game <game> --label <game>-win-9800x3d-5080 --distances <d>
|
||||
--sizes 1280x720 --repeats 3` (plus `--build` and `--resources` for Horizon), with the games taking turns at
|
||||
each distance.
|
||||
- **Memory** is the working set on Windows (what Task Manager shows), sampled from outside the process. Horizon's
|
||||
GPU figure is its own Vulkan allocator total. `nvidia-smi` gives no per-process figure under WDDM, so vanilla has
|
||||
none.
|
||||
|
||||
## Load
|
||||
|
||||
Windows has no load average, so the reports have no `load_avg_1m`. Every game ran on an otherwise idle machine:
|
||||
|
||||
- **RD 8 and RD 32** (rerun on 2026-10-30, after the first pass had builds running alongside): a script started each
|
||||
game only once no `rustc`, `cargo`, `link` (or other compiler) process and no other game (`horizon-client`, `java`,
|
||||
`javaw`, Minecraft) was running, and the machine's CPU load had stayed under 15 % in every 5-second sample for
|
||||
30 seconds. During each game it sampled every 2 seconds the machine's CPU load and the CPU of everything outside the
|
||||
benchmark's own processes. A game during which a compiler or another game ran, or other processes used over 15 % of
|
||||
the machine for 10 seconds, was discarded and run again: two of the 20 games were (vanilla + mods at RD 32, a
|
||||
build started during one, background processes during the other).
|
||||
- **RD 16** (2026-10-29): no `rustc`, `cargo` or `link` process at any point, the load logged every 5 seconds.
|
||||
|
||||
| Game | RD | Mean / max CPU load (machine, the game included) | Other processes' CPU, mean / max | Compiler processes |
|
||||
|---|---|---|---|---|
|
||||
| Horizon | 8 | 18 % / 49 % | 6 % / 12 % | 0 |
|
||||
| Vanilla | 8 | 28 % / 75 % | 7 % / 20 % | 0 |
|
||||
| Vanilla + mods | 8 | 30 % / 81 % | 7 % / 20 % | 0 |
|
||||
| Horizon | 16 | 29 % / 80 % | – | 0 |
|
||||
| Vanilla | 16 | 41 % / 91 % | – | 0 |
|
||||
| Vanilla + mods | 16 | 51 % / 90 % | – | 0 |
|
||||
| Horizon | 32 | 36 % / 100 % | 5 % / 15 % | 0 |
|
||||
| Vanilla | 32 | 39 % / 73 % | 6 % / 18 % | 0 |
|
||||
| Vanilla + mods | 32 | 42 % / 88 % | 6 % / 21 % | 0 |
|
||||
|
||||
"Other processes" is the machine's load minus the benchmark's own processes (the game and `perf_bench.py`), in
|
||||
2-second samples. Most of it is the system's share of the game's own drawing (the graphics driver and the
|
||||
compositor), which no process of the benchmark is charged for; the desktop apps left open (a browser, chat apps)
|
||||
briefly reached 5 % at most. RD 16's load was logged from outside every 5 seconds, so it has no such split, and its mean includes the time between
|
||||
games. Compared with the first pass, the idle RD 8 runs give Horizon about 10 % higher averages and about 50 % higher
|
||||
1% lows, and vanilla up to 10 % higher averages.
|
||||
|
||||
## Results
|
||||
|
||||
Mean of 3 games ± 95% confidence interval. FPS over the 12-second flight at 16 blocks/s (average / 1% low /
|
||||
0.1% low):
|
||||
|
||||
| RD | scene | Horizon v0.2.97 | Vanilla 26.3 | Vanilla + mods |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 8 | forest | 3495 ±276 / 1295 ±397 / 859 ±298 | 2457 ±836 / 625 ±224 / 252 ±52 | 2425 ±65 / 733 ±30 / 250 ±22 |
|
||||
| 8 | mountain | 3376 ±67 / 1384 ±168 / 850 ±256 | 2605 ±811 / 700 ±218 / 264 ±71 | 2538 ±167 / 760 ±34 / 241 ±44 |
|
||||
| 8 | ocean | 3346 ±147 / 1358 ±237 / 912 ±235 | 2470 ±828 / 689 ±241 / 286 ±53 | 2432 ±82 / 764 ±37 / 262 ±37 |
|
||||
| 8 | village | 2942 ±197 / 1271 ±146 / 839 ±94 | 2217 ±112 / 545 ±37 / 215 ±14 | 2104 ±101 / 577 ±84 / 196 ±47 |
|
||||
| 16 | forest | 2424 ±138 / 709 ±165 / 401 ±100 | 1912 ±324 / 402 ±89 / 149 ±25 | 1746 ±32 / 461 ±27 / 179 ±9 |
|
||||
| 16 | mountain | 1961 ±99 / 537 ±96 / 297 ±75 | 1653 ±153 / 332 ±27 / 113 ±8 | 1500 ±55 / 408 ±40 / 140 ±10 |
|
||||
| 16 | ocean | 2201 ±183 / 554 ±251 / 325 ±326 | 1861 ±289 / 446 ±142 / 165 ±29 | 1815 ±119 / 514 ±142 / 192 ±58 |
|
||||
| 16 | village | 1712 ±192 / 593 ±80 / 358 ±69 | 1218 ±65 / 318 ±16 / 127 ±5 | 1282 ±162 / 343 ±25 / 132 ±12 |
|
||||
| 32 | forest | 1389 ±70 / 504 ±33 / 330 ±118 | 1203 ±51 / 228 ±13 / 108 ±12 | 929 ±8 / 313 ±41 / 129 ±32 |
|
||||
| 32 | mountain | 1086 ±34 / 258 ±78 / 108 ±37 | 815 ±61 / 55 ±13 / 8 ±3 | 645 ±10 / 166 ±12 / 86 ±21 |
|
||||
| 32 | ocean | 1189 ±27 / 155 ±9 / 68 ±8 | 1223 ±33 / 236 ±17 / 99 ±21 | 1017 ±14 / 325 ±38 / 117 ±28 |
|
||||
| 32 | village | 1164 ±9 / 416 ±39 / 216 ±86 | 882 ±48 / 184 ±12 / 83 ±17 | 926 ±17 / 250 ±5 / 93 ±11 |
|
||||
|
||||
Startup, loading and memory (means of 3 games):
|
||||
|
||||
| RD | | Horizon v0.2.97 | Vanilla 26.3 | Vanilla + mods |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 8 | start to title / in-world | 3.0 s / 6.1 s | 7.7 s / 13.9 s | 11.1 s / 17.6 s |
|
||||
| 8 | mean scene load | 1.3 s | 4.0 s | 3.6 s |
|
||||
| 8 | working set, steady / peak | 1082 / 1172 MB | 1913 / 2120 MB | 1904 / 2053 MB |
|
||||
| 16 | start to title / in-world | 3.2 s / 7.2 s | 7.7 s / 19.9 s | 10.8 s / 23.5 s |
|
||||
| 16 | mean scene load | 2.4 s | 9.2 s | 9.0 s |
|
||||
| 16 | working set, steady / peak | 1236 / 1459 MB | 2300 / 2540 MB | 2327 / 2496 MB |
|
||||
| 32 | start to title / in-world | 2.9 s / 10.5 s | 7.5 s / 35.4 s | 11.0 s / 39.2 s |
|
||||
| 32 | mean scene load | 5.7 s | 21.1 s | 19.9 s |
|
||||
| 32 | working set, steady / peak | 1730 / 2045 MB | 2799 / 2892 MB | 2895 / 2965 MB |
|
||||
|
||||
## What it shows
|
||||
|
||||
- At RD 8 and 16, Horizon's average FPS is 18–42 % above vanilla's in every scene. Its 1% lows are 1.2–2.3 times
|
||||
vanilla's and its 0.1% lows 2.0–3.9 times. On this CPU and GPU the performance mods leave vanilla's averages
|
||||
level or slightly lower, and raise its 1% lows by 6–23 %.
|
||||
- At RD 32, Horizon's average is 15–33 % above vanilla's over the forest, the mountain and the village, with 1% lows
|
||||
2.2–4.7 times vanilla's. Over the ocean its average is level with vanilla's, but its lows are lower than vanilla's
|
||||
and the modded client's (155 vs 236 and 325 FPS 1% low, 68 vs 99 and 117 FPS 0.1% low), on an idle machine too.
|
||||
That scene is worth a closer look.
|
||||
- Horizon reaches the title screen 2.4–2.6 times faster than vanilla (3.4–3.8 times faster than the modded client)
|
||||
and loads a scene's chunks 3–4 times faster. Its steady working set is 38–46 % smaller.
|
||||
- Each game uses its own graphics API: Horizon Vulkan, vanilla OpenGL. That difference is part of what's compared.
|
||||