perf: make daemon more memory efficient

Use Box<str> instead of String in daemon. Because we don't need to
change names of timers in the daemon this is way more memory efficient.
man-page
Moritz Böhme 2023-07-29 10:15:46 +02:00
parent 853e735fcd
commit b3885f80dd
Signed by: moritz
GPG Key ID: 970C6E89EB0547A9
3 changed files with 20 additions and 30 deletions

View File

@ -11,8 +11,8 @@ use std::{
#[derive(Debug, Serialize, Deserialize)]
pub enum Command {
Add(String, Duration),
Remove(String),
Add(Box<str>, Duration),
Remove(Box<str>),
List,
}
@ -42,12 +42,11 @@ impl Display for Answer {
#[derive(Debug, thiserror::Error, Serialize, Deserialize)]
pub enum AnswerErr {
#[error("Timer with name '{}' already exists", .0)]
TimerAlreadyExist(String),
TimerAlreadyExist(Box<str>),
#[error("No timer with the name '{}' exists", .0)]
NoSuchTimer(String),
NoSuchTimer(Box<str>),
}
pub struct Daemon {
listener: UnixListener,
timers: Vec<Timer>,
@ -68,14 +67,14 @@ impl Daemon {
})
}
fn has_timer(&mut self, name: &String) -> bool {
self.timers.iter().any(|other| &other.name == name)
fn has_timer(&mut self, name: &str) -> bool {
self.timers.iter().any(|other| other.name.as_ref() == name)
}
fn handle_command(&mut self, command: Command) -> Result<Answer, AnswerErr> {
println!("Received command {:?}", command);
match command {
Command::List => Ok(Answer::Timers(self.timers.to_vec())),
Command::List => Ok(Answer::Timers(self.timers.clone())),
Command::Add(name, duration) => {
if self.has_timer(&name) {
return Err(AnswerErr::TimerAlreadyExist(name));
@ -88,12 +87,8 @@ impl Daemon {
if !self.has_timer(&name) {
return Err(AnswerErr::NoSuchTimer(name));
}
self.timers = self
.timers
.iter()
.cloned()
.filter(|other| other.name != name)
.collect();
self.timers
.retain(|other| other.name.as_ref() != name.as_ref());
Ok(Answer::Ok)
}
}
@ -108,18 +103,13 @@ impl Daemon {
}
fn check_timers(&mut self) {
self.timers = self
.timers
.iter()
.cloned()
.filter(|timer| {
let expired = timer.is_expired();
if expired {
println!("Timer {} is expired!", timer.name);
}
!expired
})
.collect();
self.timers.retain(|timer| {
let expired = timer.is_expired();
if expired {
println!("Timer {} is expired!", timer.name);
}
!expired
});
}
pub fn run(&mut self) -> anyhow::Result<()> {

View File

@ -16,9 +16,9 @@ fn main() -> Result<()> {
CliCommand::Add {
name,
duration_seconds,
} => DaemonCommand::Add(name, Duration::from_secs(duration_seconds)),
} => DaemonCommand::Add(name.into_boxed_str(), Duration::from_secs(duration_seconds)),
CliCommand::List => DaemonCommand::List,
CliCommand::Remove { name } => DaemonCommand::Remove(name),
CliCommand::Remove { name } => DaemonCommand::Remove(name.into_boxed_str()),
};
send_command(&args.socket, daemon_command)
}

View File

@ -33,7 +33,7 @@ mod approx_instant {
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
pub struct Timer {
pub name: String,
pub name: Box<str>,
#[serde(with = "approx_instant")]
start: Instant,
duration: Duration,
@ -51,7 +51,7 @@ impl Display for Timer {
}
impl Timer {
pub fn new(name: String, duration: Duration) -> Timer {
pub fn new(name: Box<str>, duration: Duration) -> Timer {
Timer {
name,
start: Instant::now(),