diff --git a/README.md b/README.md
index ec119aa..ce8a7bb 100644
--- a/README.md
+++ b/README.md
@@ -604,7 +604,7 @@ You need [`cargo`](https://www.rust-lang.org/learn/get-started), Rust's build to
The `--release` profile in Gupax is set to prefer code performance & small binary sizes over compilation speed (see [`Cargo.toml`](https://github.com/hinto-janaiyo/gupax/blob/main/Cargo.toml)). Gupax itself (with all dependencies already built) takes around 1m30s to build (vs 10s on a normal `--release`) with a Ryzen 5950x.
-There are `38` unit tests throughout the codebase files, you should probably run:
+There are `40` unit tests throughout the codebase files, you should probably run:
```
cargo test
```
diff --git a/src/README.md b/src/README.md
index e8e2d8f..7da5781 100644
--- a/src/README.md
+++ b/src/README.md
@@ -18,7 +18,7 @@
## Structure
| File/Folder | Purpose |
|--------------|---------|
-| benchmark.rs | Code for handling [XMRig's benchmark data](https://xmrig.com/docs/api/1/benchmark)
+| cpu.json | [XMRig benchmark data in JSON](https://github.com/hinto-janaiyo/xmrig-benchmarks)
| constants.rs | General constants used in Gupax
| disk.rs | Code for writing to disk: `state.toml/node.toml/pool.toml`; This holds the structs for the [State] struct
| ferris.rs | Cute crab bytes
diff --git a/src/benchmark.rs b/src/benchmark.rs
deleted file mode 100644
index 88e73e2..0000000
--- a/src/benchmark.rs
+++ /dev/null
@@ -1,87 +0,0 @@
-// Gupax - GUI Uniting P2Pool And XMRig
-//
-// Copyright (c) 2022-2023 hinto-janai
-//
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program. If not, see .
-
-// This file contains backend code for handling XMRig's benchmark data:
-// - HTTP(s) fetchs to [https://xmrig.com]
-// - (De)serialization of JSON data
-// - (De)serialization of CPU topology XML (./xmrig --export topology)
-
-use serde::{Serialize, Deserialize};
-use std::fmt::Write;
-
-// Input: Full [&str] of XMRig's [topology.xml] file
-// Output: The CPU name formatted so it's usable as the endpoint, e.g: [AMD+Ryzen+9+5950X+16-Core+Processor]
-fn cpu_name_from_xml(xml: &str) -> Option {
- // A minimal matching struct for the [CPUModel] field in the XML file
- #[derive(Debug, Serialize, Deserialize, PartialEq)]
- struct Info { //
- name: String, // name="CPUModel"
- value: String, // value="Ryzen ..."
- }
-
- // Regex to find matching field
- let regex = regex::Regex::new("\"CPUModel\"").unwrap();
-
- for line in xml.lines() {
- if !regex.is_match(&line) { continue }
-
- // If found, attempt to serialize XML proper
- if let Ok(info) = serde_xml_rs::from_str::(&line) {
- // Return early if empty
- if info.value.is_empty() {
- return None
- }
- // If serialized, turn whitespaces into '+'
- let words: Vec<&str> = info.value.split_whitespace().collect();
- let last_word = words.len();
- let mut result = String::new();
- let mut n = 1;
- for word in words.iter() {
- match n == last_word {
- false => write!(result, "{}+", word),
- true => write!(result, "{}", word),
- };
- n += 1;
- }
- return Some(result)
- }
- }
-
- // If loop didn't return early, return none
- None
-}
-
-//---------------------------------------------------------------------------------------------------- TESTS
-#[cfg(test)]
-mod test {
- #[test]
- fn get_cpu_from_xml() {
- let string =
-r#"
-
-
-
-
-
-
-
-
-
-"#;
- assert_eq!(crate::benchmark::cpu_name_from_xml(&string).unwrap(), "AMD+Ryzen+9+5950X+16-Core+Processor");
- }
-}
diff --git a/src/constants.rs b/src/constants.rs
index b91db31..4b525bf 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -174,6 +174,7 @@ pub const STATUS_XMRIG_THREADS: &str = "The amount of threads XMRig is curre
// Status Submenus
pub const STATUS_SUBMENU_PROCESSES: &str = "View the status of process related data for [Gupax|P2Pool|XMRig]";
pub const STATUS_SUBMENU_P2POOL: &str = "View P2Pool specific data";
+pub const STATUS_SUBMENU_HASHRATE: &str = "Compare your CPU hashrate with others";
//-- P2Pool
pub const STATUS_SUBMENU_PAYOUT: &str = "The total amount of payouts received via P2Pool across all time. This includes all payouts you have ever received using Gupax and P2Pool.";
pub const STATUS_SUBMENU_XMR: &str = "The total of XMR mined via P2Pool across all time. This includes all the XMR you have ever mined using Gupax and P2Pool.";
@@ -200,6 +201,21 @@ pub const STATUS_SUBMENU_P2POOL_DOMINANCE: &str = "The percent of hashrate
pub const STATUS_SUBMENU_YOUR_P2POOL_DOMINANCE: &str = "The percent of hashrate you account for in P2Pool";
pub const STATUS_SUBMENU_YOUR_MONERO_DOMINANCE: &str = "The percent of hashrate you account for in the entire Monero network";
pub const STATUS_SUBMENU_PROGRESS_BAR: &str = "The next time Gupax will update P2Pool stats. Each [*] is 900ms (updates roughly every 54 seconds)";
+//-- Benchmarks
+pub const STATUS_SUBMENU_YOUR_CPU: &str = "The CPU detected by Gupax";
+pub const STATUS_SUBMENU_YOUR_BENCHMARKS: &str = "How many benchmarks your CPU has had uploaded to [https://xmrig.com/benchmark] ";
+pub const STATUS_SUBMENU_YOUR_RANK: &str = "Your CPU's rank out of all CPUs listed on [https://xmrig.com/benchmark] (higher is better)";
+pub const STATUS_SUBMENU_YOUR_HIGH: &str = "The highest hashrate recorded for your CPU on [https://xmrig.com/benchmark]";
+pub const STATUS_SUBMENU_YOUR_AVERAGE: &str = "The average hashrate of your CPU based off the data at [https://xmrig.com/benchmark]";
+pub const STATUS_SUBMENU_YOUR_LOW: &str = "The lowest hashrate recorded for your CPU on [https://xmrig.com/benchmark]";
+pub const STATUS_SUBMENU_OTHER_CPUS: &str = "A list of ALL the recorded CPU benchmarks. The CPUs most similar to yours are listed first. All this data is taken from [https://github.com/hinto-janai/xmrig-benchmarks] which itself takes from [https://xmrig.com/benchmark].";
+pub const STATUS_SUBMENU_OTHER_CPU: &str = "The CPU name";
+pub const STATUS_SUBMENU_OTHER_RELATIVE: &str = "The relative hashrate power compared to the fastest recorded CPU, which is current: [AMD EPYC 7T83 64-Core Processor]";
+pub const STATUS_SUBMENU_OTHER_HIGH: &str = "Highest hashrate record";
+pub const STATUS_SUBMENU_OTHER_AVERAGE: &str = "Average hashrate";
+pub const STATUS_SUBMENU_OTHER_LOW: &str = "Lowest hashrate record";
+pub const STATUS_SUBMENU_OTHER_RANK: &str = "The rank of this CPU out of [1567] (lower is better)";
+pub const STATUS_SUBMENU_OTHER_BENCHMARKS: &str = "How many benchmarks this CPU has had posted to [https://xmrig.com/benchmark]";
// Gupax
pub const GUPAX_UPDATE: &str = "Check for updates on Gupax, P2Pool, and XMRig via GitHub's API and upgrade automatically";
diff --git a/src/disk.rs b/src/disk.rs
index 9069b88..f741e3a 100644
--- a/src/disk.rs
+++ b/src/disk.rs
@@ -825,6 +825,7 @@ pub enum File {
pub enum Submenu {
Processes,
P2pool,
+ Benchmarks,
}
impl Default for Submenu {
diff --git a/src/gupax.rs b/src/gupax.rs
index 3a1839e..c243e41 100644
--- a/src/gupax.rs
+++ b/src/gupax.rs
@@ -82,6 +82,7 @@ pub enum Ratio {
//---------------------------------------------------------------------------------------------------- Gupax
impl crate::disk::Gupax {
+ #[inline(always)]
pub fn show(&mut self, og: &Arc>, state_path: &Path, update: &Arc>, file_window: &Arc>, error_state: &mut ErrorState, restart: &Arc>, width: f32, height: f32, frame: &mut eframe::Frame, _ctx: &egui::Context, ui: &mut egui::Ui) {
// Update button + Progress bar
debug!("Gupax Tab | Rendering [Update] button + progress bar");
diff --git a/src/helper.rs b/src/helper.rs
index c61bcfd..33f12d6 100644
--- a/src/helper.rs
+++ b/src/helper.rs
@@ -1731,6 +1731,8 @@ pub struct PubXmrigApi {
pub diff: HumanNumber,
pub accepted: HumanNumber,
pub rejected: HumanNumber,
+
+ pub hashrate_raw: f32,
}
impl Default for PubXmrigApi {
@@ -1750,6 +1752,7 @@ impl PubXmrigApi {
diff: HumanNumber::unknown(),
accepted: HumanNumber::unknown(),
rejected: HumanNumber::unknown(),
+ hashrate_raw: 0.0,
}
}
@@ -1780,6 +1783,11 @@ impl PubXmrigApi {
// Formats raw private data into ready-to-print human readable version.
fn update_from_priv(public: &Arc>, private: PrivXmrigApi) {
let mut public = lock!(public);
+ let hashrate_raw = match private.hashrate.total.get(0) {
+ Some(Some(h)) => *h,
+ _ => 0.0,
+ };
+
*public = Self {
worker_id: private.worker_id,
resources: HumanNumber::from_load(private.resources.load_average),
@@ -1787,6 +1795,7 @@ impl PubXmrigApi {
diff: HumanNumber::from_u128(private.connection.diff),
accepted: HumanNumber::from_u128(private.connection.accepted),
rejected: HumanNumber::from_u128(private.connection.rejected),
+ hashrate_raw,
..std::mem::take(&mut *public)
}
}
diff --git a/src/human.rs b/src/human.rs
index be9586d..b13e9c9 100644
--- a/src/human.rs
+++ b/src/human.rs
@@ -116,6 +116,9 @@ impl HumanNumber {
pub fn from_str(s: &str) -> Self {
Self(s.to_string())
}
+ pub fn to_hashrate(f: f32) -> Self {
+ Self(format!("{} H/s", Self::from_f32(f)))
+ }
pub fn to_percent(f: f32) -> Self {
if f < 0.01 {
Self("0%".to_string())
diff --git a/src/main.rs b/src/main.rs
index aeaee2d..bdfbd6a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -51,6 +51,7 @@ use std::{
};
// Sysinfo
use sysinfo::SystemExt;
+use sysinfo::CpuExt;
// Modules
//mod benchmark;
mod ferris;
@@ -140,6 +141,7 @@ pub struct App {
// actual stats, and all the functions needed to mutate them.
gupax_p2pool_api: Arc>,
// Static stuff
+ benchmarks: Vec, // XMRig CPU benchmarks
pid: sysinfo::Pid, // Gupax's PID
max_threads: usize, // Max amount of detected system threads
now: Instant, // Internal timer
@@ -199,6 +201,18 @@ impl App {
};
let pub_sys = arc_mut!(Sys::new());
+ // CPU Benchmark data initialization.
+ info!("App Init | Initializing CPU benchmarks...");
+ let benchmarks: Vec = {
+ let cpu = sysinfo.cpus()[0].brand();
+ let mut json: Vec = serde_json::from_slice(include_bytes!("cpu.json")).unwrap();
+ json.sort_by(|a, b| {
+ cmp_f64(strsim::jaro(&b.cpu, &cpu), strsim::jaro(&a.cpu, &cpu))
+ });
+ json
+ };
+ info!("App Init | Assuming user's CPU is: {}", benchmarks[0].cpu);
+
info!("App Init | The rest of the [App]...");
let mut app = Self {
tab: Tab::default(),
@@ -232,6 +246,7 @@ impl App {
no_startup: false,
gupax_p2pool_api: arc_mut!(GupaxP2poolApi::new()),
pub_sys,
+ benchmarks,
pid,
max_threads: num_cpus::get(),
now,
@@ -507,6 +522,18 @@ impl Default for Tab {
}
}
+//---------------------------------------------------------------------------------------------------- CPU Benchmarks.
+#[derive(Debug,Serialize,Deserialize)]
+pub struct Benchmark {
+ pub cpu: String,
+ pub rank: u16,
+ pub percent: f32,
+ pub benchmarks: u16,
+ pub average: f32,
+ pub high: f32,
+ pub low: f32,
+}
+
//---------------------------------------------------------------------------------------------------- [Restart] Enum
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Restart {
@@ -688,6 +715,7 @@ impl KeyPressed {
}
//---------------------------------------------------------------------------------------------------- Init functions
+#[inline(always)]
fn init_text_styles(ctx: &egui::Context, width: f32) {
let scale = width / 30.0;
let mut style = (*ctx.style()).clone();
@@ -711,6 +739,7 @@ fn init_text_styles(ctx: &egui::Context, width: f32) {
ctx.request_repaint();
}
+#[inline(always)]
fn init_logger(now: Instant) {
use env_logger::fmt::Color;
let filter_env = std::env::var("RUST_LOG").unwrap_or_else(|_| "INFO".to_string());
@@ -746,6 +775,7 @@ fn init_logger(now: Instant) {
info!("Log level ... {}", filter);
}
+#[inline(always)]
fn init_options(initial_window_size: Option) -> NativeOptions {
let mut options = eframe::NativeOptions::default();
options.min_window_size = Some(Vec2::new(APP_MIN_WIDTH, APP_MIN_HEIGHT));
@@ -764,6 +794,7 @@ fn init_options(initial_window_size: Option) -> NativeOptions {
options
}
+#[inline(always)]
fn init_auto(app: &mut App) {
// Return early if [--no-startup] was not passed
if app.no_startup {
@@ -831,6 +862,7 @@ fn reset_state(path: &PathBuf) -> Result<(), TomlError> {
}
}
+#[inline(always)]
fn reset_nodes(path: &PathBuf) -> Result<(), TomlError> {
match Node::create_new(path) {
Ok(_) => { info!("Resetting [node.toml] ... OK"); Ok(()) },
@@ -838,6 +870,7 @@ fn reset_nodes(path: &PathBuf) -> Result<(), TomlError> {
}
}
+#[inline(always)]
fn reset_pools(path: &PathBuf) -> Result<(), TomlError> {
match Pool::create_new(path) {
Ok(_) => { info!("Resetting [pool.toml] ... OK"); Ok(()) },
@@ -845,6 +878,7 @@ fn reset_pools(path: &PathBuf) -> Result<(), TomlError> {
}
}
+#[inline(always)]
fn reset_gupax_p2pool_api(path: &PathBuf) -> Result<(), TomlError> {
match GupaxP2poolApi::create_new(path) {
Ok(_) => { info!("Resetting GupaxP2poolApi ... OK"); Ok(()) },
@@ -852,6 +886,7 @@ fn reset_gupax_p2pool_api(path: &PathBuf) -> Result<(), TomlError> {
}
}
+#[inline(always)]
fn reset(path: &PathBuf, state: &PathBuf, node: &PathBuf, pool: &PathBuf, gupax_p2pool_api: &PathBuf) {
let mut code = 0;
// Attempt to remove directory first
@@ -888,6 +923,7 @@ fn reset(path: &PathBuf, state: &PathBuf, node: &PathBuf, pool: &PathBuf, gupax_
}
//---------------------------------------------------------------------------------------------------- Misc functions
+#[inline(always)]
fn parse_args>(mut app: App, panic: S) -> App {
info!("Parsing CLI arguments...");
let mut args: Vec = env::args().collect();
@@ -930,6 +966,7 @@ fn parse_args>(mut app: App, panic: S) -> App {
}
// Get absolute [Gupax] binary path
+#[inline(always)]
pub fn get_exe() -> Result {
match std::env::current_exe() {
Ok(path) => { Ok(path.display().to_string()) },
@@ -938,6 +975,7 @@ pub fn get_exe() -> Result {
}
// Get absolute [Gupax] directory path
+#[inline(always)]
pub fn get_exe_dir() -> Result {
match std::env::current_exe() {
Ok(mut path) => { path.pop(); Ok(path.display().to_string()) },
@@ -947,6 +985,7 @@ pub fn get_exe_dir() -> Result {
// Clean any [gupax_update_.*] directories
// The trailing random bits must be exactly 10 alphanumeric characters
+#[inline(always)]
pub fn clean_dir() -> Result<(), anyhow::Error> {
let regex = Regex::new("^gupax_update_[A-Za-z0-9]{10}$").unwrap();
for entry in std::fs::read_dir(get_exe_dir()?)? {
@@ -964,6 +1003,7 @@ pub fn clean_dir() -> Result<(), anyhow::Error> {
}
// Print disk files to console
+#[inline(always)]
fn print_disk_file(path: &PathBuf) {
match std::fs::read_to_string(path) {
Ok(string) => { print!("{}", string); exit(0); },
@@ -972,6 +1012,7 @@ fn print_disk_file(path: &PathBuf) {
}
// Prints the GupaxP2PoolApi files.
+#[inline(always)]
fn print_gupax_p2pool_api(gupax_p2pool_api: &Arc>) {
let api = lock!(gupax_p2pool_api);
let log = match std::fs::read_to_string(&api.path_log) {
@@ -994,6 +1035,16 @@ fn print_gupax_p2pool_api(gupax_p2pool_api: &Arc>) {
exit(0);
}
+#[inline(always)]
+fn cmp_f64(a: f64, b: f64) -> std::cmp::Ordering {
+ match (a <= b, a >= b) {
+ (false, true) => std::cmp::Ordering::Greater,
+ (true, false) => std::cmp::Ordering::Less,
+ (true, true) => std::cmp::Ordering::Equal,
+ _ => std::cmp::Ordering::Less,
+ }
+}
+
//---------------------------------------------------------------------------------------------------- Main [App] frame
fn main() {
let now = Instant::now();
@@ -1018,6 +1069,7 @@ fn main() {
}
impl eframe::App for App {
+ #[inline(always)]
fn on_close_event(&mut self) -> bool {
if self.state.gupax.ask_before_quit {
// If we're already on the [ask_before_quit] screen and
@@ -1037,6 +1089,7 @@ impl eframe::App for App {
}
}
+ #[inline(always)]
fn update(&mut self, ctx: &egui::Context, frame: &mut eframe::Frame) {
// *-------*
// | DEBUG |
@@ -1104,8 +1157,9 @@ impl eframe::App for App {
match self.tab {
Tab::Status => {
match self.state.status.submenu {
- Submenu::Processes => self.state.status.submenu = Submenu::P2pool,
+ Submenu::Processes => self.state.status.submenu = Submenu::Benchmarks,
Submenu::P2pool => self.state.status.submenu = Submenu::Processes,
+ Submenu::Benchmarks => self.state.status.submenu = Submenu::P2pool,
}
},
Tab::Gupax => flip!(self.state.gupax.simple),
@@ -1119,7 +1173,8 @@ impl eframe::App for App {
Tab::Status => {
match self.state.status.submenu {
Submenu::Processes => self.state.status.submenu = Submenu::P2pool,
- Submenu::P2pool => self.state.status.submenu = Submenu::Processes,
+ Submenu::P2pool => self.state.status.submenu = Submenu::Benchmarks,
+ Submenu::Benchmarks => self.state.status.submenu = Submenu::Processes,
}
},
Tab::Gupax => flip!(self.state.gupax.simple),
@@ -1517,7 +1572,11 @@ impl eframe::App for App {
match self.tab {
Tab::Status => {
ui.group(|ui| {
- let width = (ui.available_width() / 2.0)-10.5;
+ let width = (ui.available_width() / 3.0)-14.0;
+ if ui.add_sized([width, height], SelectableLabel::new(self.state.status.submenu == Submenu::Benchmarks, "Benchmarks")).on_hover_text(STATUS_SUBMENU_HASHRATE).clicked() {
+ self.state.status.submenu = Submenu::Benchmarks;
+ }
+ ui.separator();
if ui.add_sized([width, height], SelectableLabel::new(self.state.status.submenu == Submenu::P2pool, "P2Pool")).on_hover_text(STATUS_SUBMENU_P2POOL).clicked() {
self.state.status.submenu = Submenu::P2pool;
}
@@ -1800,7 +1859,7 @@ path_xmr: {:#?}\n
}
Tab::Status => {
debug!("App | Entering [Status] Tab");
- crate::disk::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, self.width, self.height, ctx, ui);
+ crate::disk::Status::show(&mut self.state.status, &self.pub_sys, &self.p2pool_api, &self.xmrig_api, &self.p2pool_img, &self.xmrig_img, p2pool_is_alive, xmrig_is_alive, self.max_threads, &self.gupax_p2pool_api, &self.benchmarks, self.width, self.height, ctx, ui);
}
Tab::Gupax => {
debug!("App | Entering [Gupax] Tab");
@@ -1840,4 +1899,21 @@ mod test {
assert!(!Regex::is_match(&r.port, "0"));
assert!(!Regex::is_match(&r.port, "65536"));
}
+
+ #[test]
+ fn detect_benchmark_cpu() {
+ use super::{Benchmark,cmp_f64};
+
+ let cpu = "AMD Ryzen 9 5950X 16-Core Processor";
+
+ let benchmarks: Vec = {
+ let mut json: Vec = serde_json::from_slice(include_bytes!("cpu.json")).unwrap();
+ json.sort_by(|a, b| {
+ cmp_f64(strsim::jaro(&b.cpu, &cpu), strsim::jaro(&a.cpu, &cpu))
+ });
+ json
+ };
+
+ assert!(benchmarks[0].cpu == "AMD Ryzen 9 5950X 16-Core Processor");
+ }
}
diff --git a/src/p2pool.rs b/src/p2pool.rs
index b269466..f7631c4 100644
--- a/src/p2pool.rs
+++ b/src/p2pool.rs
@@ -33,6 +33,7 @@ use regex::Regex;
use log::*;
impl crate::disk::P2pool {
+ #[inline(always)]
pub fn show(&mut self, node_vec: &mut Vec<(String, Node)>, _og: &Arc>, ping: &Arc>, regex: &Regexes, process: &Arc>, api: &Arc>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console
diff --git a/src/status.rs b/src/status.rs
index 087c833..d89fa36 100644
--- a/src/status.rs
+++ b/src/status.rs
@@ -28,6 +28,7 @@ use crate::{
GupaxP2poolApi,
PayoutView,
human::HumanNumber,
+ Benchmark,
};
use std::sync::{Arc,Mutex};
use log::*;
@@ -36,12 +37,13 @@ use egui::{
TextStyle::Monospace,
TextStyle::Name,
TextEdit,
- SelectableLabel,
- Slider,
+ SelectableLabel,Hyperlink,
+ Slider,ProgressBar,Spinner,
};
impl crate::disk::Status {
-pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc>, xmrig_api: &Arc>, p2pool_img: &Arc>, xmrig_img: &Arc>, p2pool_alive: bool, xmrig_alive: bool, max_threads: usize, gupax_p2pool_api: &Arc>, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
+#[inline(always)]
+pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc>, xmrig_api: &Arc>, p2pool_img: &Arc>, xmrig_img: &Arc>, p2pool_alive: bool, xmrig_alive: bool, max_threads: usize, gupax_p2pool_api: &Arc>, benchmarks: &[Benchmark], width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
//---------------------------------------------------------------------------------------------------- [Processes]
if self.submenu == Submenu::Processes {
let width = (width/3.0)-(SPACE*1.666);
@@ -268,6 +270,115 @@ pub fn show(&mut self, sys: &Arc>, p2pool_api: &Arc 100.0 {
+ ui.add_sized([width, double], Label::new(format!("Your CPU's is faster than the highest benchmark! It is [{}] faster @ {}!", human, api.hashrate)));
+ ui.add_sized([width, text], ProgressBar::new(1.0));
+ } else if api.hashrate_raw == 0.0 {
+ ui.add_sized([width, text], Label::new("Measuring hashrate..."));
+ ui.add_sized([width, text], Spinner::new().size(text));
+ ui.add_sized([width, text], ProgressBar::new(0.0));
+ } else {
+ ui.add_sized([width, double], Label::new(format!("Your CPU's hashrate is [{}] of the highest benchmark @ {}", human, api.hashrate)));
+ ui.add_sized([width, text], ProgressBar::new(percent / 100.0));
+ }
+ } else {
+ ui.set_enabled(xmrig_alive);
+ ui.add_sized([width, double], Label::new("XMRig is offline. Hashrate cannot be determined."));
+ ui.add_sized([width, text], ProgressBar::new(0.0));
+ }
+ });
+
+ // Comparison
+ ui.group(|ui| {
+ ui.add_sized([width, text], Hyperlink::from_label_and_url("Other CPUs", "https://github.com/hinto-janai/xmrig-benchmarks")).on_hover_text(STATUS_SUBMENU_OTHER_CPUS);
+ });
+
+ egui::ScrollArea::both().max_width(f32::INFINITY).max_height(height).auto_shrink([false; 2]).show_viewport(ui, |ui, _| {
+ let width = width / 20.0;
+ let (cpu, bar, high, average, low, rank, bench) = (
+ width*10.0,
+ width*3.0,
+ width*2.0,
+ width*2.0,
+ width*2.0,
+ width,
+ width*2.0,
+ );
+ ui.group(|ui| {
+ ui.horizontal(|ui| {
+ ui.add_sized([cpu, double], Label::new("CPU")).on_hover_text(STATUS_SUBMENU_OTHER_CPU);
+ ui.separator();
+ ui.add_sized([bar, double], Label::new("Relative")).on_hover_text(STATUS_SUBMENU_OTHER_RELATIVE);
+ ui.separator();
+ ui.add_sized([high, double], Label::new("High")).on_hover_text(STATUS_SUBMENU_OTHER_HIGH);
+ ui.separator();
+ ui.add_sized([average, double], Label::new("Average")).on_hover_text(STATUS_SUBMENU_OTHER_AVERAGE);
+ ui.separator();
+ ui.add_sized([low, double], Label::new("Low")).on_hover_text(STATUS_SUBMENU_OTHER_LOW);
+ ui.separator();
+ ui.add_sized([rank, double], Label::new("Rank")).on_hover_text(STATUS_SUBMENU_OTHER_RANK);
+ ui.separator();
+ ui.add_sized([bench, double], Label::new("Benchmarks")).on_hover_text(STATUS_SUBMENU_OTHER_BENCHMARKS);
+ });
+ });
+
+ for benchmark in benchmarks[1..].iter() {
+ ui.group(|ui| { ui.horizontal(|ui| {
+ ui.add_sized([cpu, text], Label::new(benchmark.cpu.as_str()));
+ ui.separator();
+ ui.add_sized([bar, text], ProgressBar::new(benchmark.percent / 100.0));
+ ui.separator();
+ ui.add_sized([high, text], Label::new(HumanNumber::to_hashrate(benchmark.high).as_str()));
+ ui.separator();
+ ui.add_sized([average, text], Label::new(HumanNumber::to_hashrate(benchmark.average).as_str()));
+ ui.separator();
+ ui.add_sized([low, text], Label::new(HumanNumber::to_hashrate(benchmark.low).as_str()));
+ ui.separator();
+ ui.add_sized([rank, text], Label::new(HumanNumber::from_u16(benchmark.rank).as_str()));
+ ui.separator();
+ ui.add_sized([bench, text], Label::new(HumanNumber::from_u16(benchmark.benchmarks).as_str()));
+ })});
+ }
+ });
}
}
}
diff --git a/src/xmrig.rs b/src/xmrig.rs
index 317614e..6c9fcdc 100644
--- a/src/xmrig.rs
+++ b/src/xmrig.rs
@@ -34,6 +34,7 @@ use regex::Regex;
use log::*;
impl crate::disk::Xmrig {
+ #[inline(always)]
pub fn show(&mut self, pool_vec: &mut Vec<(String, Pool)>, regex: &Regexes, process: &Arc>, api: &Arc>, buffer: &mut String, width: f32, height: f32, _ctx: &egui::Context, ui: &mut egui::Ui) {
let text_edit = height / 25.0;
//---------------------------------------------------------------------------------------------------- [Simple] Console