use crate::LobstersRequest;
use crate::{COMMENTS_PER_STORY, VOTES_PER_COMMENT, VOTES_PER_STORY, VOTES_PER_USER};
use hdrhistogram::Histogram;
use histogram_sampler;
use rand::distributions::Distribution;
use std::collections::HashMap;
use std::{mem, time};
type Stats = HashMap<mem::Discriminant<LobstersRequest>, Histogram<u64>>;
#[derive(Clone, Debug)]
struct Sampler {
votes_per_user: histogram_sampler::Sampler,
votes_per_story: histogram_sampler::Sampler,
votes_per_comment: histogram_sampler::Sampler,
comments_per_story: histogram_sampler::Sampler,
}
use rand;
impl Sampler {
fn new(scale: f64) -> Self {
fn adjust<'a, F>(
hist: &'static [(usize, usize)],
f: F,
) -> impl Iterator<Item = (usize, usize)>
where
F: Fn(f64) -> f64,
{
hist.into_iter()
.map(move |&(bin, n)| (bin, f(n as f64).round() as usize))
}
let votes_per_user = adjust(VOTES_PER_USER, |n| n * scale);
let votes_per_story = adjust(VOTES_PER_STORY, |n| n);
let votes_per_comment = adjust(VOTES_PER_COMMENT, |n| n);
let comments_per_story = adjust(COMMENTS_PER_STORY, |n| n);
Sampler {
votes_per_user: histogram_sampler::Sampler::from_bins(votes_per_user, 100),
votes_per_story: histogram_sampler::Sampler::from_bins(votes_per_story, 10),
votes_per_comment: histogram_sampler::Sampler::from_bins(votes_per_comment, 10),
comments_per_story: histogram_sampler::Sampler::from_bins(comments_per_story, 10),
}
}
fn user<R: rand::Rng>(&self, rng: &mut R) -> u32 {
self.votes_per_user.sample(rng) as u32
}
fn nusers(&self) -> u32 {
self.votes_per_user.nvalues() as u32
}
fn comment_for_vote<R: rand::Rng>(&self, rng: &mut R) -> u32 {
self.votes_per_comment.sample(rng) as u32
}
fn story_for_vote<R: rand::Rng>(&self, rng: &mut R) -> u32 {
self.votes_per_story.sample(rng) as u32
}
fn nstories(&self) -> u32 {
std::cmp::max(
self.votes_per_story.nvalues(),
self.comments_per_story.nvalues(),
) as u32
}
fn story_for_comment<R: rand::Rng>(&self, rng: &mut R) -> u32 {
self.comments_per_story.sample(rng) as u32
}
fn ncomments(&self) -> u32 {
self.votes_per_comment.nvalues() as u32
}
}
const MAX_SLUGGABLE_ID: u32 = 2176782336;
#[inline]
fn id_to_slug(mut id: u32) -> [u8; 6] {
let mut slug = [0; 6];
let mut digit: u8;
digit = (id % 36) as u8;
slug[5] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
digit = (id % 36) as u8;
slug[4] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
digit = (id % 36) as u8;
slug[3] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
digit = (id % 36) as u8;
slug[2] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
digit = (id % 36) as u8;
slug[1] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
digit = (id % 36) as u8;
slug[0] = digit + if digit < 10 { b'0' } else { b'a' - 10 };
id /= 36;
debug_assert_eq!(id, 0);
slug
}
#[derive(Clone, Debug)]
pub(crate) struct Workload {
pub(crate) scale: f64,
pub(crate) warmup: time::Duration,
pub(crate) runtime: time::Duration,
}
pub(crate) mod harness;