]> git.hungrycats.org Git - bees/commitdiff
scan_next: log dst ref count and plan debt on the plan: line
authorZygo Blaxell <bees@furryterror.org>
Thu, 9 Jul 2026 00:48:20 +0000 (20:48 -0400)
committerZygo Blaxell <bees@furryterror.org>
Sat, 5 Sep 2026 04:04:13 +0000 (00:04 -0400)
The plan: line reported the op counts and timing of an accepted plan but not
why it was chosen, so a re-canonicalization drain (a high-ref extent selected as
a dst) was invisible without inferring ref counts from the dst redirect lines.

Capture two diagnostics on DstPlan at build time โ€” the winning plan's signed
space-debt (the value that beat the other orientations and the do-nothing floor)
and this dst's reference count as the planner saw it, pre-execution โ€” and append
them to the plan: line:

  plan: 128K 1d0c0p0u ... {0x...} [Dddddd] refs 9957 debt -12345.6

refs is read at build time, before the dedupe moves the dst's references, so it
is the decision-time count, not the post-execution remainder.  A whole-extent
drain of a fat extent now shows its ref count and the debt that admitted it
directly: if that debt is negative on a high refs value, the cost model
mispriced the drain; if positive, the plan won a ballot it should have lost.

Assisted-by: Claude-Code:claude-opus-4-8
src/bees-scan-next.cc

index f2abf99db3484b513f5b8b4db45b768f31252a31..f1f55e60e74b35f186783a0e0d864002fb468a86 100644 (file)
@@ -1710,6 +1710,14 @@ struct DstPlan {
        BeesExtent m_dst;
        BeesExtent m_plan_tree;
        PlanCost m_cost;
+       /// Diagnostics captured at build time (pre-execution): the winning plan's
+       /// signed space-debt (do-nothing-plan.md ยง4) that beat the other
+       /// orientations and the null floor, and this dst's reference count as the
+       /// planner saw it.  Logged on the "plan:" line so a chosen plan's debt and
+       /// the fatness of the extent it touched are visible without re-deriving
+       /// them โ€” e.g. spotting a high-ref extent drained as a dst.
+       double   m_space_debt   = 0.0;
+       uint64_t m_dst_ref_count = 0;
 };
 
 /// Output of the planner: a list of accepted dst plans plus
@@ -2879,7 +2887,8 @@ scan_next_execute_dst_plan(const shared_ptr<BeesContext> &ctx,
                << fixed << setprecision(3) << timer.age()
                << "s/" << planner_timer.age() << "s {"
                << to_hex(dst.bytenr()) << "} ["
-               << bar << "]");
+               << bar << "] refs " << dst_plan.m_dst_ref_count
+               << " debt " << setprecision(1) << dst_plan.m_space_debt);
 
        return true;
 }
@@ -3115,6 +3124,12 @@ scan_next_build_extent_plan(
        ExtentPlan out;
        out.m_start_survived = true;
 
+       // Winning plan's signed debt and this layer, for the per-dst diagnostics
+       // recorded below (logged on the "plan:" line).  refs() reads here are the
+       // planner's cached, pre-execution values.
+       auto &diag_layer = Borrower::current().layer();
+       const double winner_space_debt = winner.cost().m_space_debt;
+
        if (auto *pa = dynamic_cast<const BeesStartAsDstPlan *>(&winner)) {
                const auto *impl = pa->impl();
                if (!impl) {
@@ -3137,6 +3152,8 @@ scan_next_build_extent_plan(
                        return out;
                }
 
+               dp->m_space_debt    = winner_space_debt;
+               dp->m_dst_ref_count = start.refs(diag_layer)->size();
                out.m_total_cost = dp->m_cost;
                for (const auto &g : groups) {
                        out.m_src_bytenrs.insert(g.m_extent.bytenr());
@@ -3165,6 +3182,9 @@ scan_next_build_extent_plan(
                                auto dp = scan_next_try_build_dst_plan(ctx,
                                        entry.m_candidate, sources, policy, force);
                                if (dp) {
+                                       dp->m_space_debt    = winner_space_debt;
+                                       dp->m_dst_ref_count =
+                                               entry.m_candidate.refs(diag_layer)->size();
                                        out.m_total_cost += dp->m_cost;
                                        out.m_dst_plans.push_back(std::move(*dp));
                                }