X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Frouting%2Frouter.rs;h=75bd47fb91b5798a1d580a4343b1059b1c764fb9;hb=694e70f5b57ba6cb8392e3de98a301bd0de23b87;hp=2def88c1ca456607d8cec51078d4c8218ed3cba4;hpb=b2cf4df798994b00f0899757fd830e954d4dd500;p=rust-lightning diff --git a/lightning/src/routing/router.rs b/lightning/src/routing/router.rs index 2def88c1..75bd47fb 100644 --- a/lightning/src/routing/router.rs +++ b/lightning/src/routing/router.rs @@ -1481,6 +1481,34 @@ fn iter_equal(mut iter_a: I1, mut iter_b: I2) } } +#[cfg(target_feature = "sse")] +#[inline(always)] +unsafe fn do_prefetch(ptr: *const T) { + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64::*; + #[cfg(target_arch = "x86")] + use core::arch::x86::*; + _mm_prefetch(ptr as *const i8, _MM_HINT_T0); +} + +#[cfg(not(target_feature = "sse"))] +#[inline(always)] +unsafe fn do_prefetch(_: *const T) {} + +#[inline(always)] +fn prefetch_first_byte(t: &T) { + // While X86's prefetch should be safe even on an invalid memory address (the ISA says + // "PREFETCHh instruction is merely a hint and does not affect program behavior"), we take + // an extra step towards safety here by requiring the pointer be valid (as Rust references + // are always valid when accessed). + // + // Note that a pointer in Rust could be to a zero sized type, in which case the pointer could + // be NULL (or some other bogus value), so we explicitly check for that here. + if ::core::mem::size_of::() != 0 { + unsafe { do_prefetch(t) } + } +} + /// It's useful to keep track of the hops associated with the fees required to use them, /// so that we can choose cheaper paths (as per Dijkstra's algorithm). /// Fee values should be updated only in the context of the whole path, see update_value_and_recompute_fees. @@ -2494,6 +2522,13 @@ where L::Target: Logger { if !features.requires_unknown_bits() { for chan_id in $node.channels.iter() { let chan = network_channels.get(chan_id).unwrap(); + // Calling chan.as_directed_to, below, will require access to memory two + // cache lines away from chan.features (in the form of `one_to_two` or + // `two_to_one`, depending on our direction). Thus, while we're looking at + // feature flags, go ahead and prefetch that memory, reducing the price we + // pay for it later. + prefetch_first_byte(&chan.one_to_two); + prefetch_first_byte(&chan.two_to_one); if !chan.features.requires_unknown_bits() { if let Some((directed_channel, source)) = chan.as_directed_to(&$node_id) { if first_hops.is_none() || *source != our_node_id {