Skip to content

Commit

Permalink
Compute lquantize() bin only once
Browse files Browse the repository at this point in the history
First, quantize the value into a 0-based bin number.  As was done for
quantize(), use C code in the bpf/ subdirectory to be cross-compiled
into BPF when DTrace is built.

Then, the "implementation" function -- which needs to run twice, once
per aggregation copy -- is simply dt_cg_agg_quantize_impl().  That is,
we reuse the same function for lquantize() that was originally introduced
for quantize().

Signed-off-by: Eugene Loh <eugene.loh@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
euloh authored and kvanhees committed Dec 10, 2020
1 parent 98cf062 commit ca54e2b
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 77 deletions.
2 changes: 1 addition & 1 deletion bpf/Build
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ bpf_dlib_TARGET = dlibs/bpf_dlib
bpf_dlib_DIR := $(current-dir)
bpf_dlib_SRCDEPS = $(objdir)/include/.dir.stamp
bpf_dlib_SOURCES = \
agg_qbin.c \
agg_lqbin.c agg_qbin.c \
get_bvar.c \
get_gvar.c set_gvar.c \
get_tvar.c set_tvar.c \
Expand Down
24 changes: 24 additions & 0 deletions bpf/agg_lqbin.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
*/
#include <linux/bpf.h>
#include <stdint.h>
#include <bpf-helpers.h>

#ifndef noinline
# define noinline __attribute__((noinline))
#endif

noinline uint64_t dt_agg_lqbin(int64_t val, int32_t base, uint64_t levels,
uint64_t step)
{
uint64_t level;

if (step == 0 || val < base)
return 0;
level = (val - base) / step;
if (level > levels)
level = levels;
return level + 1;
}
94 changes: 18 additions & 76 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -3413,79 +3413,6 @@ dt_cg_agg_llquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
DT_CG_AGG_SET_STORAGE(aid, sz);
}

static void
dt_cg_agg_lquantize_impl(dt_irlist_t *dlp, dt_regset_t *drp, int dreg,
int vreg, int ireg, int32_t base, uint16_t levels,
uint16_t step)
{
uint_t lbl_l1 = dt_irlist_label(dlp);
uint_t lbl_l2 = dt_irlist_label(dlp);
uint_t lbl_add = dt_irlist_label(dlp);

TRACE_REGSET(" Impl: Begin");

/*
* // (%rd = dreg -- agg data)
* // (%rv = val)
* // (%ri = incr)
* if (val >= base) // jge %rv, base, L1
* goto L1; //
*
* tmp = dreg; // mov %r0, %rd
* goto ADD; // ja ADD
*/
emit(dlp, BPF_BRANCH_IMM(BPF_JSGE, vreg, base, lbl_l1));
dt_regset_xalloc(drp, BPF_REG_0);
emit(dlp, BPF_MOV_REG(BPF_REG_0, dreg));
emit(dlp, BPF_JUMP(lbl_add));

/*
* L1: level = (val - base) / step;
* // L1:
* // mov %r0, %rv
* // sub %r0, base
* // div %r0, step
* if (level < levels) // jlt %r0, levels, L2
* goto L2;
*
* tmp = dreg + 8 * (levels + 1);
* // mov %r0, levels + 1
* // lsh %r0, 3
* // add %r0, %rd
* goto ADD; // ja ADD
*/
emitl(dlp, lbl_l1,
BPF_MOV_REG(BPF_REG_0, vreg));
emit(dlp, BPF_ALU64_IMM(BPF_SUB, BPF_REG_0, base));
emit(dlp, BPF_ALU64_IMM(BPF_DIV, BPF_REG_0, step));
emit(dlp, BPF_BRANCH_IMM(BPF_JLT, BPF_REG_0, levels, lbl_l2));
emit(dlp, BPF_MOV_IMM(BPF_REG_0, levels + 1));
emit(dlp, BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3));
emit(dlp, BPF_ALU64_REG(BPF_ADD, BPF_REG_0, dreg));
emit(dlp, BPF_JUMP(lbl_add));

/*
* L2: tmp = dreg + 8 * (level + 1);
* // L2:
* // add %r0, 1
* // lsh %r0, 3
* // add %r0, %rd
*/
emitl(dlp, lbl_l2,
BPF_ALU64_IMM(BPF_ADD, BPF_REG_0, 1));
emit(dlp, BPF_ALU64_IMM(BPF_LSH, BPF_REG_0, 3));
emit(dlp, BPF_ALU64_REG(BPF_ADD, BPF_REG_0, dreg));

/*
* ADD: (*tmp) += incr; // xadd [%r0 + 0], %ri
*/
emitl(dlp, lbl_add,
BPF_XADD_REG(BPF_DW, BPF_REG_0, 0, ireg));
dt_regset_free(drp, BPF_REG_0);

TRACE_REGSET(" Impl: End ");
}

static void
dt_cg_agg_lquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
dt_irlist_t *dlp, dt_regset_t *drp)
Expand All @@ -3508,6 +3435,7 @@ dt_cg_agg_lquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
uint64_t step = 1;
int64_t baseval, limitval;
int sz, ireg;
dt_ident_t *idp;

if (arg1->dn_kind != DT_NODE_INT)
dnerror(arg1, D_LQUANT_BASETYPE, "lquantize( ) argument #1 "
Expand Down Expand Up @@ -3622,6 +3550,21 @@ dt_cg_agg_lquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,

dt_cg_node(dnp->dn_aggfun->dn_args, dlp, drp);

/* quantize the value to a 0-based bin # using dt_agg_lqbin() */
if (dt_regset_xalloc_args(drp) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
emit(dlp, BPF_MOV_REG(BPF_REG_1, dnp->dn_aggfun->dn_args->dn_reg));
emit(dlp, BPF_MOV_IMM(BPF_REG_2, baseval));
emit(dlp, BPF_MOV_IMM(BPF_REG_3, nlevels));
emit(dlp, BPF_MOV_IMM(BPF_REG_4, step));
idp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_agg_lqbin");
assert(idp != NULL);
dt_regset_xalloc(drp, BPF_REG_0);
emite(dlp, BPF_CALL_FUNC(idp->di_id), idp);
dt_regset_free_args(drp);
emit(dlp, BPF_MOV_REG(dnp->dn_aggfun->dn_args->dn_reg, BPF_REG_0));
dt_regset_free(drp, BPF_REG_0);

if (incr == NULL) {
if ((ireg = dt_regset_alloc(drp)) == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
Expand All @@ -3632,9 +3575,8 @@ dt_cg_agg_lquantize(dt_pcb_t *pcb, dt_ident_t *aid, dt_node_t *dnp,
ireg = incr->dn_reg;
}

DT_CG_AGG_IMPL(aid, sz, dlp, drp, dt_cg_agg_lquantize_impl,
dnp->dn_aggfun->dn_args->dn_reg, ireg,
baseval, nlevels, step);
DT_CG_AGG_IMPL(aid, sz, dlp, drp, dt_cg_agg_quantize_impl,
dnp->dn_aggfun->dn_args->dn_reg, ireg, nlevels + 1);

dt_regset_free(drp, dnp->dn_aggfun->dn_args->dn_reg);
dt_regset_free(drp, ireg);
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_dlibs.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ static const dt_ident_t dt_bpf_symbols[] = {
/* BPF built-in functions */
DT_BPF_SYMBOL(dt_program, DT_IDENT_FUNC),
/* BPF library (external) functions */
DT_BPF_SYMBOL(dt_agg_lqbin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_agg_qbin, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_bvar, DT_IDENT_SYMBOL),
DT_BPF_SYMBOL(dt_get_gvar, DT_IDENT_SYMBOL),
Expand Down

0 comments on commit ca54e2b

Please sign in to comment.