mirror of
https://codeberg.org/icewind/palantir.git
synced 2026-06-03 10:14:09 +02:00
optimize zfs
This commit is contained in:
parent
7537958e6c
commit
5544b9984a
3 changed files with 67 additions and 40 deletions
|
|
@ -1,5 +1,7 @@
|
||||||
use iai::black_box;
|
use iai::black_box;
|
||||||
use palantir::get_metrics;
|
use palantir::get_metrics;
|
||||||
|
use palantir::heim::temperatures;
|
||||||
|
use palantir::zfs::pools;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
|
|
||||||
fn iai_get_metrics() -> String {
|
fn iai_get_metrics() -> String {
|
||||||
|
|
@ -7,4 +9,13 @@ fn iai_get_metrics() -> String {
|
||||||
rt.block_on(async { black_box(get_metrics().await.unwrap()) })
|
rt.block_on(async { black_box(get_metrics().await.unwrap()) })
|
||||||
}
|
}
|
||||||
|
|
||||||
iai::main!(iai_get_metrics);
|
fn iai_zfs_pool() {
|
||||||
|
black_box(pools().collect::<Vec<_>>());
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iai_temperatures() {
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
rt.block_on(async { black_box(temperatures().await).unwrap() });
|
||||||
|
}
|
||||||
|
|
||||||
|
iai::main!(iai_get_metrics, iai_zfs_pool, iai_temperatures);
|
||||||
|
|
|
||||||
19
src/lib.rs
19
src/lib.rs
|
|
@ -1,27 +1,17 @@
|
||||||
pub(crate) mod heim;
|
pub mod heim;
|
||||||
mod zfs;
|
pub mod zfs;
|
||||||
|
|
||||||
use crate::heim::*;
|
use crate::heim::*;
|
||||||
use crate::zfs::pools;
|
use crate::zfs::pools;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use futures_util::stream::StreamExt;
|
use futures_util::stream::StreamExt;
|
||||||
use futures_util::{pin_mut, try_join};
|
use futures_util::{pin_mut, try_join};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::HashSet;
|
||||||
use std::fmt::Write;
|
use std::fmt::Write;
|
||||||
|
|
||||||
pub async fn get_metrics() -> Result<String> {
|
pub async fn get_metrics() -> Result<String> {
|
||||||
let (hostname, pools, cpu, memory, network, temperatures, disks, disk_usage): (
|
let (hostname, cpu, memory, network, temperatures, disks, disk_usage) = try_join! {
|
||||||
String,
|
|
||||||
Vec<DiskUsage>,
|
|
||||||
f64,
|
|
||||||
Memory,
|
|
||||||
_,
|
|
||||||
HashMap<TemperatureLabel, f32>,
|
|
||||||
_,
|
|
||||||
_,
|
|
||||||
) = try_join! {
|
|
||||||
hostname(),
|
hostname(),
|
||||||
pools(),
|
|
||||||
cpu_time(),
|
cpu_time(),
|
||||||
memory(),
|
memory(),
|
||||||
network_stats(),
|
network_stats(),
|
||||||
|
|
@ -29,6 +19,7 @@ pub async fn get_metrics() -> Result<String> {
|
||||||
disk_stats(),
|
disk_stats(),
|
||||||
disk_usage(),
|
disk_usage(),
|
||||||
}?;
|
}?;
|
||||||
|
let pools = pools();
|
||||||
pin_mut!(network);
|
pin_mut!(network);
|
||||||
pin_mut!(disks);
|
pin_mut!(disks);
|
||||||
pin_mut!(disk_usage);
|
pin_mut!(disk_usage);
|
||||||
|
|
|
||||||
75
src/zfs.rs
75
src/zfs.rs
|
|
@ -1,31 +1,56 @@
|
||||||
use crate::heim::DiskUsage;
|
use crate::heim::DiskUsage;
|
||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use tokio::task::spawn_blocking;
|
|
||||||
|
|
||||||
pub async fn pools() -> Result<Vec<DiskUsage>> {
|
pub fn pools() -> impl Iterator<Item = DiskUsage> {
|
||||||
spawn_blocking(move || {
|
OutputParser {
|
||||||
let mut z = Command::new("zpool");
|
str: zpool_command().unwrap_or_default(),
|
||||||
z.args(&["list", "-p", "-H", "-o", "name,size,free"]);
|
pos: 0,
|
||||||
let out = match z.output() {
|
}
|
||||||
Ok(out) => out,
|
}
|
||||||
Err(_) => return Ok(Vec::new()),
|
|
||||||
|
fn zpool_command() -> Result<String> {
|
||||||
|
let mut z = Command::new("zpool");
|
||||||
|
z.args(&["list", "-p", "-H", "-o", "name,size,free"]);
|
||||||
|
let out = z.output()?;
|
||||||
|
if out.status.success() {
|
||||||
|
Ok(String::from_utf8(out.stdout)?)
|
||||||
|
} else {
|
||||||
|
Ok(String::new())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_line(line: &str) -> Option<DiskUsage> {
|
||||||
|
let mut parts = line.split_ascii_whitespace();
|
||||||
|
let name = parts.next()?.to_string();
|
||||||
|
let size = parts.next()?.parse().ok()?;
|
||||||
|
let free = parts.next()?.parse().ok()?;
|
||||||
|
Some(DiskUsage { name, size, free })
|
||||||
|
}
|
||||||
|
|
||||||
|
struct OutputParser {
|
||||||
|
str: String,
|
||||||
|
pos: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Iterator for OutputParser {
|
||||||
|
type Item = DiskUsage;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
let str = self.str.as_str();
|
||||||
|
let line = match str[self.pos..].find('\n') {
|
||||||
|
Some(next_pos) => {
|
||||||
|
let old_pos = self.pos;
|
||||||
|
self.pos += next_pos;
|
||||||
|
Some(&str[old_pos..self.pos])
|
||||||
|
}
|
||||||
|
None if self.pos < str.len() => {
|
||||||
|
let old_pos = self.pos;
|
||||||
|
self.pos = str.len();
|
||||||
|
Some(&str[old_pos..])
|
||||||
|
}
|
||||||
|
None => None,
|
||||||
};
|
};
|
||||||
if out.status.success() {
|
line.and_then(parse_line)
|
||||||
let output = String::from_utf8(out.stdout)?;
|
}
|
||||||
Ok(output
|
|
||||||
.lines()
|
|
||||||
.flat_map(|line| {
|
|
||||||
let mut parts = line.split_ascii_whitespace();
|
|
||||||
let name = parts.next()?.to_string();
|
|
||||||
let size = parts.next()?.parse().ok()?;
|
|
||||||
let free = parts.next()?.parse().ok()?;
|
|
||||||
Some(DiskUsage { name, size, free })
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
} else {
|
|
||||||
Ok(Vec::new())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.await?
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue