Skip to content

Improve cloud capacity (CU / SU) calculation #966

Description

@renauter

Is your feature request related to a problem? Please describe

When we calculate SU and CU (integer values) we do some integer divisions which leads to some precision error.

Describe the solution you'd like

A better approach would be to deal with float divisions and round result to closest integer before converting back to integer.
With this we would get more accurate values.

Additional context

Example of precision error while calculating SU / CU for node 6705

image

Simulated calculation from rust tfchain code:

const GIGABYTE: u128 = 1024 * 1024 * 1024;
const ONE_THOUSAND: u128 = 1000;
const CRU: u64 = 12;
const MRU: u64 = 67036315648;
const SRU: u64 = 1000204886016;
const HRU: u64 = 0;

fn calc_cu() -> u64 {
    let cru_min = CRU as u128 * 2 * GIGABYTE * ONE_THOUSAND;
    let mru_min =
        ((MRU as u128).checked_sub(1).unwrap_or(0) * GIGABYTE) * ONE_THOUSAND / 4;
    let sru_min = SRU as u128 * ONE_THOUSAND / 50;

    if cru_min < mru_min && cru_min < sru_min {
        cru_min as u64
    } else if mru_min < cru_min && mru_min < sru_min {
        mru_min as u64
    } else if sru_min < cru_min && sru_min < mru_min {
        sru_min as u64
    } else {
        0
    }
}
    
fn get_cu() -> u64 {
    let cu = calc_cu();
    let calculated_cu = 2 * (cu as u128 / GIGABYTE / ONE_THOUSAND);
    calculated_cu as u64
}
    
fn get_su() -> u64 {
    let su = HRU as u128 * ONE_THOUSAND / 1200 + SRU as u128 * ONE_THOUSAND / 250;
    let calculated_su = su / GIGABYTE;
    let result = calculated_su as u128 / ONE_THOUSAND;
    result as u64
}

fn main() {
    println!("CU: {}", get_cu());
    println!("SU: {}", get_su());
}

Copy past previous code in rust playground https://play.rust-lang.org/ and run gives:

CU: 36
SU: 3

While calculating using float would give:

>>> GIGABYTE = 1024 * 1024 * 1024
>>> cru = 12
>>> mru = 67036315648
>>> sru = 1000204886016
>>> hru = 0
>>> cru_min = cru * 2 * GIGABYTE * 1000
>>> cru_min
25769803776000
>>> mru_min = ((mru - 1) * GIGABYTE) * 1000 / 4
>>> mru_min
1.799492395926238e+22
>>> sru_min = sru * 1000 / 50
>>> sru_min
20004097720320.0
>>> sru_min < cru_min and sru_min < mru_min
True
>>> cu = sru_min
>>> 2 * (cu / GIGABYTE / 1000)
37.26053558349609
>>> su = hru * 1000 / 1200 + sru * 1000 / 250
>>> su / GIGABYTE / 1000
3.7260535583496095
CU: 37
SU: 4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions