Move statistics to monitors/stats (#2962)
* Move statistics back to monitors/stats * More fun * more stats * more
This commit is contained in:
parent
e5ae6c361f
commit
c62c6a7ecc
@ -1,4 +1,5 @@
|
||||
# 0.15.0 -> 0.16.0
|
||||
|
||||
- `EventManager` is refactored to avoid calling function from `Fuzzer`, thus we do not evaluate testcases in `EventManager` anymore.
|
||||
- Now we have `EventReceiver` in `events` module, and `EventProessor` in `fuzzer` module.
|
||||
- `EventReceiver` is responsible for receiving testcases and delegates its evaluation to `EventProcessor`.
|
||||
@ -6,13 +7,13 @@
|
||||
- Since we don't evaluate testcases in the `EventManager` anymore. `on_fire` and `post_exec` have been deleted from `EventManagerHook`.
|
||||
- Similarly `pre_exec` has been renamed to `pre_receive`.
|
||||
- `AsanModule` now uses a `builder()` method for constructing its instances.
|
||||
- `Monitor` is refactored. Most statistics have been extracted into an individual module `statistics` at crate root, and `Monitor` is kept as display only.
|
||||
- `Monitor` is refactored. Most statistics have been extracted into an individual `stats` module under `monitors`.
|
||||
- There is a `ClientStatsManager` to manage client statistics, and is owned by `EventManager`. Most of previous `Monitor`'s trait methods have been moved to the `ClientStatsManager`.
|
||||
- `user_monitor` has been renamed to `user_stats`, and its structure definitions have been moved to `statistics` module as well.
|
||||
- `introspection_monitor` has been renamed to `introspection_stats`, and perf-related structure definitions have been renamed and moved to `statistics` module as well.
|
||||
- `user_monitor` has been renamed to `user_stats`, `introspection_monitor` has been renamed to `introspection_stats`, perf-related structure definitions have been renamed, and all were moved to the `stats` module.
|
||||
- `OnDiskTomlMonitor`, `OnDiskJsonMonitor`, `OnDiskJsonAggregateMonitor` are now no longer takes a base monitor to wrap. If you want to use multiple monitors together, use `libafl::combine_monitor!`.
|
||||
|
||||
# 0.14.1 -> 0.15.0
|
||||
|
||||
- `MmapShMem::new` and `MmapShMemProvider::new_shmem_with_id` now take `AsRef<Path>` instead of a byte array for the filename/id.
|
||||
- The closure passed to a `DumpToDiskStage` now provides the `Testcase` instead of just the `Input`.
|
||||
- `StatsStage` is deleted, and it is superceded by `AflStatsStage`
|
||||
@ -35,8 +36,10 @@
|
||||
- Related: removed `hash_simple` from `MapObserver`
|
||||
|
||||
# 0.14.0 -> 0.15.0
|
||||
|
||||
- Removed `with_observers` from `Executor` trait.
|
||||
- `MmapShMemProvider::new_shmem_persistent` has been removed in favour of `MmapShMem::persist`. You probably want to do something like this: `let shmem = MmapShMemProvider::new()?.new_shmem(size)?.persist()?;`
|
||||
|
||||
# Pre 0.9 -> 0.9
|
||||
|
||||
- [Migrating from LibAFL <0.9 to 0.9](https://aflplus.plus/libafl-book/design/migration-0.9.html)
|
@ -3,9 +3,10 @@
|
||||
|
||||
use std::{thread::sleep, time::Duration};
|
||||
|
||||
use libafl::{
|
||||
monitors::{tui::TuiMonitor, Monitor},
|
||||
statistics::{manager::ClientStatsManager, ClientStats},
|
||||
use libafl::monitors::{
|
||||
stats::{manager::ClientStatsManager, ClientStats},
|
||||
tui::TuiMonitor,
|
||||
Monitor,
|
||||
};
|
||||
use libafl_bolts::ClientId;
|
||||
|
||||
|
@ -18,10 +18,10 @@ use crate::{
|
||||
events::{Event, EventFirer, LogSeverity},
|
||||
executors::{Executor, HasObservers},
|
||||
inputs::Input,
|
||||
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::{LenTimeMulTestcaseScore, RemovableScheduler, Scheduler, TestcaseScore},
|
||||
state::{HasCorpus, HasExecutions},
|
||||
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
Error, HasMetadata, HasScheduler,
|
||||
};
|
||||
|
||||
|
@ -14,8 +14,7 @@ use serde::de::DeserializeOwned;
|
||||
use crate::events::llmp::COMPRESS_THRESHOLD;
|
||||
use crate::{
|
||||
events::{llmp::LLMP_TAG_EVENT_TO_BOTH, BrokerEventResult, Event},
|
||||
monitors::Monitor,
|
||||
statistics::manager::ClientStatsManager,
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
Error,
|
||||
};
|
||||
|
||||
|
@ -47,8 +47,8 @@ use uuid::Uuid;
|
||||
use crate::{
|
||||
executors::ExitKind,
|
||||
inputs::Input,
|
||||
monitors::stats::UserStats,
|
||||
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor},
|
||||
statistics::user_stats::UserStats,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
@ -107,7 +107,7 @@ pub struct EventManagerId(
|
||||
#[cfg(all(unix, feature = "std", feature = "multi_machine"))]
|
||||
use crate::events::multi_machine::NodeId;
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::ClientPerfStats;
|
||||
use crate::monitors::stats::ClientPerfStats;
|
||||
use crate::{observers::TimeObserver, stages::HasCurrentStageId};
|
||||
|
||||
/// The log event severity
|
||||
|
@ -31,14 +31,16 @@ use crate::{
|
||||
Event, EventFirer, EventManagerId, EventReceiver, EventRestarter, HasEventManagerId,
|
||||
SendExiting,
|
||||
},
|
||||
monitors::Monitor,
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
stages::HasCurrentStageId,
|
||||
state::{HasExecutions, HasLastReportTime, MaybeHasClientPerfMonitor, Stoppable},
|
||||
statistics::manager::ClientStatsManager,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
#[cfg(feature = "std")]
|
||||
use crate::{monitors::SimplePrintingMonitor, state::HasSolutions, statistics::ClientStats};
|
||||
use crate::{
|
||||
monitors::{stats::ClientStats, SimplePrintingMonitor},
|
||||
state::HasSolutions,
|
||||
};
|
||||
|
||||
/// The llmp connection from the actual fuzzer to the process supervising it
|
||||
const _ENV_FUZZER_SENDER: &str = "_AFL_ENV_FUZZER_SENDER";
|
||||
|
@ -47,13 +47,12 @@ use crate::{
|
||||
EventManagerId, EventReceiver, EventRestarter, HasEventManagerId, ProgressReporter,
|
||||
},
|
||||
inputs::Input,
|
||||
monitors::Monitor,
|
||||
monitors::{stats::ClientStatsManager, Monitor},
|
||||
stages::HasCurrentStageId,
|
||||
state::{
|
||||
HasCurrentTestcase, HasExecutions, HasImported, HasLastReportTime, HasSolutions,
|
||||
MaybeHasClientPerfMonitor, Stoppable,
|
||||
},
|
||||
statistics::manager::ClientStatsManager,
|
||||
Error, HasMetadata,
|
||||
};
|
||||
|
||||
|
@ -25,8 +25,8 @@ use crate::{
|
||||
events::{Event, EventFirer},
|
||||
executors::ExitKind,
|
||||
feedbacks::{Feedback, HasObserverHandle, StateInitializer},
|
||||
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
observers::{CanTrack, MapObserver},
|
||||
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
Error, HasMetadata, HasNamedMetadata,
|
||||
};
|
||||
|
||||
|
@ -11,7 +11,7 @@ use libafl_bolts::{current_time, tuples::MatchName};
|
||||
use serde::{de::DeserializeOwned, Serialize};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, Testcase},
|
||||
events::{
|
||||
|
@ -79,7 +79,6 @@ pub mod observers;
|
||||
pub mod schedulers;
|
||||
pub mod stages;
|
||||
pub mod state;
|
||||
pub mod statistics;
|
||||
|
||||
pub use fuzzer::*;
|
||||
pub use libafl_bolts::{nonzero, Error};
|
||||
@ -91,8 +90,7 @@ pub mod prelude {
|
||||
|
||||
pub use super::{
|
||||
corpus::*, events::*, executors::*, feedbacks::*, fuzzer::*, generators::*, inputs::*,
|
||||
monitors::*, mutators::*, observers::*, schedulers::*, stages::*, state::*, statistics::*,
|
||||
*,
|
||||
monitors::*, mutators::*, observers::*, schedulers::*, stages::*, state::*, *,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ use std::{
|
||||
use libafl_bolts::{current_time, ClientId};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager};
|
||||
use crate::monitors::{stats::ClientStatsManager, Monitor};
|
||||
|
||||
/// Wrap a monitor and log the current state of the monitor into a Toml file.
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -9,7 +9,7 @@ use std::{fs::OpenOptions, io::Write, path::PathBuf};
|
||||
use libafl_bolts::{current_time, ClientId};
|
||||
use serde_json::json;
|
||||
|
||||
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager};
|
||||
use crate::monitors::{stats::ClientStatsManager, Monitor};
|
||||
|
||||
/// A monitor that logs aggregated stats to a JSON file.
|
||||
#[derive(Clone)]
|
||||
|
@ -3,6 +3,8 @@
|
||||
pub mod multi;
|
||||
pub use multi::MultiMonitor;
|
||||
|
||||
pub mod stats;
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
pub mod disk;
|
||||
#[cfg(feature = "std")]
|
||||
@ -30,7 +32,7 @@ use libafl_bolts::ClientId;
|
||||
#[cfg(all(feature = "prometheus_monitor", feature = "std"))]
|
||||
pub use prometheus::PrometheusMonitor;
|
||||
|
||||
use crate::statistics::manager::ClientStatsManager;
|
||||
use crate::monitors::stats::ClientStatsManager;
|
||||
|
||||
/// The monitor trait keeps track of all the client's monitor, and offers methods to display them.
|
||||
pub trait Monitor {
|
||||
|
@ -8,7 +8,7 @@ use core::{
|
||||
|
||||
use libafl_bolts::{current_time, ClientId};
|
||||
|
||||
use crate::{monitors::Monitor, statistics::manager::ClientStatsManager};
|
||||
use crate::monitors::{stats::ClientStatsManager, Monitor};
|
||||
|
||||
/// Tracking monitor during fuzzing and display both per-client and cumulative info.
|
||||
#[derive(Clone)]
|
||||
|
@ -47,9 +47,9 @@ use prometheus_client::{
|
||||
// using tide for the HTTP server library (fast, async, simple)
|
||||
use tide::Request;
|
||||
|
||||
use crate::{
|
||||
monitors::Monitor,
|
||||
statistics::{manager::ClientStatsManager, user_stats::UserStatsValue},
|
||||
use crate::monitors::{
|
||||
stats::{manager::ClientStatsManager, user_stats::UserStatsValue},
|
||||
Monitor,
|
||||
};
|
||||
|
||||
/// Prometheus metrics for global and each client.
|
||||
|
@ -13,12 +13,13 @@ use core::time::Duration;
|
||||
|
||||
use hashbrown::HashMap;
|
||||
use libafl_bolts::current_time;
|
||||
pub use manager::ClientStatsManager;
|
||||
#[cfg(feature = "introspection")]
|
||||
use perf_stats::ClientPerfStats;
|
||||
pub use perf_stats::{ClientPerfStats, PerfFeature};
|
||||
use serde::{Deserialize, Serialize};
|
||||
#[cfg(feature = "std")]
|
||||
use serde_json::Value;
|
||||
use user_stats::UserStats;
|
||||
pub use user_stats::{AggregatorOps, UserStats, UserStatsValue};
|
||||
|
||||
#[cfg(feature = "afl_exec_sec")]
|
||||
const CLIENT_STATS_TIME_WINDOW_SECS: u64 = 5; // 5 seconds
|
||||
@ -107,13 +108,17 @@ impl ProcessTiming {
|
||||
}
|
||||
|
||||
/// The geometry of a single data point
|
||||
#[expect(missing_docs)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ItemGeometry {
|
||||
/// Pending entries
|
||||
pub pending: u64,
|
||||
/// Favored pending entries
|
||||
pub pend_fav: u64,
|
||||
/// How much entries we found
|
||||
pub own_finds: u64,
|
||||
/// How much entries were imported
|
||||
pub imported: u64,
|
||||
/// The stability, stringified
|
||||
pub stability: String,
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ impl fmt::Display for UserStatsValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match &self {
|
||||
UserStatsValue::Number(n) => write!(f, "{n}"),
|
||||
UserStatsValue::Float(n) => write!(f, "{}", crate::statistics::prettify_float(*n)),
|
||||
UserStatsValue::Float(n) => write!(f, "{}", crate::monitors::stats::prettify_float(*n)),
|
||||
UserStatsValue::Percent(n) => write!(f, "{:.3}%", n * 100.0),
|
||||
UserStatsValue::String(s) => write!(f, "{s}"),
|
||||
UserStatsValue::Ratio(a, b) => {
|
@ -27,13 +27,13 @@ use ratatui::{backend::CrosstermBackend, Terminal};
|
||||
use typed_builder::TypedBuilder;
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::{ClientPerfStats, PerfFeature};
|
||||
use crate::{
|
||||
monitors::Monitor,
|
||||
statistics::{
|
||||
use crate::monitors::stats::perf_stats::{ClientPerfStats, PerfFeature};
|
||||
use crate::monitors::{
|
||||
stats::{
|
||||
manager::ClientStatsManager, user_stats::UserStats, ClientStats, ItemGeometry,
|
||||
ProcessTiming,
|
||||
},
|
||||
Monitor,
|
||||
};
|
||||
|
||||
#[expect(missing_docs)]
|
||||
@ -207,19 +207,26 @@ impl PerfTuiContext {
|
||||
}
|
||||
|
||||
/// The context for a single client tracked in this [`TuiMonitor`]
|
||||
#[expect(missing_docs)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct ClientTuiContext {
|
||||
/// The corpus size
|
||||
pub corpus: u64,
|
||||
/// Amount of objectives
|
||||
pub objectives: u64,
|
||||
/// Amount of executions
|
||||
pub executions: u64,
|
||||
/// Float value formatted as String
|
||||
pub map_density: String,
|
||||
|
||||
/// How many cycles have been done.
|
||||
/// Roughly: every testcase has been scheduled once, but highly fuzzer-specific.
|
||||
pub cycles_done: u64,
|
||||
|
||||
/// Times for processing
|
||||
pub process_timing: ProcessTiming,
|
||||
/// The individual entry geometry
|
||||
pub item_geometry: ItemGeometry,
|
||||
/// Extra fuzzer-specific stats
|
||||
pub user_stats: HashMap<Cow<'static, str>, UserStats>,
|
||||
}
|
||||
|
||||
@ -241,8 +248,8 @@ impl ClientTuiContext {
|
||||
}
|
||||
|
||||
/// The [`TuiContext`] for this [`TuiMonitor`]
|
||||
#[expect(missing_docs)]
|
||||
#[derive(Debug, Clone)]
|
||||
#[expect(missing_docs)]
|
||||
pub struct TuiContext {
|
||||
pub graphs: Vec<String>,
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
//! The UI-specific parts of [`super::TuiMonitor`]
|
||||
use alloc::{string::ToString, vec::Vec};
|
||||
use std::{
|
||||
cmp::{max, min},
|
||||
@ -93,6 +94,7 @@ impl TuiUi {
|
||||
}
|
||||
}
|
||||
|
||||
/// Draw the current TUI context
|
||||
pub fn draw(&mut self, f: &mut Frame, app: &Arc<RwLock<TuiContext>>) {
|
||||
self.clients = app.read().unwrap().clients_num;
|
||||
|
||||
|
@ -26,12 +26,12 @@ use crate::{
|
||||
corpus::{Corpus, HasCurrentCorpusId, SchedulerTestcaseMetadata, Testcase},
|
||||
events::{Event, EventFirer},
|
||||
executors::HasObservers,
|
||||
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
mutators::Tokens,
|
||||
observers::MapObserver,
|
||||
schedulers::{minimizer::IsFavoredMetadata, HasQueueCycles},
|
||||
stages::{calibrate::UnstableEntriesMetadata, Stage},
|
||||
state::{HasCorpus, HasExecutions, HasImported, HasStartTime, Stoppable},
|
||||
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
std::string::ToString,
|
||||
Error, HasMetadata, HasNamedMetadata, HasScheduler,
|
||||
};
|
||||
|
@ -19,11 +19,11 @@ use crate::{
|
||||
feedbacks::{map::MapFeedbackMetadata, HasObserverHandle},
|
||||
fuzzer::Evaluator,
|
||||
inputs::Input,
|
||||
monitors::stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
observers::{MapObserver, ObserversTuple},
|
||||
schedulers::powersched::SchedulerMetadata,
|
||||
stages::{RetryCountRestartHelper, Stage},
|
||||
state::{HasCorpus, HasCurrentTestcase, HasExecutions},
|
||||
statistics::user_stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
Error, HasMetadata, HasNamedMetadata,
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ use libafl_bolts::{
|
||||
};
|
||||
|
||||
#[cfg(all(feature = "concolic_mutation", feature = "introspection"))]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::HasCurrentCorpusId,
|
||||
executors::{Executor, HasObservers},
|
||||
|
@ -12,7 +12,7 @@ use libafl_bolts::{
|
||||
};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::{Corpus, HasCurrentCorpusId},
|
||||
executors::{Executor, HasObservers},
|
||||
|
@ -10,7 +10,7 @@ use core::{marker::PhantomData, num::NonZeroUsize};
|
||||
use libafl_bolts::{rands::Rand, Named};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasCurrentCorpusId, Testcase},
|
||||
fuzzer::Evaluator,
|
||||
|
@ -9,7 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
use libafl_bolts::Named;
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::HasCurrentCorpusId,
|
||||
executors::{Executor, HasObservers},
|
||||
|
@ -12,7 +12,7 @@ use serde::Serialize;
|
||||
|
||||
use super::{PushStage, PushStageHelper, PushStageSharedState};
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId},
|
||||
events::{EventFirer, ProgressReporter},
|
||||
|
@ -17,7 +17,7 @@ use serde::Serialize;
|
||||
#[cfg(feature = "track_hit_feedbacks")]
|
||||
use crate::feedbacks::premature_last_result_err;
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::{Corpus, HasCurrentCorpusId, Testcase},
|
||||
events::EventFirer,
|
||||
|
@ -9,7 +9,7 @@ use core::{fmt::Debug, marker::PhantomData};
|
||||
use libafl_bolts::Named;
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
corpus::HasCurrentCorpusId,
|
||||
executors::{Executor, HasObservers, ShadowExecutor},
|
||||
|
@ -7,7 +7,7 @@ use libafl_bolts::{current_time, impl_serdeany, rands::Rand};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::PerfFeature;
|
||||
use crate::monitors::stats::PerfFeature;
|
||||
use crate::{
|
||||
mark_feature_time,
|
||||
mutators::{MutationResult, Mutator},
|
||||
|
@ -27,7 +27,7 @@ mod stack;
|
||||
pub use stack::StageStack;
|
||||
|
||||
#[cfg(feature = "introspection")]
|
||||
use crate::statistics::perf_stats::ClientPerfStats;
|
||||
use crate::monitors::stats::ClientPerfStats;
|
||||
use crate::{
|
||||
corpus::{Corpus, CorpusId, HasCurrentCorpusId, HasTestcase, InMemoryCorpus, Testcase},
|
||||
events::{Event, EventFirer, LogSeverity},
|
||||
|
@ -1,173 +0,0 @@
|
||||
//! Global statistics available for Monitors to use
|
||||
|
||||
use alloc::string::{String, ToString};
|
||||
use core::{cmp, time::Duration};
|
||||
|
||||
use libafl_bolts::{current_time, format_duration_hms};
|
||||
#[cfg(feature = "std")]
|
||||
use serde_json::Value;
|
||||
|
||||
use super::ClientStatsManager;
|
||||
use crate::statistics::ProcessTiming;
|
||||
#[cfg(feature = "std")]
|
||||
use crate::statistics::{
|
||||
user_stats::{AggregatorOps, UserStats, UserStatsValue},
|
||||
ItemGeometry,
|
||||
};
|
||||
|
||||
impl ClientStatsManager {
|
||||
/// Time this fuzzing run stated
|
||||
#[must_use]
|
||||
pub fn start_time(&self) -> Duration {
|
||||
self.start_time
|
||||
}
|
||||
|
||||
/// Time this fuzzing run stated
|
||||
pub fn set_start_time(&mut self, time: Duration) {
|
||||
self.start_time = time;
|
||||
}
|
||||
|
||||
/// Get global stats.
|
||||
///
|
||||
/// This global stats will be cached until the underlined client stats are modified.
|
||||
pub fn global_stats(&mut self) -> &GlobalStats {
|
||||
let global_stats = self.cached_global_stats.get_or_insert_with(|| GlobalStats {
|
||||
run_time: Duration::ZERO,
|
||||
run_time_pretty: String::new(),
|
||||
client_stats_count: self
|
||||
.client_stats
|
||||
.iter()
|
||||
.filter(|client| client.enabled)
|
||||
.count(),
|
||||
corpus_size: self
|
||||
.client_stats
|
||||
.iter()
|
||||
.fold(0_u64, |acc, x| acc + x.corpus_size),
|
||||
objective_size: self
|
||||
.client_stats
|
||||
.iter()
|
||||
.fold(0_u64, |acc, x| acc + x.objective_size),
|
||||
total_execs: self
|
||||
.client_stats
|
||||
.iter()
|
||||
.fold(0_u64, |acc, x| acc + x.executions),
|
||||
execs_per_sec: 0.0,
|
||||
execs_per_sec_pretty: String::new(),
|
||||
});
|
||||
|
||||
// Time-related data are always re-computed, since it is related with current time.
|
||||
let cur_time = current_time();
|
||||
global_stats.run_time = cur_time - self.start_time;
|
||||
global_stats.run_time_pretty = format_duration_hms(&global_stats.run_time);
|
||||
global_stats.execs_per_sec = self
|
||||
.client_stats
|
||||
.iter_mut()
|
||||
.fold(0.0, |acc, x| acc + x.execs_per_sec(cur_time));
|
||||
global_stats
|
||||
.execs_per_sec_pretty
|
||||
.push_str(&super::super::prettify_float(global_stats.execs_per_sec));
|
||||
|
||||
global_stats
|
||||
}
|
||||
|
||||
/// Get process timing. `execs_per_sec_pretty` could be retrieved from `GlobalStats`.
|
||||
#[must_use]
|
||||
pub fn process_timing(&self, execs_per_sec_pretty: String) -> ProcessTiming {
|
||||
let mut total_process_timing = ProcessTiming::new();
|
||||
total_process_timing.exec_speed = execs_per_sec_pretty;
|
||||
if self.client_stats().len() > 1 {
|
||||
let mut new_path_time = Duration::default();
|
||||
let mut new_objectives_time = Duration::default();
|
||||
for client in self.client_stats().iter().filter(|client| client.enabled()) {
|
||||
new_path_time = client.last_corpus_time().max(new_path_time);
|
||||
new_objectives_time = client.last_objective_time().max(new_objectives_time);
|
||||
}
|
||||
if new_path_time > self.start_time() {
|
||||
total_process_timing.last_new_entry = new_path_time - self.start_time();
|
||||
}
|
||||
if new_objectives_time > self.start_time() {
|
||||
total_process_timing.last_saved_solution = new_objectives_time - self.start_time();
|
||||
}
|
||||
}
|
||||
total_process_timing
|
||||
}
|
||||
|
||||
/// Get map density
|
||||
#[must_use]
|
||||
pub fn map_density(&self) -> String {
|
||||
self.client_stats()
|
||||
.iter()
|
||||
.filter(|client| client.enabled())
|
||||
.filter_map(|client| client.get_user_stats("edges"))
|
||||
.map(ToString::to_string)
|
||||
.fold("0%".to_string(), cmp::max)
|
||||
}
|
||||
|
||||
/// Get item geometry
|
||||
#[cfg(feature = "std")]
|
||||
#[must_use]
|
||||
pub fn item_geometry(&self) -> ItemGeometry {
|
||||
let mut total_item_geometry = ItemGeometry::new();
|
||||
if self.client_stats().len() < 2 {
|
||||
return total_item_geometry;
|
||||
}
|
||||
let mut ratio_a: u64 = 0;
|
||||
let mut ratio_b: u64 = 0;
|
||||
for client in self.client_stats().iter().filter(|client| client.enabled()) {
|
||||
let afl_stats = client
|
||||
.get_user_stats("AflStats")
|
||||
.map_or("None".to_string(), ToString::to_string);
|
||||
let stability = client.get_user_stats("stability").map_or(
|
||||
UserStats::new(UserStatsValue::Ratio(0, 100), AggregatorOps::Avg),
|
||||
Clone::clone,
|
||||
);
|
||||
|
||||
if afl_stats != "None" {
|
||||
let default_json = serde_json::json!({
|
||||
"pending": 0,
|
||||
"pend_fav": 0,
|
||||
"imported": 0,
|
||||
"own_finds": 0,
|
||||
});
|
||||
let afl_stats_json: Value =
|
||||
serde_json::from_str(afl_stats.as_str()).unwrap_or(default_json);
|
||||
total_item_geometry.pending +=
|
||||
afl_stats_json["pending"].as_u64().unwrap_or_default();
|
||||
total_item_geometry.pend_fav +=
|
||||
afl_stats_json["pend_fav"].as_u64().unwrap_or_default();
|
||||
total_item_geometry.own_finds +=
|
||||
afl_stats_json["own_finds"].as_u64().unwrap_or_default();
|
||||
total_item_geometry.imported +=
|
||||
afl_stats_json["imported"].as_u64().unwrap_or_default();
|
||||
}
|
||||
|
||||
if let UserStatsValue::Ratio(a, b) = stability.value() {
|
||||
ratio_a += a;
|
||||
ratio_b += b;
|
||||
}
|
||||
}
|
||||
total_item_geometry.stability = format!("{}%", ratio_a * 100 / ratio_b);
|
||||
total_item_geometry
|
||||
}
|
||||
}
|
||||
|
||||
/// Global statistics which aggregates client stats.
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalStats {
|
||||
/// Run time since started
|
||||
pub run_time: Duration,
|
||||
/// Run time since started
|
||||
pub run_time_pretty: String,
|
||||
/// Count the number of enabled client stats
|
||||
pub client_stats_count: usize,
|
||||
/// Amount of elements in the corpus (combined for all children)
|
||||
pub corpus_size: u64,
|
||||
/// Amount of elements in the objectives (combined for all children)
|
||||
pub objective_size: u64,
|
||||
/// Total executions
|
||||
pub total_execs: u64,
|
||||
/// Executions per second
|
||||
pub execs_per_sec: f64,
|
||||
/// Executions per second
|
||||
pub execs_per_sec_pretty: String,
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user