Skip to content

Commit

Permalink
Refine coprocessor benchmarks (tikv#4501)
Browse files Browse the repository at this point in the history
Signed-off-by: Breezewish <breezewish@pingcap.com>
  • Loading branch information
breezewish committed Jun 12, 2019
1 parent 6a3f632 commit 6d6e2f8
Show file tree
Hide file tree
Showing 27 changed files with 3,681 additions and 637 deletions.
246 changes: 246 additions & 0 deletions benches/coprocessor_executors/hash_aggr/mod.rs
@@ -0,0 +1,246 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

mod util;

use cop_datatype::FieldTypeTp;
use tipb::expression::{ExprType, ScalarFuncSig};
use tipb_helper::ExprDefBuilder;

use crate::util::{BenchCase, FixtureBuilder};

/// COUNT(1) GROUP BY COL where COL is a int column.
/// Each row is a new group.
fn bench_hash_aggr_count_1_group_by_int_col(b: &mut criterion::Bencher, input: &Input) {
let fb = FixtureBuilder::new(input.src_rows).push_column_i64_0_n();
let group_by = vec![ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build()];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL where COL is a int column.
/// There will be two groups totally.
fn bench_hash_aggr_count_1_group_by_int_col_2_groups(b: &mut criterion::Bencher, input: &Input) {
let fb = FixtureBuilder::new(input.src_rows).push_column_i64_sampled(&[0x123456, 0xCCCC]);
let group_by = vec![ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build()];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL > X.
/// Half of the row belong to one group and the rest belong to another group. Thus there are
/// totally two groups.
fn bench_hash_aggr_count_1_group_by_fn_2_groups(b: &mut criterion::Bencher, input: &Input) {
let fb = FixtureBuilder::new(input.src_rows).push_column_i64_0_n();
let group_by = vec![
ExprDefBuilder::scalar_func(ScalarFuncSig::GTInt, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong))
.push_child(ExprDefBuilder::constant_int((input.src_rows / 2) as i64))
.build(),
];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL where COL is a decimal column (by slow hash aggr).
/// Each row is a new group.
fn bench_hash_aggr_count_1_group_by_decimal_col(b: &mut criterion::Bencher, input: &Input) {
let fb = FixtureBuilder::new(input.src_rows).push_column_decimal_0_n();
let group_by = vec![ExprDefBuilder::column_ref(0, FieldTypeTp::NewDecimal).build()];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL where COL is a decimal column (by slow hash aggr).
/// There will be two groups totally.
fn bench_hash_aggr_count_1_group_by_decimal_col_2_groups(
b: &mut criterion::Bencher,
input: &Input,
) {
let fb = FixtureBuilder::new(input.src_rows)
.push_column_decimal_sampled(&["680644618.9451818", "767257805709854474.824642776567"]);
let group_by = vec![ExprDefBuilder::column_ref(0, FieldTypeTp::NewDecimal).build()];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL1, COL2 where COL1 is a int column and COL2 is a real column.
/// Each row is a new group.
fn bench_hash_aggr_count_1_group_by_int_col_real_col(b: &mut criterion::Bencher, input: &Input) {
let fb = FixtureBuilder::new(input.src_rows)
.push_column_i64_random()
.push_column_f64_random();
let group_by = vec![
ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build(),
ExprDefBuilder::column_ref(1, FieldTypeTp::Double).build(),
];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1) GROUP BY COL1, COL2 where COL1 is a int column and COL2 is a real column.
/// There will be two groups totally.
fn bench_hash_aggr_count_1_group_by_int_col_real_col_2_groups(
b: &mut criterion::Bencher,
input: &Input,
) {
let fb = FixtureBuilder::new(input.src_rows)
.push_column_i64_sampled(&[0xDEADBEEF, 0xFEE1DEAD])
.push_column_f64_sampled(&[680644618.9451818]);
let group_by = vec![
ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build(),
ExprDefBuilder::column_ref(1, FieldTypeTp::Double).build(),
];
let expr = ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build();
input.bencher.bench(b, &fb, &group_by, &[expr]);
}

/// COUNT(1), FIRST(COL3) GROUP BY COL1, COL2 where COL1 is a int column and
/// COL2, COL3 are real columns. Each row is a new group.
fn bench_hash_aggr_count_1_first_group_by_int_col_real_col(
b: &mut criterion::Bencher,
input: &Input,
) {
let fb = FixtureBuilder::new(input.src_rows)
.push_column_i64_random()
.push_column_f64_random()
.push_column_f64_random();
let group_by = vec![
ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build(),
ExprDefBuilder::column_ref(1, FieldTypeTp::Double).build(),
];
let expr = [
ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build(),
ExprDefBuilder::aggr_func(ExprType::First, FieldTypeTp::Double)
.push_child(ExprDefBuilder::column_ref(2, FieldTypeTp::Double))
.build(),
];
input.bencher.bench(b, &fb, &group_by, &expr);
}

/// COUNT(1), FIRST(COL3) GROUP BY COL1, COL2 where COL1 is a int column and
/// COL2, COL3 are real columns. There will be two groups totally.
fn bench_hash_aggr_count_1_first_group_by_int_col_real_col_2_groups(
b: &mut criterion::Bencher,
input: &Input,
) {
let fb = FixtureBuilder::new(input.src_rows)
.push_column_i64_sampled(&[0xDEADBEEF, 0xFEE1DEAD])
.push_column_f64_sampled(&[680644618.9451818])
.push_column_f64_random();
let group_by = vec![
ExprDefBuilder::column_ref(0, FieldTypeTp::LongLong).build(),
ExprDefBuilder::column_ref(1, FieldTypeTp::Double).build(),
];
let expr = [
ExprDefBuilder::aggr_func(ExprType::Count, FieldTypeTp::LongLong)
.push_child(ExprDefBuilder::constant_int(1))
.build(),
ExprDefBuilder::aggr_func(ExprType::First, FieldTypeTp::Double)
.push_child(ExprDefBuilder::column_ref(2, FieldTypeTp::Double))
.build(),
];
input.bencher.bench(b, &fb, &group_by, &expr);
}

#[derive(Clone)]
struct Input {
/// How many rows to aggregate
src_rows: usize,

/// The aggregate executor (batch / normal) to use
bencher: Box<dyn util::HashAggrBencher>,
}

impl std::fmt::Debug for Input {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}/rows={}", self.bencher.name(), self.src_rows)
}
}

pub fn bench(c: &mut criterion::Criterion) {
let mut inputs = vec![];

let mut rows_options = vec![5000];
if crate::util::bench_level() >= 1 {
rows_options.push(5);
}
if crate::util::bench_level() >= 2 {
rows_options.push(1);
}
let bencher_options: Vec<Box<dyn util::HashAggrBencher>> =
vec![Box::new(util::NormalBencher), Box::new(util::BatchBencher)];

for rows in &rows_options {
for bencher in &bencher_options {
inputs.push(Input {
src_rows: *rows,
bencher: bencher.box_clone(),
});
}
}

let mut cases = vec![
BenchCase::new(
"hash_aggr_count_1_group_by_int_col_2_groups",
bench_hash_aggr_count_1_group_by_int_col_2_groups,
),
BenchCase::new(
"hash_aggr_count_1_group_by_decimal_col_2_groups",
bench_hash_aggr_count_1_group_by_decimal_col_2_groups,
),
BenchCase::new(
"hash_aggr_count_1_group_by_int_col_real_col_2_groups",
bench_hash_aggr_count_1_group_by_int_col_real_col_2_groups,
),
BenchCase::new(
"hash_aggr_count_1_first_group_by_int_col_real_col_2_groups",
bench_hash_aggr_count_1_first_group_by_int_col_real_col_2_groups,
),
];
if crate::util::bench_level() >= 1 {
let mut additional_cases = vec![
BenchCase::new(
"hash_aggr_count_1_group_by_fn_2_groups",
bench_hash_aggr_count_1_group_by_fn_2_groups,
),
BenchCase::new(
"hash_aggr_count_1_group_by_int_col",
bench_hash_aggr_count_1_group_by_int_col,
),
BenchCase::new(
"hash_aggr_count_1_group_by_decimal_col",
bench_hash_aggr_count_1_group_by_decimal_col,
),
BenchCase::new(
"hash_aggr_count_1_group_by_int_col_real_col",
bench_hash_aggr_count_1_group_by_int_col_real_col,
),
BenchCase::new(
"hash_aggr_count_1_first_group_by_int_col_real_col",
bench_hash_aggr_count_1_first_group_by_int_col_real_col,
),
];
cases.append(&mut additional_cases);
}

cases.sort();
for case in cases {
c.bench_function_over_inputs(case.name, case.f, inputs.clone());
}
}
124 changes: 124 additions & 0 deletions benches/coprocessor_executors/hash_aggr/util.rs
@@ -0,0 +1,124 @@
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.

use std::sync::Arc;

use criterion::black_box;

use tipb::executor::Aggregation;
use tipb::expression::Expr;

use tikv::coprocessor::dag::batch::executors::BatchFastHashAggregationExecutor;
use tikv::coprocessor::dag::batch::executors::BatchSlowHashAggregationExecutor;
use tikv::coprocessor::dag::batch::interface::*;
use tikv::coprocessor::dag::executor::{Executor, HashAggExecutor};
use tikv::coprocessor::dag::expr::EvalConfig;

use crate::util::bencher::Bencher;
use crate::util::FixtureBuilder;

pub trait HashAggrBencher {
fn name(&self) -> &'static str;

fn bench(
&self,
b: &mut criterion::Bencher,
fb: &FixtureBuilder,
group_by_expr: &[Expr],
aggr_expr: &[Expr],
);

fn box_clone(&self) -> Box<dyn HashAggrBencher>;
}

impl Clone for Box<dyn HashAggrBencher> {
#[inline]
fn clone(&self) -> Self {
self.box_clone()
}
}

/// A bencher that will use normal hash aggregation executor to bench the giving aggregate
/// expression.
pub struct NormalBencher;

impl HashAggrBencher for NormalBencher {
fn name(&self) -> &'static str {
"normal"
}

fn bench(
&self,
b: &mut criterion::Bencher,
fb: &FixtureBuilder,
group_by_expr: &[Expr],
aggr_expr: &[Expr],
) {
crate::util::bencher::NormalNextAllBencher::new(|| {
let mut meta = Aggregation::new();
meta.set_agg_func(aggr_expr.to_vec().into());
meta.set_group_by(group_by_expr.to_vec().into());
let src = fb.clone().build_normal_fixture_executor();
let ex = HashAggExecutor::new(
black_box(meta),
black_box(Arc::new(EvalConfig::default())),
black_box(Box::new(src)),
)
.unwrap();
Box::new(ex) as Box<dyn Executor>
})
.bench(b);
}

fn box_clone(&self) -> Box<dyn HashAggrBencher> {
Box::new(Self)
}
}

/// A bencher that will use batch hash aggregation executor to bench the giving aggregate
/// expression.
pub struct BatchBencher;

impl HashAggrBencher for BatchBencher {
fn name(&self) -> &'static str {
"batch"
}

fn bench(
&self,
b: &mut criterion::Bencher,
fb: &FixtureBuilder,
group_by_expr: &[Expr],
aggr_expr: &[Expr],
) {
crate::util::bencher::BatchNextAllBencher::new(|| {
let src = fb.clone().build_batch_fixture_executor();
let mut meta = Aggregation::new();
meta.set_agg_func(aggr_expr.to_vec().into());
meta.set_group_by(group_by_expr.to_vec().into());
if BatchFastHashAggregationExecutor::check_supported(&meta).is_ok() {
let ex = BatchFastHashAggregationExecutor::new(
black_box(Arc::new(EvalConfig::default())),
black_box(Box::new(src)),
black_box(group_by_expr.to_vec()),
black_box(aggr_expr.to_vec()),
)
.unwrap();
Box::new(ex) as Box<dyn BatchExecutor>
} else {
let ex = BatchSlowHashAggregationExecutor::new(
black_box(Arc::new(EvalConfig::default())),
black_box(Box::new(src)),
black_box(group_by_expr.to_vec()),
black_box(aggr_expr.to_vec()),
)
.unwrap();
Box::new(ex) as Box<dyn BatchExecutor>
}
})
.bench(b);
}

fn box_clone(&self) -> Box<dyn HashAggrBencher> {
Box::new(Self)
}
}

0 comments on commit 6d6e2f8

Please sign in to comment.