mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 11:41:02 +00:00
Improve complexity of CompactAssignments::unique_targets (#8314)
* Improve complexity of CompactAssignments::unique_targets Original implementation was O(n**2). Current impl is O(n log n). Avoided the original proposed mitigation because it does not retain the de-duplicating property present in the original implementation. This implementation does a little more work, but retains that property. * Explicitly choose sp_std Vec and BTreeSet Ensures that the macro still works if someone uses it in a context in which sp_std is not imported or is renamed. * explicitly use sp_std vectors throughout compact macro
This commit is contained in:
committed by
GitHub
parent
2586d55754
commit
23b32e7543
@@ -125,7 +125,7 @@ pub(crate) fn into_impl(count: usize, per_thing: syn::Type) -> TokenStream2 {
|
|||||||
let target = target_at(*t_idx).or_invalid_index()?;
|
let target = target_at(*t_idx).or_invalid_index()?;
|
||||||
Ok((target, *p))
|
Ok((target, *p))
|
||||||
})
|
})
|
||||||
.collect::<Result<Vec<(A, #per_thing)>, _npos::Error>>()?;
|
.collect::<Result<_npos::sp_std::prelude::Vec<(A, #per_thing)>, _npos::Error>>()?;
|
||||||
|
|
||||||
if sum >= #per_thing::one() {
|
if sum >= #per_thing::one() {
|
||||||
return Err(_npos::Error::CompactStakeOverflow);
|
return Err(_npos::Error::CompactStakeOverflow);
|
||||||
|
|||||||
@@ -49,14 +49,14 @@ fn decode_impl(
|
|||||||
quote! {
|
quote! {
|
||||||
let #name =
|
let #name =
|
||||||
<
|
<
|
||||||
Vec<(_npos::codec::Compact<#voter_type>, _npos::codec::Compact<#target_type>)>
|
_npos::sp_std::prelude::Vec<(_npos::codec::Compact<#voter_type>, _npos::codec::Compact<#target_type>)>
|
||||||
as
|
as
|
||||||
_npos::codec::Decode
|
_npos::codec::Decode
|
||||||
>::decode(value)?;
|
>::decode(value)?;
|
||||||
let #name = #name
|
let #name = #name
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(v, t)| (v.0, t.0))
|
.map(|(v, t)| (v.0, t.0))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ fn decode_impl(
|
|||||||
quote! {
|
quote! {
|
||||||
let #name =
|
let #name =
|
||||||
<
|
<
|
||||||
Vec<(
|
_npos::sp_std::prelude::Vec<(
|
||||||
_npos::codec::Compact<#voter_type>,
|
_npos::codec::Compact<#voter_type>,
|
||||||
(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>),
|
(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>),
|
||||||
_npos::codec::Compact<#target_type>,
|
_npos::codec::Compact<#target_type>,
|
||||||
@@ -76,7 +76,7 @@ fn decode_impl(
|
|||||||
let #name = #name
|
let #name = #name
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(v, (t1, w), t2)| (v.0, (t1.0, w.0), t2.0))
|
.map(|(v, (t1, w), t2)| (v.0, (t1.0, w.0), t2.0))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,7 +90,7 @@ fn decode_impl(
|
|||||||
quote! {
|
quote! {
|
||||||
let #name =
|
let #name =
|
||||||
<
|
<
|
||||||
Vec<(
|
_npos::sp_std::prelude::Vec<(
|
||||||
_npos::codec::Compact<#voter_type>,
|
_npos::codec::Compact<#voter_type>,
|
||||||
[(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>); #c-1],
|
[(_npos::codec::Compact<#target_type>, _npos::codec::Compact<#weight_type>); #c-1],
|
||||||
_npos::codec::Compact<#target_type>,
|
_npos::codec::Compact<#target_type>,
|
||||||
@@ -104,7 +104,7 @@ fn decode_impl(
|
|||||||
[ #inner_impl ],
|
[ #inner_impl ],
|
||||||
t_last.0,
|
t_last.0,
|
||||||
))
|
))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
}
|
}
|
||||||
}).collect::<TokenStream2>();
|
}).collect::<TokenStream2>();
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ fn encode_impl(ident: syn::Ident, count: usize) -> TokenStream2 {
|
|||||||
_npos::codec::Compact(v.clone()),
|
_npos::codec::Compact(v.clone()),
|
||||||
_npos::codec::Compact(t.clone()),
|
_npos::codec::Compact(t.clone()),
|
||||||
))
|
))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
#name.encode_to(&mut r);
|
#name.encode_to(&mut r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -160,7 +160,7 @@ fn encode_impl(ident: syn::Ident, count: usize) -> TokenStream2 {
|
|||||||
),
|
),
|
||||||
_npos::codec::Compact(t2.clone()),
|
_npos::codec::Compact(t2.clone()),
|
||||||
))
|
))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
#name.encode_to(&mut r);
|
#name.encode_to(&mut r);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -184,14 +184,14 @@ fn encode_impl(ident: syn::Ident, count: usize) -> TokenStream2 {
|
|||||||
[ #inners_compact_array ],
|
[ #inners_compact_array ],
|
||||||
_npos::codec::Compact(t_last.clone()),
|
_npos::codec::Compact(t_last.clone()),
|
||||||
))
|
))
|
||||||
.collect::<Vec<_>>();
|
.collect::<_npos::sp_std::prelude::Vec<_>>();
|
||||||
#name.encode_to(&mut r);
|
#name.encode_to(&mut r);
|
||||||
}
|
}
|
||||||
}).collect::<TokenStream2>();
|
}).collect::<TokenStream2>();
|
||||||
|
|
||||||
quote!(
|
quote!(
|
||||||
impl _npos::codec::Encode for #ident {
|
impl _npos::codec::Encode for #ident {
|
||||||
fn encode(&self) -> Vec<u8> {
|
fn encode(&self) -> _npos::sp_std::prelude::Vec<u8> {
|
||||||
let mut r = vec![];
|
let mut r = vec![];
|
||||||
#encode_impl_single
|
#encode_impl_single
|
||||||
#encode_impl_double
|
#encode_impl_double
|
||||||
|
|||||||
@@ -119,14 +119,14 @@ fn struct_def(
|
|||||||
let name = field_name_for(1);
|
let name = field_name_for(1);
|
||||||
// NOTE: we use the visibility of the struct for the fields as well.. could be made better.
|
// NOTE: we use the visibility of the struct for the fields as well.. could be made better.
|
||||||
quote!(
|
quote!(
|
||||||
#vis #name: Vec<(#voter_type, #target_type)>,
|
#vis #name: _npos::sp_std::prelude::Vec<(#voter_type, #target_type)>,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let doubles = {
|
let doubles = {
|
||||||
let name = field_name_for(2);
|
let name = field_name_for(2);
|
||||||
quote!(
|
quote!(
|
||||||
#vis #name: Vec<(#voter_type, (#target_type, #weight_type), #target_type)>,
|
#vis #name: _npos::sp_std::prelude::Vec<(#voter_type, (#target_type, #weight_type), #target_type)>,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ fn struct_def(
|
|||||||
let field_name = field_name_for(c);
|
let field_name = field_name_for(c);
|
||||||
let array_len = c - 1;
|
let array_len = c - 1;
|
||||||
quote!(
|
quote!(
|
||||||
#vis #field_name: Vec<(
|
#vis #field_name: _npos::sp_std::prelude::Vec<(
|
||||||
#voter_type,
|
#voter_type,
|
||||||
[(#target_type, #weight_type); #array_len],
|
[(#target_type, #weight_type); #array_len],
|
||||||
#target_type
|
#target_type
|
||||||
@@ -194,20 +194,19 @@ fn struct_def(
|
|||||||
all_edges
|
all_edges
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unique_targets(&self) -> Vec<Self::Target> {
|
fn unique_targets(&self) -> _npos::sp_std::prelude::Vec<Self::Target> {
|
||||||
// NOTE: this implementation returns the targets sorted, but we don't use it yet per
|
// NOTE: this implementation returns the targets sorted, but we don't use it yet per
|
||||||
// se, nor is the API enforcing it.
|
// se, nor is the API enforcing it.
|
||||||
let mut all_targets: Vec<Self::Target> = Vec::with_capacity(self.average_edge_count());
|
use _npos::sp_std::collections::btree_set::BTreeSet;
|
||||||
|
|
||||||
|
let mut all_targets: BTreeSet<Self::Target> = BTreeSet::new();
|
||||||
let mut maybe_insert_target = |t: Self::Target| {
|
let mut maybe_insert_target = |t: Self::Target| {
|
||||||
match all_targets.binary_search(&t) {
|
all_targets.insert(t);
|
||||||
Ok(_) => (),
|
|
||||||
Err(pos) => all_targets.insert(pos, t)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#unique_targets_impl
|
#unique_targets_impl
|
||||||
|
|
||||||
all_targets
|
all_targets.into_iter().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn remove_voter(&mut self, to_remove: Self::Voter) -> bool {
|
fn remove_voter(&mut self, to_remove: Self::Voter) -> bool {
|
||||||
@@ -216,7 +215,7 @@ fn struct_def(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn from_assignment<FV, FT, A>(
|
fn from_assignment<FV, FT, A>(
|
||||||
assignments: Vec<_npos::Assignment<A, #weight_type>>,
|
assignments: _npos::sp_std::prelude::Vec<_npos::Assignment<A, #weight_type>>,
|
||||||
index_of_voter: FV,
|
index_of_voter: FV,
|
||||||
index_of_target: FT,
|
index_of_target: FT,
|
||||||
) -> Result<Self, _npos::Error>
|
) -> Result<Self, _npos::Error>
|
||||||
@@ -243,8 +242,8 @@ fn struct_def(
|
|||||||
self,
|
self,
|
||||||
voter_at: impl Fn(Self::Voter) -> Option<A>,
|
voter_at: impl Fn(Self::Voter) -> Option<A>,
|
||||||
target_at: impl Fn(Self::Target) -> Option<A>,
|
target_at: impl Fn(Self::Target) -> Option<A>,
|
||||||
) -> Result<Vec<_npos::Assignment<A, #weight_type>>, _npos::Error> {
|
) -> Result<_npos::sp_std::prelude::Vec<_npos::Assignment<A, #weight_type>>, _npos::Error> {
|
||||||
let mut assignments: Vec<_npos::Assignment<A, #weight_type>> = Default::default();
|
let mut assignments: _npos::sp_std::prelude::Vec<_npos::Assignment<A, #weight_type>> = Default::default();
|
||||||
#into_impl
|
#into_impl
|
||||||
Ok(assignments)
|
Ok(assignments)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,6 +119,8 @@ pub use pjr::*;
|
|||||||
pub use codec;
|
pub use codec;
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub use sp_arithmetic;
|
pub use sp_arithmetic;
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub use sp_std;
|
||||||
|
|
||||||
/// Simple Extension trait to easily convert `None` from index closures to `Err`.
|
/// Simple Extension trait to easily convert `None` from index closures to `Err`.
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in New Issue
Block a user