Skip to content

Commit

Permalink
Provide a new garbage-collection mechanism
Browse files Browse the repository at this point in the history
We introduce the configuration `min_avaialable_memory` which causes
disconnected clients to be cleaned up when the available system memory
drops below this amount.

While this is compatible with the `instance_timeout` setting, it
provides an alternative; letting `rust-analyzer` processes live forever
unless memory gets low.
  • Loading branch information
paholg committed Sep 21, 2023
1 parent 58f4ea3 commit 0a91981
Show file tree
Hide file tree
Showing 5 changed files with 214 additions and 14 deletions.
116 changes: 116 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ edition = "2021"

[dependencies]
anyhow = "1.0.53"
byte-unit = { version = "4", default-features = false, features = ["serde", "std"] }
clap = { version = "4.3.0", features = ["derive", "env"] }
directories = "4.0.1"
env_logger = "0.10.0"
log = "0.4.14"
serde = { version = "1.0.186" }
serde_derive = { version = "1.0.186" }
serde_json = "1.0.78"
sysinfo = "0.29"
tokio = { version = "1.15.0", features = ["fs", "io-std", "io-util", "macros", "net", "parking_lot", "process", "rt-multi-thread", "sync", "time"] }
toml = "0.5.8"
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,18 @@ Example configuration file:
# you can set this option to `false` for infinite timeout
instance_timeout = 300 # after 5 minutes

# when available system memory drops below this amount, the oldest rust-analyzer
# server instance wih no clients will get killed immediately to save memory.
#
# if all server instances have connected clients, then nothing will happen.
#
# you can set this option to `false` to disable it, or set it to some value in
# bytes to enable it, such as "4 GB".
min_available_memory = false

# time in seconds how long to wait between the gc task checks for disconnected
# clients and possibly starts a timeout task. the value must be at least 1.
# clients and available system memory, and possibly starts a timeout task. the
# value must be at least 1.
gc_interval = 10 # every 10 seconds

# ip address and port on which ra-multiplex-server listens
Expand Down
45 changes: 35 additions & 10 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ mod default {
Some(5 * 60)
}

pub fn min_available_memory() -> Option<byte_unit::Byte> {
None
}

pub fn gc_interval() -> u32 {
// 10 seconds
10
Expand All @@ -41,28 +45,44 @@ mod default {
mod de {
use super::*;

#[derive(Deserialize)]
#[serde(untagged)]
enum OneOf<T> {
Bool(bool),
Value(T),
}

/// parse either bool(false) or u32
pub fn instance_timeout<'de, D>(deserializer: D) -> Result<Option<u32>, D::Error>
where
D: Deserializer<'de>,
{
#[derive(Deserialize)]
#[serde(untagged)]
enum OneOf {
Bool(bool),
U32(u32),
}

match OneOf::deserialize(deserializer) {
Ok(OneOf::U32(value)) => Ok(Some(value)),
Ok(OneOf::Value(value)) => Ok(Some(value)),
Ok(OneOf::Bool(false)) => Ok(None),
Ok(OneOf::Bool(true)) => Err(Error::invalid_value(
Unexpected::Bool(true),
&"a non-negative integer or false",
)),
Err(_) => Err(Error::custom(
"invalid type: expected a non-negative integer or false",
Err(_) => Err(Error::custom("invalid type: expected a non-negative integer or false")),
}
}

/// parse either bool(false) or a number in bytes
pub fn min_available_memory<'de, D>(
deserializer: D,
) -> Result<Option<byte_unit::Byte>, D::Error>
where
D: Deserializer<'de>,
{
match OneOf::deserialize(deserializer) {
Ok(OneOf::Value(value)) => Ok(Some(value)),
Ok(OneOf::Bool(false)) => Ok(None),
Ok(OneOf::Bool(true)) => Err(Error::invalid_value(
Unexpected::Bool(true),
&"a value in bytes (e.g. '100 MB') or false",
)),
Err(_) => Err(Error::custom("invalid type: expected a value in bytes (e.g. '100 MB') or false")),
}
}

Expand All @@ -88,6 +108,10 @@ pub struct Config {
#[serde(deserialize_with = "de::instance_timeout")]
pub instance_timeout: Option<u32>,

#[serde(default = "default::min_available_memory")]
#[serde(deserialize_with = "de::min_available_memory")]
pub min_available_memory: Option<byte_unit::Byte>,

#[serde(default = "default::gc_interval")]
#[serde(deserialize_with = "de::gc_interval")]
pub gc_interval: u32,
Expand Down Expand Up @@ -129,6 +153,7 @@ impl Config {
connect: default::connect(),
log_filters: default::log_filters(),
workspace_detection: default::workspace_detection(),
min_available_memory: default::min_available_memory(),
}
}

Expand Down
Loading

0 comments on commit 0a91981

Please sign in to comment.