From 8fec6707a0a7358a43f1b54ba5d7c6451bcf3d81 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 1 Apr 2020 17:53:33 -0400 Subject: [PATCH 1/2] Permit reordering LeafNode fields Regardless of the order of the fields in the LeafNode, it is still guaranteed to be a prefix of the InternalNode as that is still repr(C). Removing the repr(C) annotation on the leaf node may permit the compiler to reorder the fields in a more optimal fashion. --- src/liballoc/collections/btree/node.rs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 6ebb98c42cd4..710ec8434d9f 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -45,7 +45,6 @@ pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; /// The underlying representation of leaf nodes. -#[repr(C)] struct LeafNode { /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. /// This either points to an actual node or is null. @@ -57,9 +56,6 @@ struct LeafNode { parent_idx: MaybeUninit, /// The number of keys and values this node stores. - /// - /// This next to `parent_idx` to encourage the compiler to join `len` and - /// `parent_idx` into the same 32-bit word, reducing space overhead. len: u16, /// The arrays storing the actual data of the node. Only the first `len` elements of each From 1c71a72c8875c86a715b52145c0cf792019fdc8b Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 1 Apr 2020 18:41:54 -0400 Subject: [PATCH 2/2] Try alternate ordering which in theory packs keys closer to edge pointers --- src/liballoc/collections/btree/node.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/liballoc/collections/btree/node.rs b/src/liballoc/collections/btree/node.rs index 710ec8434d9f..0eea8b39c9fd 100644 --- a/src/liballoc/collections/btree/node.rs +++ b/src/liballoc/collections/btree/node.rs @@ -45,6 +45,9 @@ pub const MIN_LEN: usize = B - 1; pub const CAPACITY: usize = 2 * B - 1; /// The underlying representation of leaf nodes. +// The layout is fixed so that we have tighter control over field ordering. +// We're okay with wasting some memory in trade-off for better cache locality. +#[repr(C)] struct LeafNode { /// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`. /// This either points to an actual node or is null. @@ -55,13 +58,19 @@ struct LeafNode { /// This is only guaranteed to be initialized when `parent` is non-null. parent_idx: MaybeUninit, + /// The arrays storing the values of the node. Only the first `len` elements of each + /// array are initialized and valid. + vals: [MaybeUninit; CAPACITY], + /// The number of keys and values this node stores. + // This is right before the keys because we frequently access both. len: u16, /// The arrays storing the actual data of the node. Only the first `len` elements of each /// array are initialized and valid. + // This is intentionally last so as to both be a) close to `len` and b) + // close to the edges in the internal node case. keys: [MaybeUninit; CAPACITY], - vals: [MaybeUninit; CAPACITY], } impl LeafNode {