perf: intern gameplay projection strings and verify resource overrides

This commit is contained in:
rdbtCVS committed 2026-10-17 01:42:34 +01:00
1 parent cf837118e9
commit cd61e11b56
5 files changed
+265 -15

No files matched your search

@@ -0,0 +1,188 @@
{
"scope": "Assets + block facts + behaviours loader only; excludes full startup",
"resources": ".local/horizon-client/26.3",
"repeats": 5,
"comparison": "historical cf837118 release binary",
"reference_binary": "target/release/examples/shared_json_startup_profile-cf837118",
"metrics": {
"baseline": {
"phase_ms": {
"median": 1462.003,
"samples": [
1639.999,
1506.864,
1429.844,
1462.003,
1346.061
]
},
"total_ms": {
"median": 1922.795,
"samples": [
3383.516,
1990.554,
1912.354,
1922.795,
1777.912
]
},
"cpu_ms": {
"median": 1961.459,
"samples": [
2419.086,
2021.457,
1951.587,
1961.459,
1839.984
]
},
"peak_rss_kib": {
"median": 820912,
"samples": [
819956,
821052,
820912,
821792,
820424
]
}
},
"pr607": {
"phase_ms": {
"median": 486.715,
"samples": [
460.738,
442.013,
623.053,
486.715,
550.652
]
},
"total_ms": {
"median": 948.089,
"samples": [
923.057,
935.599,
1109.64,
948.089,
1052.546
]
},
"cpu_ms": {
"median": 968.424,
"samples": [
928.489,
946.932,
1128.431,
968.424,
1079.642
]
},
"peak_rss_kib": {
"median": 351796,
"samples": [
351796,
351844,
351536,
351532,
351988
]
}
},
"cf837118": {
"phase_ms": {
"median": 474.268,
"samples": [
443.122,
474.268,
520.497,
433.525,
532.058
]
},
"total_ms": {
"median": 945.87,
"samples": [
934.722,
945.87,
1006.539,
888.201,
1032.6
]
},
"cpu_ms": {
"median": 953.668,
"samples": [
941.957,
953.668,
1029.122,
903.574,
1065.025
]
},
"peak_rss_kib": {
"median": 274476,
"samples": [
273448,
274844,
274476,
274556,
274252
]
}
},
"current": {
"phase_ms": {
"median": 445.924,
"samples": [
472.165,
427.797,
419.288,
445.924,
524.211
]
},
"total_ms": {
"median": 999.669,
"samples": [
999.669,
892.616,
1051.427,
940.595,
1112.158
]
},
"cpu_ms": {
"median": 1001.24,
"samples": [
1001.24,
887.874,
1051.732,
951.495,
1132.208
]
},
"peak_rss_kib": {
"median": 267604,
"samples": [
267716,
267920,
267448,
267604,
267344
]
}
}
},
"builds": {
"current": "release example built at cf837118 + current uncommitted delta in PR #607 worktree",
"historical": "release example built at exact cf837118 commit, with same Cargo release profile and shared dependency target"
},
"mode_commits": {
"baseline": "independent loader algorithm at e422bd13, executed in current binary",
"pr607": "shared early construction algorithm at a01d47f2, executed in current binary",
"cf837118": "exact historical binary at cf837118, deferred mode",
"current": "current PR worktree, deferred mode with interned strings"
},
"limitations": "Loader-only (Assets + BlockFacts + Behaviours), no full client startup or first-frame timing. Same release profile but different compilation contexts for historical binary; hardware activity and cache warmth vary. CPU and elapsed differences between cf837118 and current are mixed and may be noise. Peak RSS is whole-process Linux ru_maxrss."
}
@@ -9,9 +9,11 @@ use std::{path::Path, time::Instant};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut args = std::env::args().skip(1);
let root = args.next().ok_or("expected resource directory")?;
let mode = args.next().ok_or("expected baseline, pr607 or shared")?;
let mode = args
.next()
.ok_or("expected baseline, pr607, shared or deferred")?;
if !["baseline", "pr607", "shared", "deferred"].contains(&mode.as_str()) {
return Err("expected baseline, pr607 or shared".into());
return Err("expected baseline, pr607, shared or deferred".into());
}
let root = Path::new(&root);
let total = Instant::now();
+22 -10
View File
@@ -117,16 +117,24 @@ pub struct GameplayProjection {
emission: u64,
dampening: u64,
hardness: f64,
push: Box<str>,
push: Arc<str>,
volume: f64,
pitch: f64,
place: Box<str>,
break_sound: Box<str>,
fall: Box<str>,
place: Arc<str>,
break_sound: Arc<str>,
fall: Arc<str>,
}
impl GameplayProjection {
fn from_entry(entry: &decode::Entry<'_>) -> Self {
fn from_entry(entry: &decode::Entry<'_>, strings: &mut HashMap<String, Arc<str>>) -> Self {
fn intern(strings: &mut HashMap<String, Arc<str>>, value: &str) -> Arc<str> {
if let Some(existing) = strings.get(value) {
return Arc::clone(existing);
}
let value_arc: Arc<str> = Arc::from(value);
strings.insert(value.to_owned(), Arc::clone(&value_arc));
value_arc
}
const FLAGS: [&str; 11] = [
"replaceable",
"random_ticks",
@@ -147,12 +155,12 @@ impl GameplayProjection {
emission: entry.unsigned("emission"),
dampening: entry.unsigned("dampening"),
hardness: entry.number("hardness"),
push: entry.text("push").into(),
push: intern(strings, entry.text("push")),
volume: entry.sound_number("volume"),
pitch: entry.sound_number("pitch"),
place: entry.sound_id("place").into(),
break_sound: entry.sound_id("break").into(),
fall: entry.sound_id("fall").into(),
place: intern(strings, entry.sound_id("place")),
break_sound: intern(strings, entry.sound_id("break")),
fall: intern(strings, entry.sound_id("fall")),
}
}
}
@@ -239,7 +247,11 @@ impl BlockFacts {
behaviours: &Value,
) -> Result<(Self, Vec<GameplayProjection>)> {
Self::load_with_callback(root, registry, behaviours, |entries| {
Ok(entries.iter().map(GameplayProjection::from_entry).collect())
let mut strings = HashMap::new();
Ok(entries
.iter()
.map(|entry| GameplayProjection::from_entry(entry, &mut strings))
.collect())
})
}
@@ -349,6 +349,35 @@ fn independent_reloads_read_changed_behaviour_json_and_report_invalid_files() {
);
assert!(horizon_world::level::Behaviours::load(registry, &scratch).is_ok());
// Override one exported state bit at the same path and verify that a later
// independent and paired read sees it while the original resource root does not.
let mut changed: serde_json::Value = serde_json::from_slice(&original).unwrap();
let original_bits = changed["states"][0][1].as_u64().unwrap();
changed["states"][0][1] = (original_bits ^ 1).into();
fs::write(
scratch.join("block-behaviours.json"),
serde_json::to_vec(&changed).unwrap(),
)
.unwrap();
let changed_pair = BlockFacts::load_pair(&scratch, registry).unwrap();
let changed_independent = BlockFacts::load(&scratch, registry).unwrap();
let base_facts = BlockFacts::load(&base, registry).unwrap();
let state = horizon_world::registry::BlockStateId(0);
assert_ne!(
changed_pair.0.get(state).legacy_solid,
base_facts.get(state).legacy_solid
);
assert_eq!(
changed_pair.0.get(state).legacy_solid,
changed_independent.get(state).legacy_solid
);
// The world loader sees the same overridden legacy solidity flag.
let changed_world = horizon_world::level::Behaviours::load(registry, &scratch).unwrap();
assert_eq!(
changed_world.facts(state).flags & 1 != 0,
changed_pair.0.get(state).legacy_solid
);
fs::write(scratch.join("block-behaviours.json"), b"{").unwrap();
assert!(BlockFacts::load_pair(&scratch, registry).is_err());
assert!(BlockFacts::load(&scratch, registry).is_err());
+22 -3
View File
@@ -40,6 +40,8 @@ def main():
parser.add_argument("--binary", type=Path, default=Path("target/release/examples/shared_json_startup_profile"))
parser.add_argument("--resources", type=Path, default=Path(".local/horizon-client/26.3"))
parser.add_argument("--repeats", type=int, default=5)
parser.add_argument("--reference-binary", type=Path,
help="Release binary built from cf837118; compare its deferred mode against current")
parser.add_argument("--output", type=Path)
args = parser.parse_args()
if args.repeats < 1:
@@ -47,14 +49,31 @@ def main():
binary, resources = args.binary.resolve(), args.resources.resolve()
if not binary.is_file() or not resources.is_dir():
parser.error("binary or resources missing; build the example and prepare resources first")
samples = {"baseline": [], "pr607": [], "shared": [], "deferred": []}
if args.reference_binary:
reference = args.reference_binary.resolve()
if not reference.is_file():
parser.error("reference binary missing")
modes = ["baseline", "pr607", "cf837118", "current"]
commands = {
"baseline": (binary, "baseline"),
"pr607": (binary, "pr607"),
"cf837118": (reference, "deferred"),
"current": (binary, "deferred"),
}
else:
modes = ["baseline", "pr607", "shared", "deferred"]
commands = {mode: (binary, mode) for mode in modes}
samples = {mode: [] for mode in modes}
for i in range(args.repeats):
for mode in (("baseline", "pr607", "shared", "deferred") if i % 2 == 0 else ("deferred", "shared", "pr607", "baseline")):
samples[mode].append(run(binary, resources, mode))
for mode in (modes if i % 2 == 0 else list(reversed(modes))):
executable, binary_mode = commands[mode]
samples[mode].append(run(executable, resources, binary_mode))
result = {
"scope": "Assets + block facts + behaviours loader only; excludes full startup",
"resources": str(resources),
"repeats": args.repeats,
"comparison": "historical cf837118 release binary" if args.reference_binary else "same binary loading modes",
"reference_binary": str(args.reference_binary) if args.reference_binary else None,
"metrics": {mode: {key: {"median": round(statistics.median(row[key] for row in rows), 3),
"samples": [round(row[key], 3) for row in rows]}
for key in rows[0]} for mode, rows in samples.items()},