]> git.hungrycats.org Git - bees/commitdiff
scan_next: log selection-time refs_created on the plan: line
authorZygo Blaxell <bees@furryterror.org>
Thu, 9 Jul 2026 02:22:22 +0000 (22:22 -0400)
committerZygo Blaxell <bees@furryterror.org>
Sat, 5 Sep 2026 04:04:13 +0000 (00:04 -0400)
The debt on the plan: line showed that fat whole-extent drains are admitted with
a strongly negative debt, i.e. the refs_created * ref_op_cost term is absent even
though ref-op-cost is configured non-zero and wired into both plan orientations.
The remaining unknown is whether refs_created was itself ~0 at selection — the
planner pricing the dst against a stale or reduced reference view — versus the
weight being lost.

Add m_sel_refs_created to DstPlan, captured from the winning plan's cost() at
build time, and log it as "rc" beside the build-time "refs":

  ... [Dddddd] refs 4125 rc 0 debt -6708.0

refs is read fresh at build; rc is what the cost model actually charged.  rc far
below refs on a fat drain pins the cause to a stale/reduced ref count reaching
scan_next_dst_debt at cost time, not the weight or the wiring.

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

index f1f55e60e74b35f186783a0e0d864002fb468a86..7eaf3ce28b718792959a5c88a8f297bcd64f3d4f 100644 (file)
@@ -1718,6 +1718,11 @@ struct DstPlan {
        /// 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;
+       /// refs_created the winning plan's cost() actually carried into the debt
+       /// (dst_ref_count as the cost model saw it, times F).  Logged beside
+       /// m_dst_ref_count (read fresh at build): if this is ~0 while that is large,
+       /// the planner priced the dst against a stale/reduced ref view.
+       uint64_t m_sel_refs_created = 0;
 };
 
 /// Output of the planner: a list of accepted dst plans plus
@@ -2888,6 +2893,7 @@ scan_next_execute_dst_plan(const shared_ptr<BeesContext> &ctx,
                << "s/" << planner_timer.age() << "s {"
                << to_hex(dst.bytenr()) << "} ["
                << bar << "] refs " << dst_plan.m_dst_ref_count
+               << " rc " << dst_plan.m_sel_refs_created
                << " debt " << setprecision(1) << dst_plan.m_space_debt);
 
        return true;
@@ -3128,7 +3134,9 @@ scan_next_build_extent_plan(
        // 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;
+       const auto winner_cost = winner.cost();
+       const double   winner_space_debt   = winner_cost.m_space_debt;
+       const uint64_t winner_refs_created = winner_cost.m_refs_created;
 
        if (auto *pa = dynamic_cast<const BeesStartAsDstPlan *>(&winner)) {
                const auto *impl = pa->impl();
@@ -3152,8 +3160,9 @@ scan_next_build_extent_plan(
                        return out;
                }
 
-               dp->m_space_debt    = winner_space_debt;
-               dp->m_dst_ref_count = start.refs(diag_layer)->size();
+               dp->m_space_debt       = winner_space_debt;
+               dp->m_sel_refs_created = winner_refs_created;
+               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());
@@ -3182,7 +3191,8 @@ 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_space_debt       = winner_space_debt;
+                                       dp->m_sel_refs_created = winner_refs_created;
                                        dp->m_dst_ref_count =
                                                entry.m_candidate.refs(diag_layer)->size();
                                        out.m_total_cost += dp->m_cost;