mirror of
https://github.com/NotAShelf/microfetch.git
synced 2025-11-27 17:42:50 +00:00
uptime: optimize uptime calculation w/ inline assembly and custom itoa
lol, lmao even. Signed-off-by: NotAShelf <raf@notashelf.dev> Change-Id: Ie22fbd2e9c2be5740b493bdc81caafb36a6a6964
This commit is contained in:
parent
b24e720dd8
commit
f8a0070986
1 changed files with 69 additions and 5 deletions
|
|
@ -1,4 +1,66 @@
|
||||||
use std::{fmt::Write, io, mem::MaybeUninit};
|
use std::{io, mem::MaybeUninit};
|
||||||
|
|
||||||
|
/// Fast integer to string conversion (no formatting overhead)
|
||||||
|
#[inline]
|
||||||
|
fn itoa(mut n: u64, buf: &mut [u8]) -> &str {
|
||||||
|
if n == 0 {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut i = buf.len();
|
||||||
|
while n > 0 {
|
||||||
|
i -= 1;
|
||||||
|
buf[i] = b'0' + (n % 10) as u8;
|
||||||
|
n /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe { std::str::from_utf8_unchecked(&buf[i..]) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Direct sysinfo syscall using inline assembly
|
||||||
|
///
|
||||||
|
/// # Safety
|
||||||
|
/// This function uses inline assembly to make a direct syscall.
|
||||||
|
/// The caller must ensure the sysinfo pointer is valid.
|
||||||
|
#[inline]
|
||||||
|
unsafe fn sys_sysinfo(info: *mut libc::sysinfo) -> i64 {
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
{
|
||||||
|
let ret: i64;
|
||||||
|
unsafe {
|
||||||
|
std::arch::asm!(
|
||||||
|
"syscall",
|
||||||
|
in("rax") 99_i64, // __NR_sysinfo
|
||||||
|
in("rdi") info,
|
||||||
|
out("rcx") _,
|
||||||
|
out("r11") _,
|
||||||
|
lateout("rax") ret,
|
||||||
|
options(nostack)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
{
|
||||||
|
let ret: i64;
|
||||||
|
unsafe {
|
||||||
|
std::arch::asm!(
|
||||||
|
"svc #0",
|
||||||
|
in("x8") 179_i64, // __NR_sysinfo
|
||||||
|
in("x0") info,
|
||||||
|
lateout("x0") ret,
|
||||||
|
options(nostack)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
ret
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
|
||||||
|
{
|
||||||
|
unsafe { libc::sysinfo(info) as i64 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets the current system uptime.
|
/// Gets the current system uptime.
|
||||||
///
|
///
|
||||||
|
|
@ -9,7 +71,7 @@ use std::{fmt::Write, io, mem::MaybeUninit};
|
||||||
pub fn get_current() -> Result<String, io::Error> {
|
pub fn get_current() -> Result<String, io::Error> {
|
||||||
let uptime_seconds = {
|
let uptime_seconds = {
|
||||||
let mut info = MaybeUninit::uninit();
|
let mut info = MaybeUninit::uninit();
|
||||||
if unsafe { libc::sysinfo(info.as_mut_ptr()) } != 0 {
|
if unsafe { sys_sysinfo(info.as_mut_ptr()) } != 0 {
|
||||||
return Err(io::Error::last_os_error());
|
return Err(io::Error::last_os_error());
|
||||||
}
|
}
|
||||||
#[allow(clippy::cast_sign_loss)]
|
#[allow(clippy::cast_sign_loss)]
|
||||||
|
|
@ -23,22 +85,24 @@ pub fn get_current() -> Result<String, io::Error> {
|
||||||
let minutes = (uptime_seconds / 60) % 60;
|
let minutes = (uptime_seconds / 60) % 60;
|
||||||
|
|
||||||
let mut result = String::with_capacity(32);
|
let mut result = String::with_capacity(32);
|
||||||
|
let mut buf = [0u8; 20]; // Enough for u64::MAX
|
||||||
|
|
||||||
if days > 0 {
|
if days > 0 {
|
||||||
let _ = write!(result, "{days}");
|
result.push_str(itoa(days, &mut buf));
|
||||||
result.push_str(if days == 1 { " day" } else { " days" });
|
result.push_str(if days == 1 { " day" } else { " days" });
|
||||||
}
|
}
|
||||||
if hours > 0 {
|
if hours > 0 {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
result.push_str(", ");
|
result.push_str(", ");
|
||||||
}
|
}
|
||||||
let _ = write!(result, "{hours}");
|
result.push_str(itoa(hours, &mut buf));
|
||||||
result.push_str(if hours == 1 { " hour" } else { " hours" });
|
result.push_str(if hours == 1 { " hour" } else { " hours" });
|
||||||
}
|
}
|
||||||
if minutes > 0 {
|
if minutes > 0 {
|
||||||
if !result.is_empty() {
|
if !result.is_empty() {
|
||||||
result.push_str(", ");
|
result.push_str(", ");
|
||||||
}
|
}
|
||||||
let _ = write!(result, "{minutes}");
|
result.push_str(itoa(minutes, &mut buf));
|
||||||
result.push_str(if minutes == 1 { " minute" } else { " minutes" });
|
result.push_str(if minutes == 1 { " minute" } else { " minutes" });
|
||||||
}
|
}
|
||||||
if result.is_empty() {
|
if result.is_empty() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue