mirror of
https://github.com/horizon-rust/horizon.git
synced 2026-11-11 23:55:37 -10:00
World open: read the server's sync data beside the worldgen preload
The world data preload read the registries, tags, recipes and advancements the server sends (lan::sync_data) after the worldgen bundle and the loot tables. A launch into a world reached the server thread's own preload before that, so the server started a second read of the same data and then waited on SYNC's lock while the preload read it again: ~100 ms on the server thread before settle_spawn (server.sync_adopt). The preload now reads it on a thread of its own from the start. Co-Authored-By: Claude Opus 5.5 (1M context) <[email protected]>
This commit is contained in:
1 parent
435730a405
commit
189e128d00
1 file changed
+37
-3
@@ -379,6 +379,7 @@ pub(super) fn preload_world_data(
|
||||
.name("World data preload".into())
|
||||
.spawn(move || {
|
||||
horizon_threads::behind_server();
|
||||
let sync = spawn_sync_preload(&resources, true);
|
||||
// Errors are left for the world opening to report.
|
||||
if let Ok(data) = horizon_client::vanillagen::shared_data(
|
||||
&resources.join("worldgen"),
|
||||
@@ -394,8 +395,7 @@ pub(super) fn preload_world_data(
|
||||
&resources,
|
||||
&horizon_world::loot::PackOverlay::NONE,
|
||||
);
|
||||
let _ =
|
||||
super::lan::sync_data(&resources, &horizon_world::loot::PackOverlay::NONE);
|
||||
join_sync_preload(sync, &resources);
|
||||
});
|
||||
match spawned {
|
||||
Ok(thread) => *preload = Preload::Started { thread, left: None },
|
||||
@@ -444,6 +444,7 @@ pub(super) fn preload_launch_world(
|
||||
.spawn(move || {
|
||||
// Not behind the server: the world's opening waits for it.
|
||||
let started = std::time::Instant::now();
|
||||
let sync = spawn_sync_preload(&resources, false);
|
||||
// Errors are left for the world opening to report. The world's
|
||||
// flags from its level.dat: the feature packs a flag forces on.
|
||||
let enabled_features = horizon_client::save::Level::read(&world_root)
|
||||
@@ -463,7 +464,7 @@ pub(super) fn preload_launch_world(
|
||||
&resources,
|
||||
&horizon_world::loot::PackOverlay::NONE,
|
||||
);
|
||||
let _ = super::lan::sync_data(&resources, &horizon_world::loot::PackOverlay::NONE);
|
||||
join_sync_preload(sync, &resources);
|
||||
log::info!(
|
||||
"Horizon: world data preloaded for the launch's world in {} ms",
|
||||
started.elapsed().as_millis()
|
||||
@@ -475,6 +476,39 @@ pub(super) fn preload_launch_world(
|
||||
}
|
||||
}
|
||||
|
||||
/// The registries, tags, recipes and advancements the server sends
|
||||
/// (`lan::sync_data`), read on a thread of their own beside the worldgen and
|
||||
/// loot reads: they share nothing, and read after them they came too late
|
||||
/// for the server thread, which then read them a second time.
|
||||
fn spawn_sync_preload(
|
||||
resources: &std::path::Path,
|
||||
behind_server: bool,
|
||||
) -> Option<std::thread::JoinHandle<()>> {
|
||||
let resources = resources.to_owned();
|
||||
std::thread::Builder::new()
|
||||
.name("Sync data preload".into())
|
||||
.spawn(move || {
|
||||
if behind_server {
|
||||
horizon_threads::behind_server();
|
||||
}
|
||||
let _ = super::lan::sync_data(&resources, &horizon_world::loot::PackOverlay::NONE);
|
||||
})
|
||||
.ok()
|
||||
}
|
||||
|
||||
/// Waits for [`spawn_sync_preload`]'s thread, so the preload is over when
|
||||
/// its own thread is; reads the data here if that thread did not start.
|
||||
fn join_sync_preload(sync: Option<std::thread::JoinHandle<()>>, resources: &std::path::Path) {
|
||||
match sync {
|
||||
Some(thread) => {
|
||||
let _ = thread.join();
|
||||
}
|
||||
None => {
|
||||
let _ = super::lan::sync_data(resources, &horizon_world::loot::PackOverlay::NONE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A world opens: what `preload_world_data` read is the world's from now on.
|
||||
pub(super) fn world_data_used() {
|
||||
*PRELOAD.lock().unwrap_or_else(|e| e.into_inner()) = Preload::Used;
|
||||
|
||||
Reference in new issue
Block a user