KipData/FnckSQL

Feat: replace `DataValue::binary_op` with generics

Closed this issue · 1 comments

Feature Request

Specialize the DataValue::binary_op method using generics to avoid runtime branch judgment overhead.

Tips: you can introduce rules to refer to NormalizationRuleImpl::ExpressionRemapper to determine the calculation type of each ScalarExpression::Bianry during optimization. When there is no such calculation type (when the optimization rule is not used), the calculation generic of the corresponding type is obtained during calculation.

use criterion::{criterion_group, criterion_main, Criterion};
use fnck_sql::expression::BinaryOperator;

use fnck_sql::types::evaluator::BinaryEvaluator;
use fnck_sql::types::evaluator::int32::Int32PlusBinaryEvaluator;
use fnck_sql::types::evaluator::int32::Int32MinusBinaryEvaluator;
use fnck_sql::types::value::DataValue;

fn test_value(c: &mut Criterion) {
    let v1 = DataValue::Int32(Some(2));
    let v2 = DataValue::Int32(Some(99999));
    let v3 = DataValue::Int32(None);

    c.bench_function("specialized calculations", |b| {
        b.iter(|| {
            let v4 = Int32PlusBinaryEvaluator::binary_eval(&v1, &v2);
            let _v5 = Int32MinusBinaryEvaluator::binary_eval(&v4, &v3);
        })
    });
    c.bench_function("dynamic calculation", |b| {
        b.iter(|| {
            let v4 = v1.binary_op(&v2, &BinaryOperator::Plus).unwrap();
            let _v5 = v4.binary_op(&v3, &BinaryOperator::Minus);
        })
    });
}

#[cfg(windows)]
criterion_group!(
    name = query_benches;
    config = Criterion::default().sample_size(100_000);
    targets = test_value
);

criterion_main!(query_benches,);

image
criterion.zip