feat: lower the default memory on lower memory machines (#783)
This commit is contained in:
parent
86145c7180
commit
72a9b63f24
10 changed files with 84 additions and 27 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -4557,6 +4557,7 @@ dependencies = [
|
|||
"interfrost",
|
||||
"serde",
|
||||
"strum",
|
||||
"sysinfo",
|
||||
"thiserror 2.0.18",
|
||||
"url",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ pub fn memory_field(mut memory: State<String>) -> impl IntoElement {
|
|||
.child(
|
||||
TextInput::new(memory)
|
||||
.width(Size::px(90.))
|
||||
.placeholder("4096")
|
||||
.placeholder(oneclient_common::default_mem_max().to_string())
|
||||
.on_validate(validate_memory)
|
||||
.trailing(
|
||||
label()
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ use chrono::{Datelike, NaiveDate};
|
|||
use oneclient_core::clusters::Cluster;
|
||||
use oneclient_common::domain::GameLoader;
|
||||
use oneclient_common::{ParsedMcVersion, VersionKey, format_mc_version, parse_mc_version};
|
||||
use sysinfo::{MemoryRefreshKind, RefreshKind, System};
|
||||
|
||||
use oneclient_common::MEMORY_HEADROOM_GB;
|
||||
pub use oneclient_common::total_ram_mb;
|
||||
|
||||
pub type ClusterGroups = BTreeMap<ReleaseLine, Vec<Cluster>>;
|
||||
|
||||
|
|
@ -207,19 +209,7 @@ pub fn format_res((w, h): (u32, u32)) -> String {
|
|||
|
||||
/// Prevents user from choosing his max amount of ram preset (e.g Someone has 16GB of RAM,
|
||||
/// so the max preset is 16GB - 2GB = 14GB)
|
||||
const MEMORY_HEADROOM_GB: u32 = 2;
|
||||
const MEMORY_PRESETS_GB: [u32; 10] = [2, 4, 6, 8, 12, 16, 24, 32, 48, 64];
|
||||
|
||||
pub fn total_ram_mb() -> u32 {
|
||||
static TOTAL_RAM_MB: std::sync::OnceLock<u32> = std::sync::OnceLock::new();
|
||||
|
||||
*TOTAL_RAM_MB.get_or_init(|| {
|
||||
let system = System::new_with_specifics(
|
||||
RefreshKind::nothing().with_memory(MemoryRefreshKind::nothing().with_ram()),
|
||||
);
|
||||
(system.total_memory() / 1024 / 1024).min(u32::MAX as u64) as u32
|
||||
})
|
||||
}
|
||||
const MEMORY_PRESETS_GB: [u32; 11] = [2, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64];
|
||||
|
||||
pub fn memory_presets_mb() -> Vec<u32> {
|
||||
presets_for_total_gb((total_ram_mb() as f32 / 1024.).round() as u32)
|
||||
|
|
@ -451,17 +441,17 @@ mod tests {
|
|||
fn presets_stop_two_gigabytes_short_of_the_machine() {
|
||||
assert_eq!(
|
||||
presets_for_total_gb(16),
|
||||
vec![2048, 4096, 6144, 8192, 12288, 14336]
|
||||
vec![2048, 3072, 4096, 6144, 8192, 12288, 14336]
|
||||
);
|
||||
assert_eq!(
|
||||
presets_for_total_gb(32),
|
||||
vec![2048, 4096, 6144, 8192, 12288, 16384, 24576, 30720]
|
||||
vec![2048, 3072, 4096, 6144, 8192, 12288, 16384, 24576, 30720]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_ceiling_landing_on_a_round_step_is_not_repeated() {
|
||||
assert_eq!(presets_for_total_gb(8), vec![2048, 4096, 6144]);
|
||||
assert_eq!(presets_for_total_gb(8), vec![2048, 3072, 4096, 6144]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -112,7 +112,9 @@ impl Component for ClusterSettings {
|
|||
MemoryRow {
|
||||
cluster_id,
|
||||
value: profile.mem_max,
|
||||
global: global.mem_max.unwrap_or(4096),
|
||||
global: global
|
||||
.mem_max
|
||||
.unwrap_or_else(oneclient_common::default_mem_max),
|
||||
}
|
||||
.into_element(),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ impl GameSettingsProfile {
|
|||
java_path: None,
|
||||
resolution: None,
|
||||
force_fullscreen: Some(false),
|
||||
mem_max: Some(4096),
|
||||
mem_max: Some(oneclient_common::default_mem_max()),
|
||||
launch_args: None,
|
||||
launch_env: None,
|
||||
hook_pre: None,
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ interfrost.workspace = true
|
|||
directories.workspace = true
|
||||
serde.workspace = true
|
||||
strum.workspace = true
|
||||
sysinfo.workspace = true
|
||||
thiserror.workspace = true
|
||||
|
||||
url.workspace = true
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
pub mod consent;
|
||||
pub mod constants;
|
||||
pub mod domain;
|
||||
pub mod memory;
|
||||
pub mod os_ext;
|
||||
pub mod paths;
|
||||
pub mod patch;
|
||||
|
|
@ -17,6 +18,7 @@ pub use domain::{
|
|||
ContentType, GameLoader, HashAlgorithm, PackageUpdateMode, ProviderId, Resolution,
|
||||
};
|
||||
pub use error::{PathsError, PathsResult};
|
||||
pub use memory::{MEMORY_HEADROOM_GB, default_mem_max, default_mem_max_for_total, total_ram_mb};
|
||||
pub use os_ext::OsExt;
|
||||
pub use patch::Patch;
|
||||
pub use search::{MatchScore, SearchQuery, normalize_query};
|
||||
|
|
|
|||
55
packages/oneclient_common/src/memory.rs
Normal file
55
packages/oneclient_common/src/memory.rs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
use sysinfo::{MemoryRefreshKind, RefreshKind, System};
|
||||
|
||||
pub const MEMORY_HEADROOM_GB: u32 = 2;
|
||||
|
||||
const EIGHT_GB_MB: u32 = 7 * 1024;
|
||||
const TWELVE_GB_MB: u32 = 11 * 1024;
|
||||
|
||||
pub fn total_ram_mb() -> u32 {
|
||||
static TOTAL_RAM_MB: std::sync::OnceLock<u32> = std::sync::OnceLock::new();
|
||||
|
||||
*TOTAL_RAM_MB.get_or_init(|| {
|
||||
let system = System::new_with_specifics(
|
||||
RefreshKind::nothing().with_memory(MemoryRefreshKind::nothing().with_ram()),
|
||||
);
|
||||
(system.total_memory() / 1024 / 1024).min(u32::MAX as u64) as u32
|
||||
})
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn default_mem_max() -> u32 {
|
||||
default_mem_max_for_total(total_ram_mb())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn default_mem_max_for_total(total_mb: u32) -> u32 {
|
||||
match total_mb {
|
||||
0..EIGHT_GB_MB => 2048,
|
||||
EIGHT_GB_MB..TWELVE_GB_MB => 3072,
|
||||
_ => 4096,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::default_mem_max_for_total;
|
||||
|
||||
#[test]
|
||||
fn the_default_heap_ramps_with_total_ram() {
|
||||
assert_eq!(default_mem_max_for_total(3987), 2048); // 4GB
|
||||
assert_eq!(default_mem_max_for_total(6060), 2048); // 6GB
|
||||
assert_eq!(default_mem_max_for_total(7167), 2048);
|
||||
assert_eq!(default_mem_max_for_total(7168), 3072);
|
||||
assert_eq!(default_mem_max_for_total(7900), 3072); // 8GB
|
||||
assert_eq!(default_mem_max_for_total(11263), 3072);
|
||||
assert_eq!(default_mem_max_for_total(11264), 4096);
|
||||
assert_eq!(default_mem_max_for_total(11800), 4096); // 12GB
|
||||
assert_eq!(default_mem_max_for_total(16290), 4096); // 16GB
|
||||
assert_eq!(default_mem_max_for_total(65229), 4096); // 64GB
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_machine_that_reports_nothing_still_gets_a_heap() {
|
||||
assert_eq!(default_mem_max_for_total(0), 2048);
|
||||
}
|
||||
}
|
||||
|
|
@ -259,7 +259,7 @@ pub async fn launch_cluster(
|
|||
&libraries,
|
||||
&classpaths,
|
||||
&version_name,
|
||||
profile.mem_max.unwrap_or(2048),
|
||||
profile.mem_max.unwrap_or_else(oneclient_common::default_mem_max),
|
||||
profile.launch_args.clone().unwrap_or_default(),
|
||||
&java.os_arch,
|
||||
java.major,
|
||||
|
|
@ -349,8 +349,13 @@ pub async fn launch_cluster(
|
|||
mc_version: cluster.mc_version.clone(),
|
||||
});
|
||||
|
||||
let recorder =
|
||||
SessionRecorder::start(state, cluster_id, profile.mem_max.unwrap_or(2048), &java).await;
|
||||
let recorder = SessionRecorder::start(
|
||||
state,
|
||||
cluster_id,
|
||||
profile.mem_max.unwrap_or_else(oneclient_common::default_mem_max),
|
||||
&java,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Pinned to the session row so that if the launcher exits first the next
|
||||
// start can tell whether the game is still playing
|
||||
|
|
|
|||
|
|
@ -13,11 +13,12 @@ async fn cluster_lifecycle_with_settings_profile() {
|
|||
|
||||
let global = state.settings.read().global_game_settings.clone();
|
||||
|
||||
// Deliberately not the global default of 4096 so the assertions distinguish
|
||||
// "the cluster's own profile was used" from "fell back to global and matched"
|
||||
// Deliberately not a value `default_mem_max()` can return so the assertions
|
||||
// distinguish "the cluster's own profile was used" from "fell back to global
|
||||
// and matched"
|
||||
let cluster = state.clusters.create(
|
||||
&global,
|
||||
CreateClusterOptions::new("Test Cluster", "1.21.1", GameLoader::Fabric).mem_max(2048),
|
||||
CreateClusterOptions::new("Test Cluster", "1.21.1", GameLoader::Fabric).mem_max(5120),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
|
@ -31,7 +32,7 @@ async fn cluster_lifecycle_with_settings_profile() {
|
|||
let resolved = state.clusters.resolve_settings(&global, &cluster)
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(resolved.mem_max, Some(2048));
|
||||
assert_eq!(resolved.mem_max, Some(5120));
|
||||
|
||||
state.clusters.update_profile(cluster.id,
|
||||
ProfileUpdate {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue