Add basic benches for `ql`

The benches for the protocol were fixed as well.
next
Sayan Nandan 2 years ago
parent db35f8a31b
commit 05b8fe81c0
No known key found for this signature in database
GPG Key ID: 8BC07A0A4D41DD52

@ -29,7 +29,7 @@
/// A [`DataType`] represents the underlying data-type, although this enumeration when used in a collection will always
/// be of one type.
#[derive(Debug, PartialEq)]
#[cfg_attr(debug_assertions, derive(Clone))]
#[cfg_attr(test, derive(Clone))]
pub enum DataType {
/// An UTF-8 string
String(String),

@ -78,35 +78,41 @@ impl Entity {
pub(super) fn tokens_with_full(tok: &[Token]) -> bool {
tok.len() > 2 && tok[0].is_ident() && tok[1] == Token![.] && tok[2].is_ident()
}
pub(super) fn parse(cm: &mut Compiler) -> LangResult<Self> {
let sl = cm.remslice();
let is_partial = Self::tokens_with_partial(sl);
let is_current = Self::tokens_with_single(sl);
let is_full = Self::tokens_with_full(sl);
let c;
#[inline(always)]
pub(super) fn parse_from_tokens(tok: &[Token], c: &mut usize) -> LangResult<Self> {
let is_partial = Self::tokens_with_partial(tok);
let is_current = Self::tokens_with_single(tok);
let is_full = Self::tokens_with_full(tok);
let r = match () {
_ if is_full => unsafe {
c = 3;
Self::full_entity_from_slice(sl)
*c = 3;
Self::full_entity_from_slice(tok)
},
_ if is_current => unsafe {
c = 1;
Self::single_entity_from_slice(sl)
*c = 1;
Self::single_entity_from_slice(tok)
},
_ if is_partial => unsafe {
c = 2;
Self::partial_entity_from_slice(sl)
*c = 2;
Self::partial_entity_from_slice(tok)
},
_ => return Err(LangError::UnexpectedToken),
};
Ok(r)
}
#[inline(always)]
pub(super) fn parse(cm: &mut Compiler) -> LangResult<Self> {
let sl = cm.remslice();
let mut c = 0;
let r = Self::parse_from_tokens(sl, &mut c);
unsafe {
cm.incr_cursor_by(c);
}
Ok(r)
r
}
}
#[cfg_attr(debug_assertions, derive(Debug, PartialEq))]
#[cfg_attr(test, derive(Debug, PartialEq))]
pub enum Statement {
CreateModel(schema::Model),
CreateSpace(schema::Space),

@ -0,0 +1,116 @@
/*
* Created on Wed Nov 16 2022
*
* 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) 2022, 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/>.
*
*/
/*
All benches should be aggregate costs of full execution. This means that when for example
you're writing a benchmark for something like parsing a `select` statement, you should calculate
the total time of execution including lexing, parsing and allocating. Hopefully in the future we can
implement a testing framework that enables us to find the total tiered cost of execution for each stage
and hence enable us to iterate on the weakness and fix it. Maybe even visualize it? That'd be amazing
and maybe would be something I'll work on around 0.9.
-- Sayan (@ohsayan)
*/
extern crate test;
use {crate::engine::ql::tests::lex, test::Bencher};
mod lexer {
use {
super::*,
crate::engine::ql::{
lexer::{Lit, Token},
RawSlice,
},
};
#[bench]
fn lex_number(b: &mut Bencher) {
let src = b"1234567890";
let expected = vec![Token::Lit(1234567890.into())];
b.iter(|| assert_eq!(lex(src).unwrap(), expected));
}
#[bench]
fn lex_bool(b: &mut Bencher) {
let s = b"true";
let e = vec![Token::Lit(true.into())];
b.iter(|| assert_eq!(lex(s).unwrap(), e));
}
#[bench]
fn lex_string_noescapes(b: &mut Bencher) {
let s = br#"'hello, world!'"#;
let e = vec![Token::Lit("hello, world!".into())];
b.iter(|| assert_eq!(lex(s).unwrap(), e));
}
#[bench]
fn lex_string_with_escapes(b: &mut Bencher) {
let s = br#"'hello, world! this is within a \'quote\''"#;
let e = vec![Token::Lit("hello, world! this is within a 'quote'".into())];
b.iter(|| assert_eq!(lex(s).unwrap(), e));
}
#[bench]
fn lex_raw_literal(b: &mut Bencher) {
let src = b"\r44\ne69b10ffcc250ae5091dec6f299072e23b0b41d6a739";
let expected = vec![Token::Lit(Lit::UnsafeLit(RawSlice::from(
"e69b10ffcc250ae5091dec6f299072e23b0b41d6a739",
)))];
b.iter(|| assert_eq!(lex(src).unwrap(), expected));
}
}
mod ast {
use {super::*, crate::engine::ql::ast::Entity};
#[bench]
fn parse_entity_single(b: &mut Bencher) {
let e = Entity::Single("tweeter".into());
b.iter(|| {
let src = lex(b"tweeter").unwrap();
let mut i = 0;
assert_eq!(Entity::parse_from_tokens(&src, &mut i).unwrap(), e);
assert_eq!(i, src.len());
});
}
#[bench]
fn parse_entity_double(b: &mut Bencher) {
let e = ("tweeter", "user").into();
b.iter(|| {
let src = lex(b"tweeter.user").unwrap();
let mut i = 0;
assert_eq!(Entity::parse_from_tokens(&src, &mut i).unwrap(), e);
assert_eq!(i, src.len());
});
}
#[bench]
fn parse_entity_partial(b: &mut Bencher) {
let e = Entity::Partial("user".into());
b.iter(|| {
let src = lex(b":user").unwrap();
let mut i = 0;
assert_eq!(Entity::parse_from_tokens(&src, &mut i).unwrap(), e);
assert_eq!(i, src.len());
});
}
}

@ -27,13 +27,16 @@
#[macro_use]
mod macros;
pub(super) mod ast;
#[cfg(feature = "nightly")]
#[cfg(test)]
mod benches;
pub(super) mod dml;
pub(super) mod lexer;
pub(super) mod schema;
#[cfg(test)]
mod tests;
#[cfg(debug_assertions)]
#[cfg(test)]
use core::{fmt, ops::Deref};
use core::{mem, slice, str};
@ -67,11 +70,11 @@ pub enum LangError {
/// Notes:
/// - [`Clone`] is implemented for [`RawSlice`] because it is a simple bitwise copy of the fat ptr
/// - [`fmt::Debug`] is implemented in different ways
/// - With debug assertions enabled, it will output a slice
/// - For test builds like test and bench, it will output a slice
/// - In release mode, it will output the fat ptr meta
/// - [`PartialEq`] is implemented in debug mode with slice comparison, but is **NOT implemented for release mode in the
/// way you'd expect it to**. In release mode, a comparison will simply panic.
#[cfg_attr(not(debug_assertions), derive(Debug))]
/// way you'd expect it to**. In release mode (non-test), a comparison will simply panic.
#[cfg_attr(not(test), derive(Debug))]
#[derive(Clone)]
pub struct RawSlice {
ptr: *const u8,
@ -95,7 +98,7 @@ impl RawSlice {
}
}
#[cfg(debug_assertions)]
#[cfg(test)]
impl fmt::Debug for RawSlice {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(unsafe {
@ -105,7 +108,7 @@ impl fmt::Debug for RawSlice {
}
}
#[cfg(debug_assertions)]
#[cfg(test)]
impl PartialEq for RawSlice {
fn eq(&self, other: &Self) -> bool {
unsafe {
@ -115,14 +118,14 @@ impl PartialEq for RawSlice {
}
}
#[cfg(not(debug_assertions))]
#[cfg(not(test))]
impl PartialEq for RawSlice {
fn eq(&self, _other: &Self) -> bool {
panic!("Called partialeq on rawslice in release mode");
}
}
#[cfg(debug_assertions)]
#[cfg(test)]
impl<U> PartialEq<U> for RawSlice
where
U: Deref<Target = [u8]>,

@ -157,6 +157,17 @@ pub struct Field {
pub(super) props: HashSet<StaticStr>,
}
impl Field {
#[inline(always)]
pub fn new(field_name: RawSlice, layers: Vec<Layer>, props: HashSet<StaticStr>) -> Self {
Self {
field_name,
layers,
props,
}
}
}
#[derive(Debug, PartialEq)]
/// A model definition
pub struct Model {
@ -168,6 +179,17 @@ pub struct Model {
pub(super) props: Dict,
}
impl Model {
#[inline(always)]
pub fn new(model_name: RawSlice, fields: Vec<Field>, props: Dict) -> Self {
Self {
model_name,
fields,
props,
}
}
}
#[derive(Debug, PartialEq)]
/// A space
pub struct Space {
@ -974,7 +996,7 @@ pub(super) fn parse_field_syntax<const ALLOW_RESET: bool>(
}
#[derive(Debug)]
#[cfg_attr(debug_assertions, derive(PartialEq))]
#[cfg_attr(test, derive(PartialEq))]
/// The alter operation kind
pub enum AlterKind {
Add(Box<[ExpandedField]>),

@ -25,6 +25,7 @@
*/
extern crate test;
use {
super::{super::Query, Parser},
test::Bencher,
@ -45,7 +46,7 @@ fn simple_query(b: &mut Bencher) {
let ret: Vec<String> = query
.as_slice()
.iter()
.map(|s| String::from_utf8_lossy(s.as_slice()).to_string())
.map(|s| String::from_utf8_lossy(unsafe { s.as_slice() }).to_string())
.collect();
assert_eq!(ret, expected)
});
@ -73,7 +74,7 @@ fn pipelined_query(b: &mut Bencher) {
query
.as_slice()
.iter()
.map(|v| String::from_utf8_lossy(v.as_slice()).to_string())
.map(|v| String::from_utf8_lossy(unsafe { v.as_slice() }).to_string())
.collect()
})
.collect();

@ -38,6 +38,7 @@ use {
mod interface_impls;
// test and bench modules
#[cfg(feature = "nightly")]
#[cfg(test)]
mod benches;
#[cfg(test)]
mod tests;

@ -45,7 +45,7 @@ fn simple_query(b: &mut Bencher) {
let ret: Vec<String> = query
.as_slice()
.iter()
.map(|s| String::from_utf8_lossy(s.as_slice()).to_string())
.map(|s| String::from_utf8_lossy(unsafe { s.as_slice() }).to_string())
.collect();
assert_eq!(ret, expected)
});
@ -73,7 +73,7 @@ fn pipelined_query(b: &mut Bencher) {
query
.as_slice()
.iter()
.map(|v| String::from_utf8_lossy(v.as_slice()).to_string())
.map(|v| String::from_utf8_lossy(unsafe { v.as_slice() }).to_string())
.collect()
})
.collect();

@ -35,6 +35,7 @@ use {
};
#[cfg(feature = "nightly")]
#[cfg(test)]
mod benches;
#[cfg(test)]
mod tests;

Loading…
Cancel
Save