output bot metrics data in tidepool with "-M" flag
This commit is contained in:
parent
52d339747a
commit
9067459eb1
|
@ -42,12 +42,12 @@ pub struct CliArgs {
|
|||
|
||||
#[derive(Clone, Debug, Args)]
|
||||
pub struct OutputDataArgs {
|
||||
/// Generate profiling data in the output.
|
||||
#[arg(short = 'P', long)]
|
||||
pub profile: bool,
|
||||
/// Generate the full list of moves in the output.
|
||||
#[arg(short = 'L', long)]
|
||||
pub list_moves: bool,
|
||||
/// Generate algorithm metrics in the output.
|
||||
#[arg(short = 'M', long)]
|
||||
pub metrics: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Args)]
|
||||
|
|
|
@ -341,6 +341,7 @@ fn run_simulation(
|
|||
exit_early: &atomic::AtomicBool,
|
||||
) {
|
||||
let mut moves = data_args.list_moves.then(Vec::new);
|
||||
let mut metrics = data_args.metrics.then(Vec::new);
|
||||
let seed = seed.unwrap_or_else(|| rand::thread_rng().next_u64());
|
||||
let weights = eval::Weights::default();
|
||||
|
||||
|
@ -363,6 +364,9 @@ fn run_simulation(
|
|||
sim.matrix(),
|
||||
mino::Queue::new(sim.queue().hold(), sim.queue().next()),
|
||||
);
|
||||
if data_args.metrics {
|
||||
bot.start_instrumenting();
|
||||
}
|
||||
|
||||
while bot.iterations() < config.bot.iters {
|
||||
let gas = std::cmp::min(50_000, config.bot.iters - bot.iterations());
|
||||
|
@ -385,6 +389,9 @@ fn run_simulation(
|
|||
if let Some(moves) = moves.as_mut() {
|
||||
moves.push(output::Move { placement })
|
||||
}
|
||||
if let Some(metrics) = metrics.as_mut() {
|
||||
metrics.push(bot.metrics().unwrap());
|
||||
}
|
||||
|
||||
let status = Status {
|
||||
lines_left: sim.lines_left(),
|
||||
|
@ -396,17 +403,13 @@ fn run_simulation(
|
|||
}
|
||||
}
|
||||
|
||||
let profile = data_args.profile.then(|| output::Profile {
|
||||
time: Instant::now() - time_start,
|
||||
});
|
||||
|
||||
let output = output::Output {
|
||||
seed,
|
||||
cleared: config.game.goal - sim.lines_left(),
|
||||
pieces: sim.pieces(),
|
||||
config: config.game,
|
||||
moves,
|
||||
profile,
|
||||
metrics,
|
||||
};
|
||||
if tx.send(Msg::Output(id, output.into())).is_err() {
|
||||
tracing::debug!("nobody received output id={id}");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use fish::bot::Metrics;
|
||||
use mino::srs::Piece;
|
||||
use serde::Serialize;
|
||||
use std::time::Duration;
|
||||
|
||||
use crate::config::GameConfig;
|
||||
|
||||
|
@ -11,10 +11,13 @@ pub struct Output {
|
|||
pub config: GameConfig,
|
||||
pub pieces: usize,
|
||||
pub cleared: usize,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub moves: Option<Vec<Move>>,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
pub profile: Option<Profile>,
|
||||
#[serde(
|
||||
serialize_with = "ser::metrics",
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
pub metrics: Option<Vec<Metrics>>,
|
||||
}
|
||||
|
||||
impl Output {
|
||||
|
@ -30,16 +33,6 @@ pub struct Move {
|
|||
// TODO: spin?
|
||||
}
|
||||
|
||||
#[derive(Serialize, Debug)]
|
||||
pub struct Profile {
|
||||
#[serde(serialize_with = "ser::seconds")]
|
||||
pub time: Duration,
|
||||
// TODO: pps mean/variance
|
||||
// TODO: timing stats for specific functions/routines
|
||||
// TODO: stats info about top <N> evaluations
|
||||
// TODO: histograms about selected nodes
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct SummaryStats<T: Copy> {
|
||||
count: usize,
|
||||
|
@ -167,11 +160,56 @@ mod ser {
|
|||
.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn seconds<S>(dur: &Duration, serializer: S) -> Result<S::Ok, S::Error>
|
||||
pub fn metrics<S>(metrics: &Option<Vec<Metrics>>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
dur.as_secs_f64().serialize(serializer)
|
||||
#[derive(Serialize)]
|
||||
struct MoveMetrics {
|
||||
start: NodeMetrics,
|
||||
end: NodeMetrics,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct NodeMetrics {
|
||||
features: Vec<i32>,
|
||||
heuristic: i32,
|
||||
#[serde(flatten)]
|
||||
rating: RatingVariant,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
iteration: Option<u32>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
#[serde(untagged)]
|
||||
enum RatingVariant {
|
||||
NotApplicable,
|
||||
Rating { rating: i32 },
|
||||
Solution { solution: i32 },
|
||||
}
|
||||
|
||||
metrics
|
||||
.iter()
|
||||
.flat_map(|m| m.iter())
|
||||
.map(|m| MoveMetrics {
|
||||
start: NodeMetrics {
|
||||
features: m.start_features.1.to_vec(),
|
||||
heuristic: m.start_heuristic,
|
||||
rating: RatingVariant::NotApplicable,
|
||||
iteration: None,
|
||||
},
|
||||
end: NodeMetrics {
|
||||
features: m.end_features.1.to_vec(),
|
||||
heuristic: m.end_heuristic,
|
||||
rating: match m.end_rating {
|
||||
(false, v) => RatingVariant::Rating { rating: v },
|
||||
(true, v) => RatingVariant::Solution { solution: -v },
|
||||
},
|
||||
iteration: Some(m.end_iteration),
|
||||
},
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.serialize(serializer)
|
||||
}
|
||||
|
||||
pub fn summary_stats<S, T>(stats: &SummaryStats<T>, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
|
Loading…
Reference in New Issue