Documentation
// const CPUINFO: &str = "/proc/cpuinfo";
// const MEMINFO: &str = "/proc/meminfo";

// freq 频率
// freq_unit 单位

// export LC_ALL=C; lscpu; unset LC_ALL
// top -bn 1 -i -c // https://www.cnblogs.com/gongchixin/articles/7998054.html

// fn get_num_physical_cpus() -> usize {
//     use std::io::BufReader;
//     use std::io::BufRead;
//     use std::fs::File;
//     use std::collections::HashSet;

//     let file = match File::open("/proc/cpuinfo") {
//         Ok(val) => val,
//         Err(_) => {return get_num_cpus()},
//     };
//     let reader = BufReader::new(file);
//     let mut set = HashSet::new();
//     let mut coreid: u32 = 0;
//     let mut physid: u32 = 0;
//     let mut chgcount = 0;
//     for line in reader.lines().filter_map(|result| result.ok()) {
//         let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
//         if parts.len() != 2 {
//             continue
//         }
//         if parts[0] == "core id" || parts[0] == "physical id" {
//             let value = match parts[1].trim().parse() {
//               Ok(val) => val,
//               Err(_) => break,
//             };
//             match parts[0] {
//                 "core id"     => coreid = value,
//                 "physical id" => physid = value,
//                 _ => {},
//             }
//             chgcount += 1;
//         }
//         if chgcount == 2 {
//             set.insert((physid, coreid));
//             chgcount = 0;
//         }
//     }
//     let count = set.len();
//     if count == 0 { get_num_cpus() } else { count }
// }

// fn cpuinfo() -> io::Result<(String, usize, f64)> {
//     let mut file = File::open(CPUINFO)?;

//     let mut contents = String::new();
//     file.read_to_string(&mut contents)?;

//     contents = contents.replace("\t", "");

//     let parts: Vec<&str> = contents.split("\n\n").filter(|p| p.len() != 0).collect();

//     let cpu_num = parts.len();
//     let mut cpu_name = "";

//     let mut mhz = 0f64;

//     for part in parts {

//         let lines: Vec<&str> = part.split("\n").collect();

//         // let temp = 

//         for line in lines {
//             let value = line.split(':').map(|s| s.trim()).collect::<Vec<&str>>();
//             // println!("{:?}", value);

//             if value[0] == "cpu MHz" {
//                 mhz += value[1].parse::<f64>().unwrap();
//                 // println!("{:?}", mhz);
//             }

//             if value[0] == "model name" {
//                 cpu_name = value[1];
//             }
//         }
//     }

//     println!("{:?}", mhz / cpu_num as f64);
//     println!("{:?}", cpu_name);


//     return Ok((cpu_name.to_string(), cpu_num, mhz / cpu_num as f64))
// }

/*
use std::io;

#[derive(Debug, Default)]
pub struct CpuInfo {
    pub architecture: String,
    pub cpu_op_modes: String,
    pub byte_order: String,
    pub cpus: String,
    pub on_line: String,
    pub threads_per_core: String,
    pub cores_per_socket: String,
    pub sockets: String,
    pub numa_nodes: String,
    pub verdor_id: String,
    pub cpu_family: String,
    pub model: String,
    pub model_name: String,
    pub stepping: String,
    pub cpu_mhz: String,
    pub cpu_max_mhz: String,
    pub cpu_min_mhz: String,
    pub bogo_mips: String,
    pub virtualization: String,
    pub l1d_cache: String,
    pub l1i_cache: String,
    pub l2_cache: String,
    pub l3_cache: String,
    pub numa_node0_cpus: String,
    pub flags: String
}

pub fn cpuinfo() -> io::Result<Option<CpuInfo>>{
    use std::process::Command;

    let lscpu = Command::new("lscpu").env("LC_ALL", "C").output();

    let lscpu = match lscpu {
        Ok(l) => l,
        Err(_) => return Ok(None)
    };

    if !lscpu.status.success() {
        return Ok(None)
    }

    let lscpu = String::from_utf8_lossy(&lscpu.stdout).to_string();

    let lines: Vec<&str> = lscpu.split("\n").collect();

    let mut cpuinfo = CpuInfo::default();

    for line in lines {
        let parts = line.split(':').map(|s| s.trim()).collect::<Vec<&str>>();

        if parts.len() < 2 {
            continue;
        }

        match parts[0] {
            "Architecture" => cpuinfo.architecture = parts[1].to_string(),
            "CPU op-mode(s)" => cpuinfo.cpu_op_modes = parts[1].to_string(),
            "Byte Order" => cpuinfo.byte_order = parts[1].to_string(),
            "CPU(s)" => cpuinfo.cpus = parts[1].to_string(),
            "On-line CPU(s) list" => cpuinfo.on_line = parts[1].to_string(),
            "Thread(s) per core" => cpuinfo.threads_per_core = parts[1].to_string(),
            "Core(s) per socket" => cpuinfo.cores_per_socket = parts[1].to_string(),
            "Socket(s)" => cpuinfo.sockets = parts[1].to_string(),
            "NUMA node(s)" => cpuinfo.numa_nodes = parts[1].to_string(),
            "Vendor ID" => cpuinfo.verdor_id = parts[1].to_string(),
            "CPU family" => cpuinfo.cpu_family = parts[1].to_string(),
            "Model" => cpuinfo.model = parts[1].to_string(),
            "Model name" => cpuinfo.model_name = parts[1].to_string(),
            "Stepping" => cpuinfo.model_name = parts[1].to_string(),
            "CPU MHz" => cpuinfo.cpu_mhz = parts[1].to_string(),
            "CPU max MHz" => cpuinfo.cpu_max_mhz = parts[1].to_string(),
            "CPU min MHz" => cpuinfo.cpu_min_mhz = parts[1].to_string(),
            "BogoMIPS" => cpuinfo.bogo_mips = parts[1].to_string(),
            "Virtualization" => cpuinfo.virtualization = parts[1].to_string(),
            "L1d cache" => cpuinfo.l1d_cache = parts[1].to_string(),
            "L1i cache" => cpuinfo.l1i_cache = parts[1].to_string(),
            "L2 cache" => cpuinfo.l2_cache = parts[1].to_string(),
            "L3 cache" => cpuinfo.l3_cache = parts[1].to_string(),
            "NUMA node0 CPU(s)" => cpuinfo.numa_node0_cpus = parts[1].to_string(),
            "Flags" => cpuinfo.flags = parts[1].to_string(),
            _ => ()
        }
    }

    return Ok(Some(cpuinfo))
}

pub fn sysinfo() {
    let mut sysinfo: libc::sysinfo = unsafe { std::mem::zeroed() };
    unsafe { libc::sysinfo(&mut sysinfo as *mut _); }
}

// cat /proc/loadavg
pub fn loadavg() {

}

pub fn uptime() {

}
*/