Commit 282748b0 authored by Brendan Gregg's avatar Brendan Gregg

rename to hist()

parent 6bdd1198
......@@ -12,7 +12,7 @@ CONFIG_BPF_EVENTS=y
To use some BPFtrace features, minimum kernel versions are required:
- 4.1+ - kprobes
- 4.3+ - uprobes
- 4.6+ - stack traces, count and quantize builtins (use PERCPU maps for accuracy and efficiency)
- 4.6+ - stack traces, count and hist builtins (use PERCPU maps for accuracy and efficiency)
- 4.7+ - tracepoints
- 4.9+ - timers/profiling
......
......@@ -40,7 +40,7 @@ kprobe:sys_read
kretprobe:sys_read / @start[tid] /
{
@times = quantize(nsecs - @start[tid]);
@times = hist(nsecs - @start[tid]);
delete(@start[tid]);
}
```
......@@ -220,7 +220,7 @@ Variables:
- `func` - Name of the function currently being traced
Functions:
- `quantize(int n)` - Produce a log2 histogram of values of `n`
- `hist(int n)` - Produce a log2 histogram of values of `n`
- `lhist(int n, int min, int max, int step)` - Produce a linear histogram of values of `n`
- `count()` - Count the number of times this function is called
- `sum(int n)` - Sum this value
......
......@@ -186,11 +186,11 @@ void CodegenLLVM::visit(Call &call)
}
else if (call.func == "avg" || call.func == "stats")
{
// avg stores the count and total in a quantize map using indexes 0 and 1
// avg stores the count and total in a hist map using indexes 0 and 1
// respectively, and the calculation is made when printing.
Map &map = *call.map;
AllocaInst *count_key = getQuantizeMapKey(map, b_.getInt64(0));
AllocaInst *count_key = getHistMapKey(map, b_.getInt64(0));
Value *count_old = b_.CreateMapLookupElem(map, count_key);
AllocaInst *count_new = b_.CreateAllocaBPF(map.type, map.ident + "_num");
b_.CreateStore(b_.CreateAdd(count_old, b_.getInt64(1)), count_new);
......@@ -198,7 +198,7 @@ void CodegenLLVM::visit(Call &call)
b_.CreateLifetimeEnd(count_key);
b_.CreateLifetimeEnd(count_new);
AllocaInst *total_key = getQuantizeMapKey(map, b_.getInt64(1));
AllocaInst *total_key = getHistMapKey(map, b_.getInt64(1));
Value *total_old = b_.CreateMapLookupElem(map, total_key);
AllocaInst *total_new = b_.CreateAllocaBPF(map.type, map.ident + "_val");
call.vargs->front()->accept(*this);
......@@ -209,13 +209,13 @@ void CodegenLLVM::visit(Call &call)
expr_ = nullptr;
}
else if (call.func == "quantize")
else if (call.func == "hist")
{
Map &map = *call.map;
call.vargs->front()->accept(*this);
Function *log2_func = module_->getFunction("log2");
Value *log2 = b_.CreateCall(log2_func, expr_, "log2");
AllocaInst *key = getQuantizeMapKey(map, log2);
AllocaInst *key = getHistMapKey(map, log2);
Value *oldval = b_.CreateMapLookupElem(map, key);
AllocaInst *newval = b_.CreateAllocaBPF(map.type, map.ident + "_val");
......@@ -250,7 +250,7 @@ void CodegenLLVM::visit(Call &call)
Value *linear = b_.CreateCall(linear_func, {value, min, max, step} , "linear");
AllocaInst *key = getQuantizeMapKey(map, linear);
AllocaInst *key = getHistMapKey(map, linear);
Value *oldval = b_.CreateMapLookupElem(map, key);
AllocaInst *newval = b_.CreateAllocaBPF(map.type, map.ident + "_val");
......@@ -718,7 +718,7 @@ AllocaInst *CodegenLLVM::getMapKey(Map &map)
return key;
}
AllocaInst *CodegenLLVM::getQuantizeMapKey(Map &map, Value *log2)
AllocaInst *CodegenLLVM::getHistMapKey(Map &map, Value *log2)
{
AllocaInst *key;
if (map.vargs) {
......
......@@ -46,7 +46,7 @@ public:
void visit(Include &include) override;
void visit(Program &program) override;
AllocaInst *getMapKey(Map &map);
AllocaInst *getQuantizeMapKey(Map &map, Value *log2);
AllocaInst *getHistMapKey(Map &map, Value *log2);
Value *createLogicalAnd(Binop &binop);
Value *createLogicalOr(Binop &binop);
......
......@@ -82,12 +82,12 @@ void SemanticAnalyser::visit(Call &call)
}
}
if (call.func == "quantize") {
if (call.func == "hist") {
check_assignment(call, true, false);
check_nargs(call, 1);
check_arg(call, Type::integer, 0);
call.type = SizedType(Type::quantize, 8);
call.type = SizedType(Type::hist, 8);
}
else if (call.func == "lhist") {
check_nargs(call, 4);
......
......@@ -380,8 +380,8 @@ int BPFtrace::print_maps()
{
IMap &map = *mapmap.second.get();
int err;
if (map.type_.type == Type::quantize || map.type_.type == Type::lhist)
err = print_map_quantize(map, 0, 0);
if (map.type_.type == Type::hist || map.type_.type == Type::lhist)
err = print_map_hist(map, 0, 0);
else if (map.type_.type == Type::avg || map.type_.type == Type::stats)
err = print_map_stats(map);
else
......@@ -402,8 +402,8 @@ int BPFtrace::print_map_ident(const std::string &ident, uint32_t top, uint32_t d
{
IMap &map = *mapmap.second.get();
if (map.name_ == ident) {
if (map.type_.type == Type::quantize)
err = print_map_quantize(map, top, div);
if (map.type_.type == Type::hist)
err = print_map_hist(map, top, div);
else
err = print_map(map, top, div);
return err;
......@@ -451,8 +451,8 @@ int BPFtrace::clear_map(IMap &map)
std::vector<uint8_t> old_key;
try
{
if (map.type_.type == Type::quantize)
// quantize maps have 8 extra bytes for the bucket number
if (map.type_.type == Type::hist)
// hist maps have 8 extra bytes for the bucket number
old_key = find_empty_key(map, map.key_.size() + 8);
else
old_key = find_empty_key(map, map.key_.size());
......@@ -492,8 +492,8 @@ int BPFtrace::zero_map(IMap &map)
std::vector<uint8_t> old_key;
try
{
if (map.type_.type == Type::quantize)
// quantize maps have 8 extra bytes for the bucket number
if (map.type_.type == Type::hist)
// hist maps have 8 extra bytes for the bucket number
old_key = find_empty_key(map, map.key_.size() + 8);
else
old_key = find_empty_key(map, map.key_.size());
......@@ -632,11 +632,11 @@ int BPFtrace::print_map(IMap &map, uint32_t top, uint32_t div)
return 0;
}
int BPFtrace::print_map_quantize(IMap &map, uint32_t top, uint32_t div)
int BPFtrace::print_map_hist(IMap &map, uint32_t top, uint32_t div)
{
// A quantize-map adds an extra 8 bytes onto the end of its key for storing
// A hist-map adds an extra 8 bytes onto the end of its key for storing
// the bucket number.
// e.g. A map defined as: @x[1, 2] = @quantize(3);
// e.g. A map defined as: @x[1, 2] = @hist(3);
// would actually be stored with the key: [1, 2, 3]
std::vector<uint8_t> old_key;
......@@ -674,7 +674,7 @@ int BPFtrace::print_map_quantize(IMap &map, uint32_t top, uint32_t div)
if (values_by_key.find(key_prefix) == values_by_key.end())
{
// New key - create a list of buckets for it
if (map.type_.type == Type::quantize)
if (map.type_.type == Type::hist)
values_by_key[key_prefix] = std::vector<uint64_t>(65);
else
values_by_key[key_prefix] = std::vector<uint64_t>(1002);
......@@ -716,8 +716,8 @@ int BPFtrace::print_map_quantize(IMap &map, uint32_t top, uint32_t div)
std::cout << map.name_ << map.key_.argument_value_list(*this, key) << ": " << std::endl;
if (map.type_.type == Type::quantize)
print_quantize(value, div);
if (map.type_.type == Type::hist)
print_hist(value, div);
else
print_lhist(value, map.lqmin, map.lqmax, map.lqstep);
......@@ -729,7 +729,7 @@ int BPFtrace::print_map_quantize(IMap &map, uint32_t top, uint32_t div)
int BPFtrace::print_map_stats(IMap &map)
{
// A quantize-map adds an extra 8 bytes onto the end of its key for storing
// A hist-map adds an extra 8 bytes onto the end of its key for storing
// the bucket number.
std::vector<uint8_t> old_key;
......@@ -809,7 +809,7 @@ int BPFtrace::print_map_stats(IMap &map)
return 0;
}
int BPFtrace::print_quantize(const std::vector<uint64_t> &values, uint32_t div) const
int BPFtrace::print_hist(const std::vector<uint64_t> &values, uint32_t div) const
{
int max_index = -1;
int max_value = 0;
......@@ -835,8 +835,8 @@ int BPFtrace::print_quantize(const std::vector<uint64_t> &values, uint32_t div)
}
else
{
header << "[" << quantize_index_label(i);
header << ", " << quantize_index_label(i+1) << ")";
header << "[" << hist_index_label(i);
header << ", " << hist_index_label(i+1) << ")";
}
int max_width = 52;
......@@ -899,7 +899,7 @@ int BPFtrace::print_lhist(const std::vector<uint64_t> &values, int min, int max,
return 0;
}
std::string BPFtrace::quantize_index_label(int power)
std::string BPFtrace::hist_index_label(int power)
{
char suffix = '\0';
if (power >= 40)
......@@ -969,7 +969,7 @@ std::vector<uint8_t> BPFtrace::find_empty_key(IMap &map, size_t size) const
if (size == 0) size = 8;
auto key = std::vector<uint8_t>(size);
int value_size = map.type_.size;
if (map.type_.type == Type::count || map.type_.type == Type::quantize ||
if (map.type_.type == Type::count || map.type_.type == Type::hist ||
map.type_.type == Type::sum || map.type_.type == Type::min ||
map.type_.type == Type::max || map.type_.type == Type::avg ||
map.type_.type == Type::stats)
......
......@@ -70,15 +70,15 @@ private:
int clear_map(IMap &map);
int zero_map(IMap &map);
int print_map(IMap &map, uint32_t top, uint32_t div);
int print_map_quantize(IMap &map, uint32_t top, uint32_t div);
int print_map_hist(IMap &map, uint32_t top, uint32_t div);
int print_map_lhist(IMap &map);
int print_map_stats(IMap &map);
int print_quantize(const std::vector<uint64_t> &values, uint32_t div) const;
int print_hist(const std::vector<uint64_t> &values, uint32_t div) const;
int print_lhist(const std::vector<uint64_t> &values, int min, int max, int step) const;
static uint64_t reduce_value(const std::vector<uint8_t> &value, int ncpus);
static uint64_t min_value(const std::vector<uint8_t> &value, int ncpus);
static uint64_t max_value(const std::vector<uint8_t> &value, int ncpus);
static std::string quantize_index_label(int power);
static std::string hist_index_label(int power);
std::vector<uint8_t> find_empty_key(IMap &map, size_t size) const;
};
......
......@@ -20,7 +20,7 @@ Map::Map(const std::string &name, const SizedType &type, const MapKey &key, int
lqstep = step;
int key_size = key.size();
if (type.type == Type::quantize || type.type == Type::lhist ||
if (type.type == Type::hist || type.type == Type::lhist ||
type.type == Type::avg || type.type == Type::stats)
key_size += 8;
if (key_size == 0)
......@@ -28,7 +28,7 @@ Map::Map(const std::string &name, const SizedType &type, const MapKey &key, int
int max_entries = 128;
enum bpf_map_type map_type;
if ((type.type == Type::quantize || type.type == Type::lhist || type.type == Type::count ||
if ((type.type == Type::hist || type.type == Type::lhist || type.type == Type::count ||
type.type == Type::sum || type.type == Type::min || type.type == Type::max ||
type.type == Type::avg || type.type == Type::stats) &&
(LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0)))
......
......@@ -27,7 +27,7 @@ std::string typestr(Type t)
{
case Type::none: return "none"; break;
case Type::integer: return "integer"; break;
case Type::quantize: return "quantize"; break;
case Type::hist: return "hist"; break;
case Type::lhist: return "lhist"; break;
case Type::count: return "count"; break;
case Type::sum: return "sum"; break;
......
......@@ -15,7 +15,7 @@ enum class Type
{
none,
integer,
quantize,
hist,
lhist,
count,
sum,
......
......@@ -709,9 +709,9 @@ attributes #1 = { argmemonly nounwind }
)EXPECTED");
}
TEST(codegen, call_quantize)
TEST(codegen, call_hist)
{
test("kprobe:f { @x = quantize(pid) }",
test("kprobe:f { @x = hist(pid) }",
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
......
......@@ -221,7 +221,7 @@ TEST(Parser, expressions)
TEST(Parser, call)
{
test("kprobe:sys_open { @x = count(); @y = quantize(1,2,3); delete(@x); }",
test("kprobe:sys_open { @x = count(); @y = hist(1,2,3); delete(@x); }",
"Program\n"
" kprobe:sys_open\n"
" =\n"
......@@ -229,7 +229,7 @@ TEST(Parser, call)
" call: count\n"
" =\n"
" map: @y\n"
" call: quantize\n"
" call: hist\n"
" int: 1\n"
" int: 2\n"
" int: 3\n"
......
......@@ -78,7 +78,7 @@ TEST(semantic_analyser, builtin_variables)
TEST(semantic_analyser, builtin_functions)
{
test("kprobe:f { @x = quantize(123) }", 0);
test("kprobe:f { @x = hist(123) }", 0);
test("kprobe:f { @x = count() }", 0);
test("kprobe:f { @x = sum(pid) }", 0);
test("kprobe:f { @x = min(pid) }", 0);
......@@ -129,14 +129,14 @@ TEST(semantic_analyser, mismatched_call_types)
{
test("kprobe:f { @x = 1; @x = count(); }", 1);
test("kprobe:f { @x = count(); @x = sum(pid); }", 1);
test("kprobe:f { @x = 1; @x = quantize(0); }", 1);
test("kprobe:f { @x = 1; @x = hist(0); }", 1);
}
TEST(semantic_analyser, call_quantize)
TEST(semantic_analyser, call_hist)
{
test("kprobe:f { @x = quantize(1); }", 0);
test("kprobe:f { @x = quantize(); }", 1);
test("kprobe:f { quantize(); }", 1);
test("kprobe:f { @x = hist(1); }", 0);
test("kprobe:f { @x = hist(); }", 1);
test("kprobe:f { hist(); }", 1);
}
TEST(semantic_analyser, call_count)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment