Move start_time to ClientStatsManager (#2948)

* Move start_time to ClientStatsManager

* Remove unnessary &self

* Make clippy happy

* Make clippy happy
This commit is contained in:
EvianZhang 2025-02-07 23:39:39 +08:00 committed by GitHub
parent c03dfd9daf
commit ce01f4a427
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 88 additions and 253 deletions

View File

@ -330,7 +330,7 @@ where
self.staterestorer.reset();
self.staterestorer.save(&(
state,
self.inner.monitor.start_time(),
self.inner.client_stats_manager.start_time(),
self.inner.client_stats_manager.client_stats(),
))
}
@ -435,7 +435,7 @@ where
/// Launch the simple restarting manager.
/// This `EventManager` is simple and single threaded,
/// but can still used shared maps to recover from crashes and timeouts.
pub fn launch(mut monitor: MT, shmem_provider: &mut SP) -> Result<(Option<S>, Self), Error>
pub fn launch(monitor: MT, shmem_provider: &mut SP) -> Result<(Option<S>, Self), Error>
where
S: DeserializeOwned + Serialize + HasSolutions<I>,
MT: Debug,
@ -546,8 +546,8 @@ where
staterestorer.reset();
// reload the state of the monitor to display the correct stats after restarts
monitor.set_start_time(start_time);
let mut this = SimpleRestartingEventManager::launched(monitor, staterestorer);
this.inner.client_stats_manager.set_start_time(start_time);
this.inner
.client_stats_manager
.update_all_client_stats(clients_stats);

View File

@ -32,16 +32,6 @@ impl<M> Monitor for OnDiskTomlMonitor<M>
where
M: Monitor,
{
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.base.start_time()
}
/// Set creation time
fn set_start_time(&mut self, time: Duration) {
self.base.set_start_time(time);
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -66,7 +56,7 @@ objectives = {}
executions = {}
exec_sec = {}
",
format_duration_hms(&(cur_time - self.start_time())),
format_duration_hms(&(cur_time - client_stats_manager.start_time())),
client_stats_manager.client_stats_count(),
client_stats_manager.corpus_size(),
client_stats_manager.objective_size(),
@ -193,14 +183,6 @@ where
F: FnMut(&mut M) -> bool,
M: Monitor,
{
fn start_time(&self) -> Duration {
self.base.start_time()
}
fn set_start_time(&mut self, time: Duration) {
self.base.set_start_time(time);
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -215,7 +197,7 @@ where
.expect("Failed to open logging file");
let line = json!({
"run_time": current_time() - self.base.start_time(),
"run_time": current_time() - client_stats_manager.start_time(),
"clients": client_stats_manager.client_stats_count(),
"corpus": client_stats_manager.corpus_size(),
"objectives": client_stats_manager.objective_size(),

View File

@ -38,14 +38,6 @@ impl<M> Monitor for OnDiskJsonAggregateMonitor<M>
where
M: Monitor,
{
fn set_start_time(&mut self, time: Duration) {
self.base.set_start_time(time);
}
fn start_time(&self) -> Duration {
self.base.start_time()
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -68,7 +60,7 @@ where
.expect("Failed to open JSON logging file");
let mut json_value = json!({
"run_time": (cur_time - self.start_time()).as_secs(),
"run_time": (cur_time - client_stats_manager.start_time()).as_secs(),
"clients": client_stats_manager.client_stats_count(),
"corpus": client_stats_manager.corpus_size(),
"objectives": client_stats_manager.objective_size(),

View File

@ -34,12 +34,6 @@ use crate::statistics::manager::ClientStatsManager;
/// The monitor trait keeps track of all the client's monitor, and offers methods to display them.
pub trait Monitor {
/// Creation time
fn start_time(&self) -> Duration;
/// Set creation time
fn set_start_time(&mut self, time: Duration);
/// Show the monitor to the user
fn display(
&mut self,
@ -52,21 +46,9 @@ pub trait Monitor {
/// Monitor that print exactly nothing.
/// Not good for debugging, very good for speed.
#[derive(Debug, Clone)]
pub struct NopMonitor {
start_time: Duration,
}
pub struct NopMonitor {}
impl Monitor for NopMonitor {
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
/// Time this fuzzing run stated
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
#[inline]
fn display(
&mut self,
@ -81,9 +63,7 @@ impl NopMonitor {
/// Create new [`NopMonitor`]
#[must_use]
pub fn new() -> Self {
Self {
start_time: current_time(),
}
Self {}
}
}
@ -95,19 +75,8 @@ impl Default for NopMonitor {
/// Tracking monitor during fuzzing that just prints to `stdout`.
#[cfg(feature = "std")]
#[derive(Debug, Clone)]
pub struct SimplePrintingMonitor {
start_time: Duration,
}
#[cfg(feature = "std")]
impl Default for SimplePrintingMonitor {
fn default() -> Self {
Self {
start_time: current_time(),
}
}
}
#[derive(Debug, Clone, Default)]
pub struct SimplePrintingMonitor {}
#[cfg(feature = "std")]
impl SimplePrintingMonitor {
@ -120,16 +89,6 @@ impl SimplePrintingMonitor {
#[cfg(feature = "std")]
impl Monitor for SimplePrintingMonitor {
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
/// Time this fuzzing run stated
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -146,7 +105,7 @@ impl Monitor for SimplePrintingMonitor {
"[{} #{}] run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}, {}",
event_msg,
sender_id.0,
format_duration_hms(&(current_time() - self.start_time)),
format_duration_hms(&(current_time() - client_stats_manager.start_time())),
client_stats_manager.client_stats_count(),
client_stats_manager.corpus_size(),
client_stats_manager.objective_size(),
@ -177,7 +136,6 @@ where
F: FnMut(&str),
{
print_fn: F,
start_time: Duration,
print_user_monitor: bool,
}
@ -186,9 +144,7 @@ where
F: FnMut(&str),
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SimpleMonitor")
.field("start_time", &self.start_time)
.finish_non_exhaustive()
f.debug_struct("SimpleMonitor").finish_non_exhaustive()
}
}
@ -196,16 +152,6 @@ impl<F> Monitor for SimpleMonitor<F>
where
F: FnMut(&str),
{
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
/// Set creation time
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -216,7 +162,7 @@ where
"[{} #{}] run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
event_msg,
sender_id.0,
format_duration_hms(&(current_time() - self.start_time)),
format_duration_hms(&(current_time() - client_stats_manager.start_time())),
client_stats_manager.client_stats_count(),
client_stats_manager.corpus_size(),
client_stats_manager.objective_size(),
@ -259,25 +205,23 @@ where
pub fn new(print_fn: F) -> Self {
Self {
print_fn,
start_time: current_time(),
print_user_monitor: false,
}
}
/// Creates the monitor with a given `start_time`.
pub fn with_time(print_fn: F, start_time: Duration) -> Self {
Self {
print_fn,
start_time,
print_user_monitor: false,
}
#[deprecated(
since = "0.16.0",
note = "Please use new to create. start_time is useless here."
)]
pub fn with_time(print_fn: F, _start_time: Duration) -> Self {
Self::new(print_fn)
}
/// Creates the monitor that also prints the user monitor
pub fn with_user_monitor(print_fn: F) -> Self {
Self {
print_fn,
start_time: current_time(),
print_user_monitor: true,
}
}
@ -320,34 +264,16 @@ macro_rules! mark_feedback_time {
pub struct CombinedMonitor<A, B> {
first: A,
second: B,
start_time: Duration,
}
impl<A: Monitor, B: Monitor> CombinedMonitor<A, B> {
/// Create a new combined monitor
pub fn new(mut first: A, mut second: B) -> Self {
let start_time = current_time();
first.set_start_time(start_time);
second.set_start_time(start_time);
Self {
first,
second,
start_time,
}
pub fn new(first: A, second: B) -> Self {
Self { first, second }
}
}
impl<A: Monitor, B: Monitor> Monitor for CombinedMonitor<A, B> {
fn start_time(&self) -> Duration {
self.start_time
}
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
self.first.set_start_time(time);
self.second.set_start_time(time);
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,

View File

@ -17,7 +17,6 @@ where
F: FnMut(&str),
{
print_fn: F,
start_time: Duration,
}
impl<F> Debug for MultiMonitor<F>
@ -25,9 +24,7 @@ where
F: FnMut(&str),
{
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
f.debug_struct("MultiMonitor")
.field("start_time", &self.start_time)
.finish_non_exhaustive()
f.debug_struct("MultiMonitor").finish_non_exhaustive()
}
}
@ -35,16 +32,6 @@ impl<F> Monitor for MultiMonitor<F>
where
F: FnMut(&str),
{
/// Set creation time
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -61,7 +48,7 @@ where
let mut global_fmt = format!(
"[{}] (GLOBAL) run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
head,
format_duration_hms(&(current_time() - self.start_time)),
format_duration_hms(&(current_time() - client_stats_manager.start_time())),
client_stats_manager.client_stats_count(),
client_stats_manager.corpus_size(),
client_stats_manager.objective_size(),
@ -116,17 +103,15 @@ where
{
/// Creates the monitor, using the `current_time` as `start_time`.
pub fn new(print_fn: F) -> Self {
Self {
print_fn,
start_time: current_time(),
}
Self { print_fn }
}
/// Creates the monitor with a given `start_time`.
pub fn with_time(print_fn: F, start_time: Duration) -> Self {
Self {
print_fn,
start_time,
}
#[deprecated(
since = "0.16.0",
note = "Please use new to create. start_time is useless here."
)]
pub fn with_time(print_fn: F, _start_time: Duration) -> Self {
Self::new(print_fn)
}
}

View File

@ -71,7 +71,6 @@ where
F: FnMut(&str),
{
print_fn: F,
start_time: Duration,
prometheus_global_stats: PrometheusStats, // global prometheus metrics
prometheus_client_stats: PrometheusStats, // per-client prometheus metrics
}
@ -81,9 +80,7 @@ where
F: FnMut(&str),
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("PrometheusMonitor")
.field("start_time", &self.start_time)
.finish_non_exhaustive()
f.debug_struct("PrometheusMonitor").finish_non_exhaustive()
}
}
@ -91,16 +88,6 @@ impl<F> Monitor for PrometheusMonitor<F>
where
F: FnMut(&str),
{
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
/// Set creation time
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
fn display(
&mut self,
client_stats_manager: &mut ClientStatsManager,
@ -152,7 +139,7 @@ where
})
.set(execs_per_sec);
let run_time = (current_time() - self.start_time).as_secs();
let run_time = (current_time() - client_stats_manager.start_time()).as_secs();
self.prometheus_global_stats
.runtime
.get_or_create(&Labels {
@ -177,7 +164,7 @@ where
let mut global_fmt = format!(
"[Prometheus] [{} #GLOBAL] run time: {}, clients: {}, corpus: {}, objectives: {}, executions: {}, exec/sec: {}",
event_msg,
format_duration_hms(&(current_time() - self.start_time)),
format_duration_hms(&(current_time() - client_stats_manager.start_time())),
client_stats_manager.client_stats_count(),
client_stats_manager.corpus_size(),
client_stats_manager.objective_size(),
@ -357,33 +344,17 @@ where
});
Self {
print_fn,
start_time: current_time(),
prometheus_global_stats,
prometheus_client_stats,
}
}
/// Creates the monitor with a given `start_time`.
pub fn with_time(listener: String, print_fn: F, start_time: Duration) -> Self {
let prometheus_global_stats = PrometheusStats::default();
let prometheus_global_stats_clone = prometheus_global_stats.clone();
let prometheus_client_stats = PrometheusStats::default();
let prometheus_client_stats_clone = prometheus_client_stats.clone();
thread::spawn(move || {
block_on(serve_metrics(
listener,
prometheus_global_stats_clone,
prometheus_client_stats_clone,
))
.map_err(|err| log::error!("{err:?}"))
.ok();
});
Self {
print_fn,
start_time,
prometheus_global_stats,
prometheus_client_stats,
}
#[deprecated(
since = "0.16.0",
note = "Please use new to create. start_time is useless here."
)]
pub fn with_time(listener: String, print_fn: F, _start_time: Duration) -> Self {
Self::new(listener, print_fn)
}
}

View File

@ -58,10 +58,6 @@ pub struct TuiMonitorConfig {
/// A version string to show for this (optional)
#[builder(default_code = r#""default".to_string()"#, setter(into))]
pub version: String,
/// Creates the monitor with an explicit `start_time`.
/// If nothings was set, this will use [`current_time`] instead.
#[builder(default_code = "current_time()")]
pub start_time: Duration,
/// Enables unicode TUI graphics, Looks better but may interfere with old terminals.
#[builder(default = true)]
pub enhanced_graphics: bool,
@ -393,8 +389,6 @@ impl TuiContext {
#[derive(Debug, Clone)]
pub struct TuiMonitor {
pub(crate) context: Arc<RwLock<TuiContext>>,
start_time: Duration,
}
impl From<TuiMonitorConfig> for TuiMonitor {
@ -402,22 +396,12 @@ impl From<TuiMonitorConfig> for TuiMonitor {
fn from(builder: TuiMonitorConfig) -> Self {
Self::with_time(
TuiUi::with_version(builder.title, builder.version, builder.enhanced_graphics),
builder.start_time,
current_time(),
)
}
}
impl Monitor for TuiMonitor {
/// Time this fuzzing run stated
fn start_time(&self) -> Duration {
self.start_time
}
/// Set creation time
fn set_start_time(&mut self, time: Duration) {
self.start_time = time;
}
#[expect(clippy::cast_sign_loss)]
fn display(
&mut self,
@ -431,8 +415,8 @@ impl Monitor for TuiMonitor {
// TODO implement floating-point support for TimedStat
let execsec = client_stats_manager.execs_per_sec() as u64;
let totalexec = client_stats_manager.total_execs();
let run_time = cur_time - self.start_time;
let total_process_timing = self.process_timing(client_stats_manager);
let run_time = cur_time - client_stats_manager.start_time();
let total_process_timing = get_process_timing(client_stats_manager);
let mut ctx = self.context.write().unwrap();
ctx.total_process_timing = total_process_timing;
@ -441,6 +425,7 @@ impl Monitor for TuiMonitor {
ctx.objective_size_timed
.add(run_time, client_stats_manager.objective_size());
ctx.execs_per_sec_timed.add(run_time, execsec);
ctx.start_time = client_stats_manager.start_time();
ctx.total_execs = totalexec;
ctx.clients_num = client_stats_manager.client_stats().len();
ctx.total_map_density = get_map_density(client_stats_manager);
@ -565,13 +550,11 @@ impl TuiMonitor {
io::stdout,
);
}
Self {
context,
start_time,
}
Self { context }
}
}
fn process_timing(&self, client_stats_manager: &mut ClientStatsManager) -> ProcessTiming {
fn get_process_timing(client_stats_manager: &mut ClientStatsManager) -> ProcessTiming {
let mut total_process_timing = ProcessTiming::new();
total_process_timing.exec_speed = client_stats_manager.execs_per_sec_pretty();
if client_stats_manager.client_stats().len() > 1 {
@ -585,15 +568,15 @@ impl TuiMonitor {
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_path_time > client_stats_manager.start_time() {
total_process_timing.last_new_entry = new_path_time - client_stats_manager.start_time();
}
if new_objectives_time > self.start_time {
total_process_timing.last_saved_solution = new_objectives_time - self.start_time;
if new_objectives_time > client_stats_manager.start_time() {
total_process_timing.last_saved_solution =
new_objectives_time - client_stats_manager.start_time();
}
}
total_process_timing
}
}
fn get_map_density(client_stats_manager: &ClientStatsManager) -> String {

View File

@ -17,6 +17,7 @@ pub struct ClientStatsManager {
///
/// This map is updated by event manager, and is read by monitors to display user-defined stats.
pub(super) cached_aggregated_user_stats: HashMap<String, UserStatsValue>,
start_time: Duration,
}
impl ClientStatsManager {
@ -26,9 +27,21 @@ impl ClientStatsManager {
Self {
client_stats: vec![],
cached_aggregated_user_stats: HashMap::new(),
start_time: current_time(),
}
}
/// 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 all client stats
#[must_use]
pub fn client_stats(&self) -> &[ClientStats] {

View File

@ -1,14 +1,7 @@
use core::ffi::c_int;
#[cfg(unix)]
use std::io::{stderr, stdout, Write};
use std::{
fmt::Debug,
fs::File,
net::TcpListener,
os::fd::AsRawFd,
str::FromStr,
time::{SystemTime, UNIX_EPOCH},
};
use std::{fmt::Debug, fs::File, net::TcpListener, os::fd::AsRawFd, str::FromStr};
use libafl::{
corpus::Corpus,
@ -208,16 +201,10 @@ pub fn fuzz(
.build();
fuzz_many_forking(options, harness, shmem_provider, forks, monitor)
} else if forks == 1 {
let monitor = MultiMonitor::with_time(
create_monitor_closure(),
SystemTime::now().duration_since(UNIX_EPOCH).unwrap(),
);
let monitor = MultiMonitor::new(create_monitor_closure());
fuzz_single_forking(options, harness, shmem_provider, monitor)
} else {
let monitor = MultiMonitor::with_time(
create_monitor_closure(),
SystemTime::now().duration_since(UNIX_EPOCH).unwrap(),
);
let monitor = MultiMonitor::new(create_monitor_closure());
fuzz_many_forking(options, harness, shmem_provider, forks, monitor)
}
} else if options.tui() {

View File

@ -4,7 +4,6 @@ use std::{
fs::{rename, File},
io::Write,
os::fd::{AsRawFd, FromRawFd},
time::{SystemTime, UNIX_EPOCH},
};
use libafl::{
@ -57,15 +56,12 @@ pub fn merge(
let new_fd = libc::dup(std::io::stderr().as_raw_fd());
File::from_raw_fd(new_fd)
};
let monitor = MultiMonitor::with_time(
move |s| {
let monitor = MultiMonitor::new(move |s| {
#[cfg(unix)]
writeln!(stderr, "{s}").expect("Could not write to stderr???");
#[cfg(not(unix))]
eprintln!("{s}");
},
SystemTime::now().duration_since(UNIX_EPOCH).unwrap(),
);
});
let (state, mut mgr): (
Option<StdState<_, _, _, _>>,