Skip to content

Commit 30890c2

Browse files
refactor(dfir_rs): use slotmap SecondaryMap for metrics, remove custom slot_vec tags
Replace custom `SecondarySlotVec<SubgraphTag, _>` and `SecondarySlotVec<HandoffTag, _>` in DfirMetrics with `slotmap::SecondaryMap<GraphSubgraphId, _>` and `SecondaryMap<GraphNodeId, _>` from dfir_lang. This eliminates the `slotmap_raw_idx` conversion hack in codegen — keys are now reconstructed via `slotmap::KeyData::from_ffi()` which preserves the full key (including version), not just the raw index. Make `dfir_lang` a non-optional dependency of `dfir_rs` (it was already always compiled via `dfir_macro`). Re-export `dfir_lang` and `slotmap` from `dfir_rs` for use in generated code. Remove `HandoffTag` and `HandoffId` from `scheduled/mod.rs` (no longer needed). Update `hydro_lang/src/telemetry/emf.rs` to use `Debug` formatting for slotmap keys instead of `Display`. Co-authored-by: Infinity 🤖 <infinity@hydro.run>
1 parent fda9dfa commit 30890c2

6 files changed

Lines changed: 33 additions & 34 deletions

File tree

dfir_lang/src/graph/meta_graph.rs

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -822,12 +822,10 @@ impl DfirGraph {
822822
prefix: TokenStream,
823823
diagnostics: &mut Diagnostics,
824824
) -> Result<TokenStream, Diagnostics> {
825-
// Extract the slot index from a slotmap key for use as a runtime metrics key.
826-
// Uses the low 32 bits of `KeyData::as_ffi()` (the idx, ignoring the version).
827-
// TODO(cleanup): When scheduled Dfir is removed, DfirMetrics could use slotmap
828-
// SecondaryMaps directly, eliminating this conversion.
829-
fn slotmap_raw_idx(key: impl Key) -> usize {
830-
(key.data().as_ffi() & 0xFFFF_FFFF) as usize
825+
// Convert a slotmap key to its FFI representation for use in generated code.
826+
// The FFI value can reconstruct the key at runtime via `KeyData::from_ffi`.
827+
fn slotmap_key_ffi(key: impl Key) -> u64 {
828+
key.data().as_ffi()
831829
}
832830

833831
let df = Ident::new(GRAPH, Span::call_site());
@@ -974,7 +972,7 @@ impl DfirGraph {
974972
let mut subgraph_blocks = Vec::new();
975973
{
976974
for &(subgraph_id, subgraph_nodes) in all_subgraphs.iter() {
977-
let sg_metrics_idx = slotmap_raw_idx(subgraph_id);
975+
let sg_metrics_ffi = slotmap_key_ffi(subgraph_id);
978976
let (recv_hoffs, send_hoffs) = &subgraph_handoffs[subgraph_id];
979977

980978
// Generate buffer ident helpers for this subgraph's handoffs.
@@ -1011,7 +1009,7 @@ impl DfirGraph {
10111009
.zip(recv_buf_idents.iter())
10121010
.zip(recv_hoffs.iter())
10131011
.map(|((port_ident, buf_ident), &hoff_id)| {
1014-
let hoff_idx = slotmap_raw_idx(hoff_id);
1012+
let hoff_ffi = slotmap_key_ffi(hoff_id);
10151013
// Use call_site span for internal identifiers to avoid
10161014
// hygiene issues when invoked through declarative macros
10171015
// (e.g. dfir_expect_warnings!). TODO(#2781): define these once.
@@ -1030,7 +1028,7 @@ impl DfirGraph {
10301028
#work_done = true;
10311029
}
10321030
let hoff_metrics = &#metrics.handoffs[
1033-
#root::util::slot_vec::Key::<#root::scheduled::HandoffTag>::from_raw(#hoff_idx)
1031+
#root::slotmap::KeyData::from_ffi(#hoff_ffi).into()
10341032
];
10351033
hoff_metrics.total_items_count.update(|x| x + hoff_len);
10361034
hoff_metrics.curr_items_count.set(hoff_len);
@@ -1436,10 +1434,10 @@ impl DfirGraph {
14361434
.iter()
14371435
.zip(send_buf_idents.iter())
14381436
.map(|(&hoff_id, buf_ident)| {
1439-
let hoff_idx = slotmap_raw_idx(hoff_id);
1437+
let hoff_ffi = slotmap_key_ffi(hoff_id);
14401438
quote! {
14411439
__dfir_metrics.handoffs[
1442-
#root::util::slot_vec::Key::<#root::scheduled::HandoffTag>::from_raw(#hoff_idx)
1440+
#root::slotmap::KeyData::from_ffi(#hoff_ffi).into()
14431441
].curr_items_count.set(#buf_ident.len());
14441442
}
14451443
})
@@ -1455,7 +1453,7 @@ impl DfirGraph {
14551453
};
14561454
{
14571455
let sg_metrics = &__dfir_metrics.subgraphs[
1458-
#root::util::slot_vec::Key::<#root::scheduled::SubgraphTag>::from_raw(#sg_metrics_idx)
1456+
#root::slotmap::KeyData::from_ffi(#sg_metrics_ffi).into()
14591457
];
14601458
#root::scheduled::metrics::InstrumentSubgraph::new(
14611459
#sg_fut_ident, sg_metrics
@@ -1485,19 +1483,19 @@ impl DfirGraph {
14851483
// Generate metrics initialization: one entry per handoff and per subgraph.
14861484
let metrics_init_code = {
14871485
let handoff_inits = handoff_nodes.iter().map(|&(node_id, _)| {
1488-
let idx = slotmap_raw_idx(node_id);
1486+
let ffi = slotmap_key_ffi(node_id);
14891487
quote! {
14901488
dfir_metrics.handoffs.insert(
1491-
#root::util::slot_vec::Key::from_raw(#idx),
1489+
#root::slotmap::KeyData::from_ffi(#ffi).into(),
14921490
::std::default::Default::default(),
14931491
);
14941492
}
14951493
});
14961494
let subgraph_inits = all_subgraphs.iter().map(|&(sg_id, _)| {
1497-
let idx = slotmap_raw_idx(sg_id);
1495+
let ffi = slotmap_key_ffi(sg_id);
14981496
quote! {
14991497
dfir_metrics.subgraphs.insert(
1500-
#root::util::slot_vec::Key::from_raw(#idx),
1498+
#root::slotmap::KeyData::from_ffi(#ffi).into(),
15011499
::std::default::Default::default(),
15021500
);
15031501
}

dfir_rs/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ workspace = true
1414
[features]
1515
default = [ "macros", "debugging", "meta" ]
1616

17-
meta = [ "dep:dfir_lang" ]
17+
meta = [ ]
1818
macros = [ "dfir_macro" ]
1919
dfir_macro = [ "dep:dfir_macro" ]
2020
debugging = [ "dfir_lang/debugging" ]
@@ -28,7 +28,7 @@ name = "kvs_bench"
2828
[dependencies]
2929
bincode = "1.3.1"
3030
bytes = "1.1.0"
31-
dfir_lang = { path = "../dfir_lang", version = "^0.15.0", optional = true }
31+
dfir_lang = { path = "../dfir_lang", version = "^0.15.0" }
3232
dfir_macro = { optional = true, path = "../dfir_macro", version = "^0.15.0" }
3333
dfir_pipes = { path = "../dfir_pipes", version = "^0.0.1" }
3434
futures = "0.3.0"

dfir_rs/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ pub use ::{
2727
#[cfg(feature = "meta")]
2828
#[cfg_attr(docsrs, doc(cfg(feature = "meta")))]
2929
pub use dfir_lang as lang;
30+
pub use dfir_lang;
3031
pub use dfir_pipes::itertools;
32+
pub use slotmap;
3133
pub use variadics::{self, var_args, var_expr, var_type};
3234

3335
/// `#[macro_use]` automagically brings the declarative macro export to the crate-level.

dfir_rs/src/scheduled/metrics.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ use std::pin::Pin;
55
use std::rc::Rc;
66
use std::task::{Context, Poll};
77

8+
use dfir_lang::graph::{GraphNodeId, GraphSubgraphId};
89
use pin_project_lite::pin_project;
10+
use slotmap::SecondaryMap;
911
use web_time::{Duration, Instant};
1012

11-
use super::{HandoffTag, SubgraphTag};
12-
use crate::util::slot_vec::SecondarySlotVec;
13-
1413
/// Metrics for a [`Dfir`](super::context::Dfir) graph instance.
1514
///
1615
/// Call [`Dfir::metrics`](super::context::Dfir::metrics) for reference-counted continually-updated metrics,
@@ -20,9 +19,9 @@ use crate::util::slot_vec::SecondarySlotVec;
2019
#[non_exhaustive]
2120
pub struct DfirMetrics {
2221
/// Per-subgraph metrics.
23-
pub subgraphs: SecondarySlotVec<SubgraphTag, SubgraphMetrics>,
22+
pub subgraphs: SecondaryMap<GraphSubgraphId, SubgraphMetrics>,
2423
/// Per-handoff metrics.
25-
pub handoffs: SecondarySlotVec<HandoffTag, HandoffMetrics>,
24+
pub handoffs: SecondaryMap<GraphNodeId, HandoffMetrics>,
2625
}
2726

2827
impl DfirMetrics {
@@ -222,13 +221,18 @@ where
222221

223222
#[cfg(test)]
224223
mod test {
224+
use dfir_lang::graph::{GraphNodeId, GraphSubgraphId};
225+
use slotmap::SlotMap;
226+
225227
use super::*;
226-
use crate::scheduled::{HandoffId, SubgraphId};
227228

228229
#[test]
229230
fn test_dfir_metrics_intervals() {
230-
let sg_id = SubgraphId::from_raw(0);
231-
let handoff_id = HandoffId::from_raw(0);
231+
// Create slotmaps to generate valid keys.
232+
let mut sg_map: SlotMap<GraphSubgraphId, ()> = SlotMap::with_key();
233+
let mut node_map: SlotMap<GraphNodeId, ()> = SlotMap::with_key();
234+
let sg_id = sg_map.insert(());
235+
let handoff_id = node_map.insert(());
232236

233237
let mut metrics = DfirMetrics::default();
234238
metrics.subgraphs.insert(

dfir_rs/src/scheduled/mod.rs

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,9 @@ pub mod ticks;
1111

1212
/// Tag for [`SubgraphId`].
1313
pub enum SubgraphTag {}
14-
/// A subgraph's ID. Used as a key for metrics tracking.
14+
/// A subgraph's ID.
1515
pub type SubgraphId = Key<SubgraphTag>;
1616

17-
/// Tag for [`HandoffId`].
18-
pub enum HandoffTag {}
19-
/// A handoff's ID. Used as a key for metrics tracking.
20-
pub type HandoffId = Key<HandoffTag>;
21-
2217
/// Tag for [`StateId`].
2318
pub enum StateTag {}
2419
/// A state handle's ID.

hydro_lang/src/telemetry/emf.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ where
184184
]
185185
},
186186
"LocationName": location_name,
187-
"HandoffId": hoff_id.to_string(),
187+
"HandoffId": format!("{:?}", hoff_id),
188188
"CurrItemsCount": hoff_metrics.curr_items_count(),
189189
"TotalItemsCount": hoff_metrics.total_items_count(),
190190
})
@@ -213,7 +213,7 @@ where
213213
]
214214
},
215215
"LocationName": location_name,
216-
"SubgraphId": sg_id.to_string(),
216+
"SubgraphId": format!("{:?}", sg_id),
217217
"TotalRunCount": sg_metrics.total_run_count(),
218218
"TotalPollDuration": sg_metrics.total_poll_duration().as_micros(),
219219
"TotalPollCount": sg_metrics.total_poll_count(),

0 commit comments

Comments
 (0)