Clean-up validation impls in sky-bench

next
Sayan Nandan 3 years ago
parent 50eb183f46
commit e67dfb2453
No known key found for this signature in database
GPG Key ID: 18E77EBDCADD5AD6

@ -24,7 +24,7 @@
* *
*/ */
use crate::report; use crate::report::AggregatedReport;
use devtimer::DevTime; use devtimer::DevTime;
use libstress::utils::generate_random_byte_vector; use libstress::utils::generate_random_byte_vector;
use libstress::PoolConfig; use libstress::PoolConfig;
@ -33,80 +33,14 @@ use skytable::types::RawString;
use skytable::Query; use skytable::Query;
use std::io::{Read, Write}; use std::io::{Read, Write};
use std::net::TcpStream; use std::net::TcpStream;
mod validation;
/// Just a sweet `*1\n` use self::validation::SIMPLE_QUERY_SIZE;
const SIMPLE_QUERY_SIZE: usize = 3;
/// For a dataframe, this returns the dataframe size for array responses. const NOTICE_INIT_BENCH: &str = "Finished sanity test. Initializing benchmark ...";
/// const NOTICE_INIT_COMPLETE: &str = "Initialization complete! Benchmark started";
/// For example, const CONFIG_TABLE_MODEL: &str = "keymap(binstr,binstr)";
/// ```text const CONFIG_TABLE_VOLATILITY: &str = "volatile";
/// &<n>\n
/// (<tsymbol><size>\n<element>)*
/// ```
#[allow(dead_code)] // TODO(@ohsayan): Remove this lint
pub fn calculate_array_dataframe_size(element_count: usize, per_element_size: usize) -> usize {
let mut s = 0;
s += 1; // `&`
s += element_count.to_string().len(); // `<n>`
s += 1; // `\n`
let mut subsize = 0;
subsize += 1; // `+`
subsize += per_element_size.to_string().len(); // `<n>`
subsize += 1; // `\n`
subsize += per_element_size; // the element size itself
subsize += 1; // `\n`
s += subsize * element_count;
s
}
/// For a monoelement dataframe, this returns the size:
/// ```text
/// <tsymbol><size>\n
/// <element>\n
/// ```
///
/// For an `okay` respcode, it will look like this:
/// ```text
/// !1\n
/// 0\n
/// ```
pub fn calculate_monoelement_dataframe_size(per_element_size: usize) -> usize {
let mut s = 0;
s += 1; // the tsymbol (always one byte)
s += per_element_size.to_string().len(); // the bytes in size string
s += 1; // the LF
s += per_element_size; // the element itself
s += 1; // the final LF
s
}
#[test]
fn test_monoelement_calculation() {
assert_eq!(calculate_monoelement_dataframe_size(1), 5);
}
/// Returns the metaframe size
/// ```text
/// *<n>\n
/// ```
#[allow(dead_code)] // TODO(@ohsayan): Remove this lint
pub fn calculate_metaframe_size(queries: usize) -> usize {
if queries == 1 {
SIMPLE_QUERY_SIZE
} else {
let mut s = 0;
s += 1; // `*`
s += queries.to_string().len(); // the bytes in size string
s += 1; // `\n`
s
}
}
#[test]
fn test_simple_query_metaframe_size() {
assert_eq!(calculate_metaframe_size(1), SIMPLE_QUERY_SIZE);
}
/// Run the benchmark tool /// Run the benchmark tool
pub fn runner( pub fn runner(
@ -125,28 +59,22 @@ pub fn runner(
err!(format!("Sanity test failed with error: {}", e)); err!(format!("Sanity test failed with error: {}", e));
} }
if !json_out { if !json_out {
println!("Finished sanity test. Initializing benchmark ..."); println!("{}", NOTICE_INIT_BENCH);
println!("Connections: {}", max_connections); println!("Connections: {}", max_connections);
println!("Queries: {}", max_queries); println!("Queries: {}", max_queries);
println!("Data size (key+value): {} bytes", (per_kv_size * 2)); println!("Data size (key+value): {} bytes", (per_kv_size * 2));
} }
let host = hoststr!(host, port); let host = hoststr!(host, port);
let mut rand = thread_rng(); let mut rand = thread_rng();
let temp_table = init_temp_table(&mut rand, &host);
let temp_table = libstress::utils::rand_alphastring(10, &mut rand);
let create_table = Query::from("create")
.arg("table")
.arg(&temp_table)
.arg("keymap(binstr,binstr)")
.arg("volatile")
.into_raw_query();
let switch_table = Query::from("use") let switch_table = Query::from("use")
.arg(format!("default:{}", &temp_table)) .arg(format!("default:{}", &temp_table))
.into_raw_query(); .into_raw_query();
let mut create_table_connection = TcpStream::connect(&host).unwrap();
// an okay response code size: `*1\n!1\n0\n`: // an okay response code size: `*1\n!1\n0\n`:
let response_okay_size = calculate_monoelement_dataframe_size(1) + SIMPLE_QUERY_SIZE; let response_okay_size =
validation::calculate_monoelement_dataframe_size(1) + SIMPLE_QUERY_SIZE;
let pool_config = PoolConfig::new( let pool_config = PoolConfig::new(
max_connections, max_connections,
@ -170,15 +98,11 @@ pub fn runner(
Some(max_queries), Some(max_queries),
); );
// create table
create_table_connection.write_all(&create_table).unwrap();
let mut v = vec![0; response_okay_size];
let _ = create_table_connection.read_exact(&mut v).unwrap();
// Create separate connection pools for get and set operations // Create separate connection pools for get and set operations
let keys = generate_random_byte_vector(max_queries, per_kv_size, &mut rand, true); let keys = generate_random_byte_vector(max_queries, per_kv_size, &mut rand, true);
let values = generate_random_byte_vector(max_queries, per_kv_size, &mut rand, false); let values = generate_random_byte_vector(max_queries, per_kv_size, &mut rand, false);
/* /*
We create three vectors of vectors: `set_packs`, `get_packs` and `del_packs` We create three vectors of vectors: `set_packs`, `get_packs` and `del_packs`
The bytes in each of `set_packs` has a query packet for setting data; The bytes in each of `set_packs` has a query packet for setting data;
@ -211,13 +135,15 @@ pub fn runner(
q.into_raw_query() q.into_raw_query()
}) })
.collect(); .collect();
if !json_out { if !json_out {
println!("Per-packet size (GET): {} bytes", get_packs[0].len()); println!("Per-packet size (GET): {} bytes", get_packs[0].len());
println!("Per-packet size (SET): {} bytes", set_packs[0].len()); println!("Per-packet size (SET): {} bytes", set_packs[0].len());
println!("Per-packet size (UPDATE): {} bytes", update_packs[0].len()); println!("Per-packet size (UPDATE): {} bytes", update_packs[0].len());
println!("Initialization complete! Benchmark started"); println!("{}", NOTICE_INIT_COMPLETE);
} }
let mut report = report::AggregatedReport::new(3, runs, max_queries);
let mut report = AggregatedReport::new(3, runs, max_queries);
for i in 1..runs + 1 { for i in 1..runs + 1 {
let mut dt = DevTime::new_complex(); let mut dt = DevTime::new_complex();
// clone in the keys // clone in the keys
@ -232,10 +158,8 @@ pub fn runner(
setpool.execute_and_finish_iter(set_packs); setpool.execute_and_finish_iter(set_packs);
dt.stop_timer("SET").unwrap(); dt.stop_timer("SET").unwrap();
// TODO: Update the getpool to use correct sizes
// bench GET
let get_response_packet_size = let get_response_packet_size =
calculate_monoelement_dataframe_size(per_kv_size) + SIMPLE_QUERY_SIZE; validation::calculate_monoelement_dataframe_size(per_kv_size) + SIMPLE_QUERY_SIZE;
let getpool = let getpool =
pool_config.with_loop_closure(move |sock: &mut TcpStream, packet: Vec<u8>| { pool_config.with_loop_closure(move |sock: &mut TcpStream, packet: Vec<u8>| {
sock.write_all(&packet).unwrap(); sock.write_all(&packet).unwrap();
@ -270,7 +194,27 @@ pub fn runner(
dt.iter() dt.iter()
.for_each(|(name, timer)| report.insert(name, timer.time_in_nanos().unwrap())); .for_each(|(name, timer)| report.insert(name, timer.time_in_nanos().unwrap()));
} }
if json_out { print_results(json_out, report);
}
fn init_temp_table(rand: &mut impl rand::Rng, host: &str) -> String {
let temp_table = libstress::utils::rand_alphastring(10, rand);
let create_table = Query::from("create")
.arg("table")
.arg(&temp_table)
.arg(CONFIG_TABLE_MODEL)
.arg(CONFIG_TABLE_VOLATILITY)
.into_raw_query();
let mut create_table_connection = TcpStream::connect(host).unwrap();
// create table
create_table_connection.write_all(&create_table).unwrap();
let mut v = [0u8; 8];
let _ = create_table_connection.read_exact(&mut v).unwrap();
temp_table
}
fn print_results(flag_json: bool, report: AggregatedReport) {
if flag_json {
let serialized = report.into_json(); let serialized = report.into_json();
println!("{}", serialized); println!("{}", serialized);
} else { } else {

@ -0,0 +1,132 @@
/*
* Created on Fri Nov 26 2021
*
* This file is a part of Skytable
* Skytable (formerly known as TerrabaseDB or Skybase) is a free and open-source
* NoSQL database written by Sayan Nandan ("the Author") with the
* vision to provide flexibility in data modelling without compromising
* on performance, queryability or scalability.
*
* Copyright (c) 2021, Sayan Nandan <ohsayan@outlook.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/// Just a sweet `*1\n`
pub(super) const SIMPLE_QUERY_SIZE: usize = 3;
/// For a dataframe, this returns the dataframe size for array responses.
///
/// For example,
/// ```text
/// &<n>\n
/// (<tsymbol><size>\n<element>)*
/// ```
#[allow(dead_code)] // TODO(@ohsayan): Remove this lint
pub fn calculate_array_dataframe_size(element_count: usize, per_element_size: usize) -> usize {
let mut s = 0;
s += 1; // `&`
s += element_count.to_string().len(); // `<n>`
s += 1; // `\n`
let mut subsize = 0;
subsize += 1; // `+`
subsize += per_element_size.to_string().len(); // `<n>`
subsize += 1; // `\n`
subsize += per_element_size; // the element size itself
subsize += 1; // `\n`
s += subsize * element_count;
s
}
/// For a dataframe with a typed array, calculate its size
///
/// **Warning:** Null entries are not yet supported (for a full null array, just pass `1` for the `per_element_size`)
#[allow(dead_code)]
pub fn calculate_typed_array_dataframe_size(
element_count: usize,
per_element_size: usize,
) -> usize {
let mut s = 0usize;
s += 2; // `@<tsymbol>`
s += element_count.to_string().len(); // `<n>`
s += 1; // `\n`
// now for the payload
let mut subsize = 0usize;
subsize += per_element_size.to_string().len(); // `<n>`
subsize += 1; // `\n`
subsize += per_element_size; // the payload itself
subsize += 1; // `\n`
s += subsize * element_count;
s
}
/// For a monoelement dataframe, this returns the size:
/// ```text
/// <tsymbol><size>\n
/// <element>\n
/// ```
///
/// For an `okay` respcode, it will look like this:
/// ```text
/// !1\n
/// 0\n
/// ```
pub fn calculate_monoelement_dataframe_size(per_element_size: usize) -> usize {
let mut s = 0;
s += 1; // the tsymbol (always one byte)
s += per_element_size.to_string().len(); // the bytes in size string
s += 1; // the LF
s += per_element_size; // the element itself
s += 1; // the final LF
s
}
/// Returns the metaframe size
/// ```text
/// *<n>\n
/// ```
#[allow(dead_code)] // TODO(@ohsayan): Remove this lint
pub fn calculate_metaframe_size(queries: usize) -> usize {
if queries == 1 {
SIMPLE_QUERY_SIZE
} else {
let mut s = 0;
s += 1; // `*`
s += queries.to_string().len(); // the bytes in size string
s += 1; // `\n`
s
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_monoelement_calculation() {
assert_eq!(calculate_monoelement_dataframe_size(1), 5);
}
#[test]
fn test_simple_query_metaframe_size() {
assert_eq!(calculate_metaframe_size(1), SIMPLE_QUERY_SIZE);
}
#[test]
fn test_typed_array_dataframe_size() {
let packet = b"@+3\n3\nhow\n3\nyou\n3\ndng\n";
assert_eq!(calculate_typed_array_dataframe_size(3, 3), packet.len());
}
}
Loading…
Cancel
Save