Skip to content

Instantly share code, notes, and snippets.

@leiless
Last active May 17, 2023 07:39
Show Gist options
  • Save leiless/22b6cf392622c6e48ca7ae9d4f15e169 to your computer and use it in GitHub Desktop.
Save leiless/22b6cf392622c6e48ca7ae9d4f15e169 to your computer and use it in GitHub Desktop.
_rdtsc ticks per second estimation
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <assert.h>
#define N 10
#define SIZE_OF(a) (sizeof(a) / sizeof(*a))
int main(void) {
uint64_t arr[N] = {};
uint64_t a, b;
unsigned int ret;
for (size_t i = 0; i < SIZE_OF(arr); i++) {
a = __builtin_ia32_rdtsc();
ret = sleep(1);
b = __builtin_ia32_rdtsc();
assert(ret == 0);
assert(b >= a);
arr[i] = b - a;
}
uint64_t max = 0;
uint64_t min = (uint64_t) -1;
uint64_t sum = 0;
for (size_t i = 0; i < SIZE_OF(arr); i++) {
printf("[%zu] = %zu\n", i, arr[i]);
if (max < arr[i]) {
max = arr[i];
}
if (min > arr[i]) {
min = arr[i];
}
sum += arr[i];
}
printf("\n");
printf("Min = %zu\n", max);
printf("Max = %zu\n", min);
printf("Max - Min = %zu\n", max - min);
printf("Avg = %zu\n", sum / N);
return 0;
}
@leiless
Copy link
Author

leiless commented May 17, 2023

fn estimate_ticks_per_second() {
    const N_THREAD: usize = 12;

    let mut handles = Vec::with_capacity(N_THREAD);
    let sleep_time = std::time::Duration::from_secs(1);

    for _i in 0..N_THREAD {
        let sleep_time_1 = sleep_time.clone();

        let h = std::thread::spawn(move || {
            let a = unsafe { core::arch::x86_64::_rdtsc() };
            std::thread::sleep(sleep_time_1);
            let b = unsafe { core::arch::x86_64::_rdtsc() };

            assert!(b >= a);

            b - a
        });
        handles.push(h);
    }

    let mut v = Vec::with_capacity(handles.len());

    for h in handles {
        let ticks_per_second = h.join().unwrap();
        v.push(ticks_per_second);
    }

    let min_tps = *v.iter().min().unwrap();
    let max_tps = *v.iter().max().unwrap();
    let avg_tps: u64 = v.iter().sum::<u64>() / N_THREAD as u64;
    let std_dev = std_deviation(v.as_slice());

    eprintln!(" N_THREAD: {}", N_THREAD);
    eprintln!("  Min TPS: {}", min_tps);
    eprintln!("  Max TPS: {}", max_tps);
    eprintln!("Max - Min: {}", max_tps - min_tps);
    eprintln!("  Avg TPS: {}", avg_tps);
    eprintln!("  Std dev: {}", std_dev.unwrap());
}

fn mean(data: &[u64]) -> Option<f64> {
    let sum = data.iter().sum::<u64>() as f64;
    let count = data.len();

    match count {
        positive if positive > 0 => Some(sum / count as f64),
        _ => None,
    }
}

// https://rust-lang-nursery.github.io/rust-cookbook/science/mathematics/statistics.html
fn std_deviation(data: &[u64]) -> Option<f64> {
    match (mean(data), data.len()) {
        (Some(data_mean), count) if count > 0 => {
            let variance = data.iter().map(|value| {
                let diff = data_mean - (*value as f64);

                diff * diff
            }).sum::<f64>() / count as f64;

            Some(variance.sqrt())
        }
        _ => None
    }
}
 N_THREAD: 12
  Min TPS: 3748208824
  Max TPS: 3754740006
Max - Min: 6531182
  Avg TPS: 3751327835
  Std dev: 2131743.207178706

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment