-
Notifications
You must be signed in to change notification settings - Fork 2.6k
Document weight for asset, system and timestamp pallets #5593
Changes from 5 commits
8e40c66
085fd68
71003b2
7f1e6cc
7b80b40
10f557a
3ec0a1d
ac4e662
90733de
5d6711a
9bb9334
c598d25
81e86c1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -482,19 +482,35 @@ decl_module! { | |
} | ||
|
||
/// Make some on-chain remark. | ||
/// | ||
/// # <weight> | ||
/// - `O(1)` | ||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedNormal(10_000)] | ||
fn remark(origin, _remark: Vec<u8>) { | ||
ensure_signed(origin)?; | ||
} | ||
|
||
/// Set the number of pages in the WebAssembly environment's heap. | ||
/// | ||
/// # <weight> | ||
/// - `O(1)` | ||
/// - 1 storage write. | ||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(10_000)] | ||
fn set_heap_pages(origin, pages: u64) { | ||
ensure_root(origin)?; | ||
storage::unhashed::put_raw(well_known_keys::HEAP_PAGES, &pages.encode()); | ||
} | ||
|
||
/// Set the new runtime code. | ||
/// | ||
/// # <weight> | ||
/// - `O(C + S)` where `C` length of `code` and `S` complexity of `can_set_code` | ||
/// - 1 storage write (codec `O(C)`). | ||
/// - 1 call to `can_set_code`: `O(S)` (calls `sp_io::misc::runtime_version` which is expensive). | ||
/// - 1 event. | ||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(200_000)] | ||
pub fn set_code(origin, code: Vec<u8>) { | ||
Self::can_set_code(origin, &code)?; | ||
|
@@ -504,6 +520,12 @@ decl_module! { | |
} | ||
|
||
/// Set the new runtime code without doing any checks of the given `code`. | ||
/// | ||
/// # <weight> | ||
/// - `O(C)` where `C` length of `code` | ||
/// - 1 storage write (codec `O(C)`). | ||
/// - 1 event. | ||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(200_000)] | ||
pub fn set_code_without_checks(origin, code: Vec<u8>) { | ||
ensure_root(origin)?; | ||
|
@@ -512,6 +534,12 @@ decl_module! { | |
} | ||
|
||
/// Set the new changes trie configuration. | ||
/// | ||
/// # <weight> | ||
/// - `O(L)` where `L` complexity of `deposit_log` | ||
/// - 1 storage write or delete (codec `O(1)`). | ||
/// - 1 call to `deposit_log`: `O(L)` (which is `O(D)` for the length of `Digest`) | ||
apopiak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(20_000)] | ||
pub fn set_changes_trie_config(origin, changes_trie_config: Option<ChangesTrieConfiguration>) { | ||
ensure_root(origin)?; | ||
|
@@ -530,6 +558,11 @@ decl_module! { | |
} | ||
|
||
/// Set some items of storage. | ||
/// | ||
/// # <weight> | ||
/// - `O(VI)` where `V` length of `items` and `I` length of one item | ||
/// - `V` storage writes (codec `O(I)`). | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't we consider that a storage write is constant complexity? #2966 (comment) So complexity would be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The thing is that there is no bound (that I could see by looking at the code here) on the size of the item. AFAICS it's just a vec and could thus be arbitrarily big. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If we can find a correct upper bound for the size of value where it is still kind of constant complexity we can benchmark agains't this upper bound and say in the doc of this extrinsic that if (note that such documentation constrain is only possible because this is root exstrinsic) |
||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(10_000)] | ||
fn set_storage(origin, items: Vec<KeyValue>) { | ||
ensure_root(origin)?; | ||
|
@@ -539,6 +572,11 @@ decl_module! { | |
} | ||
|
||
/// Kill some items from storage. | ||
/// | ||
/// # <weight> | ||
/// - `O(VK)` where `V` length of `keys` and `K` length of one key | ||
/// - `V` storage deletions (codec `O(K)`). | ||
apopiak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(10_000)] | ||
fn kill_storage(origin, keys: Vec<Key>) { | ||
ensure_root(origin)?; | ||
|
@@ -548,6 +586,11 @@ decl_module! { | |
} | ||
|
||
/// Kill all storage items with a key that starts with the given prefix. | ||
/// | ||
/// # <weight> | ||
/// - `O(P)` where `P` amount of keys with prefix `prefix` | ||
apopiak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// - `P` storage deletions. | ||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(10_000)] | ||
fn kill_prefix(origin, prefix: Key) { | ||
ensure_root(origin)?; | ||
|
@@ -556,6 +599,11 @@ decl_module! { | |
|
||
/// Kill the sending account, assuming there are no references outstanding and the composite | ||
/// data is equal to its default value. | ||
/// | ||
/// # <weight> | ||
/// - `O(1)` | ||
/// - 1 storage read and deletion. | ||
apopiak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// # </weight> | ||
#[weight = SimpleDispatchInfo::FixedOperational(25_000)] | ||
fn suicide(origin) { | ||
let who = ensure_signed(origin)?; | ||
|
@@ -912,6 +960,11 @@ impl<T: Trait> Module<T> { | |
} | ||
|
||
/// Deposits a log and ensures it matches the block's log data. | ||
/// | ||
/// # <weight> | ||
/// - `O(D)` where `D` length of `Digest` | ||
/// - 1 storage mutation (codec `O(D)`). | ||
/// # </weight> | ||
pub fn deposit_log(item: DigestItemOf<T>) { | ||
let mut l = <Digest<T>>::get(); | ||
l.push(item); | ||
apopiak marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure how should we express this:
shouldn't it be:
complexity = O(C) + S with S cost of sp_io::misc::runtime_version
?Here S is not a variable complexity it is a constant one.
I guess if I follow benchmark philosophie (in notion) then it should be written just
O(C)
and benchmark will figure out K1 and K2 withweight = K1 + K2*C
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because big O notation only gives an upper bound and not the tight upper bound, both
O(C + S)
andO(C) + S
are totally admissable. The only guarantee is "will never be higher than the complexity of a function in this category", so in principle it's fine either way.I guess in practice we often try to give a reasonably tight upper bound, but I don't think we need to spend a lot of time discussing how tight exactly it should be. 🤷
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nice thing of
O(S)
(instead ofS
) is that there might be some constant costs associated with callingcan_set_code
(or as in your commentruntime_version
) that are included with big O, but not if you just put it there.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
O(C + S)
if S is constant complexity is equivalent toO(C)
and so we should prefer the second one. By equivalent I mean that there is mathematically no differences at all (but I actually forgot a bit of my approximation math courses)In the notion https://www.notion.so/Benchmarking-Philosophy-c5aafd34578f4be9ab8c8d7510e98314
It seems the strategy is to then come up with real number using benchmark. but S here is not varying so we don't benchmark its variation. so we will only benchmark with C varying and we will compute
w = K1 + K2*C
and so S will disappear in K1I don't understand this for me S is constant cost so when a chain will benchmark its stuff it will be included in K1 no matter what the chain is using under the hood
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PS: I'm not trying to be picky I'm just thinking that if we want to follow the strategy:
O(M + logM + B + E)
weight(M, B, E) = K_1 + K_2 * M + K_3 * logM + B + E
hmm actually I lost myself with this paragraph in notion:
I though benchmark will compute:
weight(M, B, E) = K_1 + K_2 * M + K_3 * logM + K_4*B + K_5*E
So not sure anymore about how this works
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have not looked into the benchmarks much, yet, so I'm sad to tell you that I cannot be very helpful there. Maybe @shawntabrizi can weigh in .
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah I mixed myself indeed
complexity(sp_io::misc::runtime_version(&code)) == O(code.len())
so the cost of the extrinsic should be
O(C + C)= O(C)
no ?At the end
weight(C) = K1 + K2*C
any constant cost in can_set_code will be in K1 anyway.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, except that I don't know whether S might be
O(C^2)
or something even more crazy. I went the conservative way because I saw the note onsp_io::misc::runtime_version
being expensive and relying on executing the code in question.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm ok I also mistaken on the complexity of
sp_io::misc::runtime_version
then I'm ok to have S as complexity ofsp_io::misc::runtime_version
, which is unknown to me.I guess to come up to a correct formula we should say this weight full block ?
EDIT: at the same time knowing the version of the runtime shouldn't be too costy, so this upper bound is very inaccurate. Another idea would be to actually benchmark it for the current runtime and do
weight = 10 * benchmark_result
and say that we don't expect a new runtime to increase this cost by 10. or maybe we can compare it to the cost of an empty block or base transaction weight.But anyway this will only happen on runtime upgrade so IMHO it is fine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe? I'm out of my depth here.
@gavofyork or @shawntabrizi What do you think?