Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bpftrace
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
bpftrace
Commits
282748b0
Commit
282748b0
authored
Aug 28, 2018
by
Brendan Gregg
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rename to hist()
parent
6bdd1198
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
50 additions
and
50 deletions
+50
-50
INSTALL.md
INSTALL.md
+1
-1
README.md
README.md
+2
-2
src/ast/codegen_llvm.cpp
src/ast/codegen_llvm.cpp
+7
-7
src/ast/codegen_llvm.h
src/ast/codegen_llvm.h
+1
-1
src/ast/semantic_analyser.cpp
src/ast/semantic_analyser.cpp
+2
-2
src/bpftrace.cpp
src/bpftrace.cpp
+20
-20
src/bpftrace.h
src/bpftrace.h
+3
-3
src/map.cpp
src/map.cpp
+2
-2
src/types.cpp
src/types.cpp
+1
-1
src/types.h
src/types.h
+1
-1
tests/codegen.cpp
tests/codegen.cpp
+2
-2
tests/parser.cpp
tests/parser.cpp
+2
-2
tests/semantic_analyser.cpp
tests/semantic_analyser.cpp
+6
-6
No files found.
INSTALL.md
View file @
282748b0
...
...
@@ -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
...
...
README.md
View file @
282748b0
...
...
@@ -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
...
...
src/ast/codegen_llvm.cpp
View file @
282748b0
...
...
@@ -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
=
get
Quantize
MapKey
(
map
,
b_
.
getInt64
(
0
));
AllocaInst
*
count_key
=
get
Hist
MapKey
(
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
=
get
Quantize
MapKey
(
map
,
b_
.
getInt64
(
1
));
AllocaInst
*
total_key
=
get
Hist
MapKey
(
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
=
get
Quantize
MapKey
(
map
,
log2
);
AllocaInst
*
key
=
get
Hist
MapKey
(
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
=
get
Quantize
MapKey
(
map
,
linear
);
AllocaInst
*
key
=
get
Hist
MapKey
(
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
::
get
Quantize
MapKey
(
Map
&
map
,
Value
*
log2
)
AllocaInst
*
CodegenLLVM
::
get
Hist
MapKey
(
Map
&
map
,
Value
*
log2
)
{
AllocaInst
*
key
;
if
(
map
.
vargs
)
{
...
...
src/ast/codegen_llvm.h
View file @
282748b0
...
...
@@ -46,7 +46,7 @@ public:
void
visit
(
Include
&
include
)
override
;
void
visit
(
Program
&
program
)
override
;
AllocaInst
*
getMapKey
(
Map
&
map
);
AllocaInst
*
get
Quantize
MapKey
(
Map
&
map
,
Value
*
log2
);
AllocaInst
*
get
Hist
MapKey
(
Map
&
map
,
Value
*
log2
);
Value
*
createLogicalAnd
(
Binop
&
binop
);
Value
*
createLogicalOr
(
Binop
&
binop
);
...
...
src/ast/semantic_analyser.cpp
View file @
282748b0
...
...
@@ -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
);
...
...
src/bpftrace.cpp
View file @
282748b0
...
...
@@ -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
)
...
...
src/bpftrace.h
View file @
282748b0
...
...
@@ -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
;
};
...
...
src/map.cpp
View file @
282748b0
...
...
@@ -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
)))
...
...
src/types.cpp
View file @
282748b0
...
...
@@ -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
;
...
...
src/types.h
View file @
282748b0
...
...
@@ -15,7 +15,7 @@ enum class Type
{
none
,
integer
,
quantize
,
hist
,
lhist
,
count
,
sum
,
...
...
tests/codegen.cpp
View file @
282748b0
...
...
@@ -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
...
...
tests/parser.cpp
View file @
282748b0
...
...
@@ -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
"
...
...
tests/semantic_analyser.cpp
View file @
282748b0
...
...
@@ -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
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment