Skip to content

Commit 1a84c62

Browse files
committed
Somewhat optimize the generic Features::requires_unknown_bits
It turns out we spend several percent of our routefinding time just checking if nodes and channels require unknown features byte-by-byte. While the cost is almost certainly dominated by the memory read latency, avoiding doing the checks byte-by-byte should reduce the branch count slightly, which may reduce the overhead.
1 parent aef2a35 commit 1a84c62

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

lightning/src/ln/features.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -763,16 +763,23 @@ impl<T: sealed::Context> Features<T> {
763763
pub fn requires_unknown_bits(&self) -> bool {
764764
// Bitwise AND-ing with all even bits set except for known features will select required
765765
// unknown features.
766-
let byte_count = T::KNOWN_FEATURE_MASK.len();
767-
self.flags.iter().enumerate().any(|(i, &byte)| {
768-
let required_features = 0b01_01_01_01;
769-
let unknown_features = if i < byte_count {
770-
!T::KNOWN_FEATURE_MASK[i]
771-
} else {
772-
0b11_11_11_11
773-
};
774-
(byte & (required_features & unknown_features)) != 0
775-
})
766+
let mut known_chunks = T::KNOWN_FEATURE_MASK.chunks(8);
767+
for chunk in self.flags.chunks(8) {
768+
let mut flag_bytes = [0; 8];
769+
flag_bytes[..chunk.len()].copy_from_slice(&chunk);
770+
let flag_int = u64::from_le_bytes(flag_bytes);
771+
772+
let known_chunk = known_chunks.next().unwrap_or(&[0; 0]);
773+
let mut known_bytes = [0; 8];
774+
known_bytes[..known_chunk.len()].copy_from_slice(&known_chunk);
775+
let known_int = u64::from_le_bytes(known_bytes);
776+
777+
const REQ_MASK: u64 = 0x55555555_55555555;
778+
if flag_int & (REQ_MASK & !known_int) != 0 {
779+
return true;
780+
}
781+
}
782+
false
776783
}
777784

778785
pub(crate) fn supports_unknown_bits(&self) -> bool {

0 commit comments

Comments
 (0)