Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
B
bcc
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
bcc
Commits
b1e3b670
Commit
b1e3b670
authored
Sep 24, 2015
by
Brenden Blanco
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #247 from iovisor/bblanco_dev
Add BPF_HISTOGRAM type and print support
parents
4037b4df
6255f1f0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
194 additions
and
35 deletions
+194
-35
src/cc/export/helpers.h
src/cc/export/helpers.h
+14
-0
src/cc/frontends/clang/b_frontend_action.cc
src/cc/frontends/clang/b_frontend_action.cc
+51
-8
src/cc/frontends/clang/b_frontend_action.h
src/cc/frontends/clang/b_frontend_action.h
+2
-0
src/python/bcc/__init__.py
src/python/bcc/__init__.py
+49
-23
tests/cc/CMakeLists.txt
tests/cc/CMakeLists.txt
+2
-0
tests/cc/test_histogram.py
tests/cc/test_histogram.py
+74
-0
tools/biolatency
tools/biolatency
+2
-4
No files found.
src/cc/export/helpers.h
View file @
b1e3b670
...
@@ -36,6 +36,7 @@ struct _name##_table_t { \
...
@@ -36,6 +36,7 @@ struct _name##_table_t { \
int (*update) (_key_type *, _leaf_type *); \
int (*update) (_key_type *, _leaf_type *); \
int (*delete) (_key_type *); \
int (*delete) (_key_type *); \
void (*call) (void *, int index); \
void (*call) (void *, int index); \
void (*increment) (_key_type); \
_leaf_type data[_max_entries]; \
_leaf_type data[_max_entries]; \
}; \
}; \
__attribute__((section("maps/" _table_type))) \
__attribute__((section("maps/" _table_type))) \
...
@@ -55,6 +56,19 @@ struct _name##_table_t _name
...
@@ -55,6 +56,19 @@ struct _name##_table_t _name
#define BPF_HASH(...) \
#define BPF_HASH(...) \
BPF_HASHX(__VA_ARGS__, BPF_HASH3, BPF_HASH2, BPF_HASH1)(__VA_ARGS__)
BPF_HASHX(__VA_ARGS__, BPF_HASH3, BPF_HASH2, BPF_HASH1)(__VA_ARGS__)
#define BPF_HIST1(_name) \
BPF_TABLE("histogram", int, u64, _name, 64)
#define BPF_HIST2(_name, _key_type) \
BPF_TABLE("histogram", _key_type, u64, _name, 64)
#define BPF_HIST3(_name, _key_type, _size) \
BPF_TABLE("histogram", _key_type, u64, _name, _size)
#define BPF_HISTX(_1, _2, _3, NAME, ...) NAME
// Define a histogram, some arguments optional
// BPF_HISTOGRAM(name, key_type=int, size=64)
#define BPF_HISTOGRAM(...) \
BPF_HISTX(__VA_ARGS__, BPF_HIST3, BPF_HIST2, BPF_HIST1)(__VA_ARGS__)
// packet parsing state machine helpers
// packet parsing state machine helpers
#define cursor_advance(_cursor, _len) \
#define cursor_advance(_cursor, _len) \
({ void *_tmp = _cursor; _cursor += _len; _tmp; })
({ void *_tmp = _cursor; _cursor += _len; _tmp; })
...
...
src/cc/frontends/clang/b_frontend_action.cc
View file @
b1e3b670
...
@@ -67,9 +67,11 @@ bool BMapDeclVisitor::VisitRecordDecl(RecordDecl *D) {
...
@@ -67,9 +67,11 @@ bool BMapDeclVisitor::VisitRecordDecl(RecordDecl *D) {
for
(
auto
F
:
D
->
getDefinition
()
->
fields
())
{
for
(
auto
F
:
D
->
getDefinition
()
->
fields
())
{
result_
+=
"["
;
result_
+=
"["
;
if
(
F
->
getType
()
->
isPointerType
())
if
(
F
->
getType
()
->
isPointerType
())
result_
+=
"
\"
unsigned long long
\"
"
;
result_
+=
"
\"
"
+
F
->
getName
().
str
()
+
"
\"
,
\"
unsigned long long
\"
"
;
else
else
TraverseDecl
(
F
);
TraverseDecl
(
F
);
if
(
const
ConstantArrayType
*
T
=
dyn_cast
<
ConstantArrayType
>
(
F
->
getType
()))
result_
+=
", ["
+
T
->
getSize
().
toString
(
10
,
false
)
+
"]"
;
if
(
F
->
isBitField
())
if
(
F
->
isBitField
())
result_
+=
", "
+
to_string
(
F
->
getBitWidthValue
(
C
));
result_
+=
", "
+
to_string
(
F
->
getBitWidthValue
(
C
));
result_
+=
"], "
;
result_
+=
"], "
;
...
@@ -158,6 +160,23 @@ bool ProbeVisitor::VisitBinaryOperator(BinaryOperator *E) {
...
@@ -158,6 +160,23 @@ bool ProbeVisitor::VisitBinaryOperator(BinaryOperator *E) {
}
}
return
true
;
return
true
;
}
}
bool
ProbeVisitor
::
VisitUnaryOperator
(
UnaryOperator
*
E
)
{
if
(
E
->
getOpcode
()
!=
UO_Deref
)
return
true
;
if
(
memb_visited_
.
find
(
E
)
!=
memb_visited_
.
end
())
return
true
;
if
(
!
ProbeChecker
(
E
,
ptregs_
).
needs_probe
())
return
true
;
memb_visited_
.
insert
(
E
);
Expr
*
sub
=
E
->
getSubExpr
();
string
rhs
=
rewriter_
.
getRewrittenText
(
SourceRange
(
sub
->
getLocStart
(),
sub
->
getLocEnd
()));
string
text
;
text
=
"({ typeof("
+
E
->
getType
().
getAsString
()
+
") _val; memset(&_val, 0, sizeof(_val));"
;
text
+=
" bpf_probe_read(&_val, sizeof(_val), (u64)"
;
text
+=
rhs
+
"); _val; })"
;
rewriter_
.
ReplaceText
(
SourceRange
(
E
->
getLocStart
(),
E
->
getLocEnd
()),
text
);
return
true
;
}
bool
ProbeVisitor
::
VisitMemberExpr
(
MemberExpr
*
E
)
{
bool
ProbeVisitor
::
VisitMemberExpr
(
MemberExpr
*
E
)
{
if
(
memb_visited_
.
find
(
E
)
!=
memb_visited_
.
end
())
return
true
;
if
(
memb_visited_
.
find
(
E
)
!=
memb_visited_
.
end
())
return
true
;
...
@@ -194,7 +213,7 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) {
...
@@ -194,7 +213,7 @@ bool ProbeVisitor::VisitMemberExpr(MemberExpr *E) {
}
}
BTypeVisitor
::
BTypeVisitor
(
ASTContext
&
C
,
Rewriter
&
rewriter
,
vector
<
TableDesc
>
&
tables
)
BTypeVisitor
::
BTypeVisitor
(
ASTContext
&
C
,
Rewriter
&
rewriter
,
vector
<
TableDesc
>
&
tables
)
:
C
(
C
),
rewriter_
(
rewriter
),
out_
(
llvm
::
errs
()),
tables_
(
tables
)
{
:
C
(
C
),
diag_
(
C
.
getDiagnostics
()),
rewriter_
(
rewriter
),
out_
(
llvm
::
errs
()),
tables_
(
tables
)
{
}
}
bool
BTypeVisitor
::
VisitFunctionDecl
(
FunctionDecl
*
D
)
{
bool
BTypeVisitor
::
VisitFunctionDecl
(
FunctionDecl
*
D
)
{
...
@@ -276,7 +295,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
...
@@ -276,7 +295,7 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
string
map_update_policy
=
"BPF_ANY"
;
string
map_update_policy
=
"BPF_ANY"
;
string
txt
;
string
txt
;
if
(
memb_name
==
"lookup_or_init"
)
{
if
(
memb_name
==
"lookup_or_init"
)
{
string
map_update_policy
=
"BPF_NOEXIST"
;
map_update_policy
=
"BPF_NOEXIST"
;
string
name
=
Ref
->
getDecl
()
->
getName
();
string
name
=
Ref
->
getDecl
()
->
getName
();
string
arg0
=
rewriter_
.
getRewrittenText
(
SourceRange
(
Call
->
getArg
(
0
)
->
getLocStart
(),
string
arg0
=
rewriter_
.
getRewrittenText
(
SourceRange
(
Call
->
getArg
(
0
)
->
getLocStart
(),
Call
->
getArg
(
0
)
->
getLocEnd
()));
Call
->
getArg
(
0
)
->
getLocEnd
()));
...
@@ -291,6 +310,19 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
...
@@ -291,6 +310,19 @@ bool BTypeVisitor::VisitCallExpr(CallExpr *Call) {
txt
+=
" if (!leaf) return 0;"
;
txt
+=
" if (!leaf) return 0;"
;
txt
+=
"}"
;
txt
+=
"}"
;
txt
+=
"leaf;})"
;
txt
+=
"leaf;})"
;
}
else
if
(
memb_name
==
"increment"
)
{
string
name
=
Ref
->
getDecl
()
->
getName
();
string
arg0
=
rewriter_
.
getRewrittenText
(
SourceRange
(
Call
->
getArg
(
0
)
->
getLocStart
(),
Call
->
getArg
(
0
)
->
getLocEnd
()));
string
lookup
=
"bpf_map_lookup_elem_(bpf_pseudo_fd(1, "
+
fd
+
")"
;
string
update
=
"bpf_map_update_elem_(bpf_pseudo_fd(1, "
+
fd
+
")"
;
txt
=
"({ typeof("
+
name
+
".key) _key = "
+
arg0
+
"; "
;
if
(
table_it
->
type
==
BPF_MAP_TYPE_HASH
)
{
txt
+=
"typeof("
+
name
+
".leaf) _zleaf; memset(&_zleaf, 0, sizeof(_zleaf)); "
;
txt
+=
update
+
", &_key, &_zleaf, BPF_NOEXIST); "
;
}
txt
+=
"typeof("
+
name
+
".leaf) *_leaf = "
+
lookup
+
", &_key); "
;
txt
+=
"if (_leaf) (*_leaf)++; })"
;
}
else
{
}
else
{
if
(
memb_name
==
"lookup"
)
{
if
(
memb_name
==
"lookup"
)
{
prefix
=
"bpf_map_lookup_elem"
;
prefix
=
"bpf_map_lookup_elem"
;
...
@@ -463,11 +495,21 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
...
@@ -463,11 +495,21 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
++
i
;
++
i
;
}
}
bpf_map_type
map_type
=
BPF_MAP_TYPE_UNSPEC
;
bpf_map_type
map_type
=
BPF_MAP_TYPE_UNSPEC
;
if
(
A
->
getName
()
==
"maps/hash"
)
if
(
A
->
getName
()
==
"maps/hash"
)
{
map_type
=
BPF_MAP_TYPE_HASH
;
map_type
=
BPF_MAP_TYPE_HASH
;
else
if
(
A
->
getName
()
==
"maps/array"
)
}
else
if
(
A
->
getName
()
==
"maps/array"
)
{
map_type
=
BPF_MAP_TYPE_ARRAY
;
map_type
=
BPF_MAP_TYPE_ARRAY
;
else
if
(
A
->
getName
()
==
"maps/prog"
)
{
}
else
if
(
A
->
getName
()
==
"maps/histogram"
)
{
if
(
table
.
key_desc
==
"
\"
int
\"
"
)
map_type
=
BPF_MAP_TYPE_ARRAY
;
else
map_type
=
BPF_MAP_TYPE_HASH
;
if
(
table
.
leaf_desc
!=
"
\"
unsigned long long
\"
"
)
{
unsigned
diag_id
=
diag_
.
getCustomDiagID
(
DiagnosticsEngine
::
Error
,
"histogram leaf type must be u64, got %0"
);
diag_
.
Report
(
Decl
->
getLocStart
(),
diag_id
)
<<
table
.
leaf_desc
;
}
}
else
if
(
A
->
getName
()
==
"maps/prog"
)
{
struct
utsname
un
;
struct
utsname
un
;
if
(
uname
(
&
un
)
==
0
)
{
if
(
uname
(
&
un
)
==
0
)
{
int
major
=
0
,
minor
=
0
;
int
major
=
0
,
minor
=
0
;
...
@@ -485,8 +527,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
...
@@ -485,8 +527,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
table
.
type
=
map_type
;
table
.
type
=
map_type
;
table
.
fd
=
bpf_create_map
(
map_type
,
table
.
key_size
,
table
.
leaf_size
,
table
.
max_entries
);
table
.
fd
=
bpf_create_map
(
map_type
,
table
.
key_size
,
table
.
leaf_size
,
table
.
max_entries
);
if
(
table
.
fd
<
0
)
{
if
(
table
.
fd
<
0
)
{
C
.
getDiagnostics
().
Report
(
Decl
->
getLocStart
(),
diag
::
err_expected
)
unsigned
diag_id
=
C
.
getDiagnostics
().
getCustomDiagID
(
DiagnosticsEngine
::
Error
,
<<
"valid bpf fd"
;
"could not open bpf map: %0"
);
C
.
getDiagnostics
().
Report
(
Decl
->
getLocStart
(),
diag_id
)
<<
strerror
(
errno
);
return
false
;
return
false
;
}
}
tables_
.
push_back
(
std
::
move
(
table
));
tables_
.
push_back
(
std
::
move
(
table
));
...
...
src/cc/frontends/clang/b_frontend_action.h
View file @
b1e3b670
...
@@ -71,6 +71,7 @@ class BTypeVisitor : public clang::RecursiveASTVisitor<BTypeVisitor> {
...
@@ -71,6 +71,7 @@ class BTypeVisitor : public clang::RecursiveASTVisitor<BTypeVisitor> {
private:
private:
clang
::
ASTContext
&
C
;
clang
::
ASTContext
&
C
;
clang
::
DiagnosticsEngine
&
diag_
;
clang
::
Rewriter
&
rewriter_
;
/// modifications to the source go into this class
clang
::
Rewriter
&
rewriter_
;
/// modifications to the source go into this class
llvm
::
raw_ostream
&
out_
;
/// for debugging
llvm
::
raw_ostream
&
out_
;
/// for debugging
std
::
vector
<
TableDesc
>
&
tables_
;
/// store the open FDs
std
::
vector
<
TableDesc
>
&
tables_
;
/// store the open FDs
...
@@ -85,6 +86,7 @@ class ProbeVisitor : public clang::RecursiveASTVisitor<ProbeVisitor> {
...
@@ -85,6 +86,7 @@ class ProbeVisitor : public clang::RecursiveASTVisitor<ProbeVisitor> {
bool
VisitVarDecl
(
clang
::
VarDecl
*
Decl
);
bool
VisitVarDecl
(
clang
::
VarDecl
*
Decl
);
bool
VisitCallExpr
(
clang
::
CallExpr
*
Call
);
bool
VisitCallExpr
(
clang
::
CallExpr
*
Call
);
bool
VisitBinaryOperator
(
clang
::
BinaryOperator
*
E
);
bool
VisitBinaryOperator
(
clang
::
BinaryOperator
*
E
);
bool
VisitUnaryOperator
(
clang
::
UnaryOperator
*
E
);
bool
VisitMemberExpr
(
clang
::
MemberExpr
*
E
);
bool
VisitMemberExpr
(
clang
::
MemberExpr
*
E
);
void
set_ptreg
(
clang
::
Decl
*
D
)
{
ptregs_
.
insert
(
D
);
}
void
set_ptreg
(
clang
::
Decl
*
D
)
{
ptregs_
.
insert
(
D
);
}
private:
private:
...
...
src/python/bcc/__init__.py
View file @
b1e3b670
...
@@ -99,7 +99,7 @@ KALLSYMS = "/proc/kallsyms"
...
@@ -99,7 +99,7 @@ KALLSYMS = "/proc/kallsyms"
ksym_addrs
=
[]
ksym_addrs
=
[]
ksym_names
=
[]
ksym_names
=
[]
ksym_loaded
=
0
ksym_loaded
=
0
stars_max
=
38
stars_max
=
40
@
atexit
.
register
@
atexit
.
register
def
cleanup_kprobes
():
def
cleanup_kprobes
():
...
@@ -238,38 +238,60 @@ class BPF(object):
...
@@ -238,38 +238,60 @@ class BPF(object):
text
=
text
[:
-
1
]
+
"+"
text
=
text
[:
-
1
]
+
"+"
return
text
return
text
def
print_log2_hist
(
self
,
val_type
=
"value"
):
def
print_log2_hist
(
self
,
val_type
=
"value"
,
bucket_type
=
"ptr"
):
"""print_log2_hist(
type=value
)
"""print_log2_hist(
val_type="value", bucket_type="ptr"
)
Prints a table as a log2 histogram. The table must be stored as
Prints a table as a log2 histogram. The table must be stored as
log2. The type argument is optional, and is a column header.
log2. The val_type argument is optional, and is a column header.
If the histogram has a secondary key, multiple tables will print
and bucket_type can be used as a header description for each.
"""
"""
if
isinstance
(
self
.
Key
(),
ct
.
Structure
):
tmp
=
{}
f1
=
self
.
Key
.
_fields_
[
0
][
0
]
f2
=
self
.
Key
.
_fields_
[
1
][
0
]
for
k
,
v
in
self
.
items
():
bucket
=
getattr
(
k
,
f1
)
vals
=
tmp
[
bucket
]
=
tmp
.
get
(
bucket
,
[
0
]
*
65
)
slot
=
getattr
(
k
,
f2
)
vals
[
slot
]
=
v
.
value
for
bucket
,
vals
in
tmp
.
items
():
print
(
"
\
n
Bucket %s = %r"
%
(
bucket_type
,
bucket
))
self
.
_print_log2_hist
(
vals
,
val_type
,
0
)
else
:
vals
=
[
0
]
*
65
for
k
,
v
in
self
.
items
():
vals
[
k
.
value
]
=
v
.
value
self
.
_print_log2_hist
(
vals
,
val_type
,
0
)
def
_print_log2_hist
(
self
,
vals
,
val_type
,
val_max
):
global
stars_max
global
stars_max
log2_dist_max
=
64
log2_dist_max
=
64
idx_max
=
-
1
idx_max
=
-
1
val_max
=
0
for
i
in
range
(
1
,
log2_dist_max
+
1
):
for
i
,
v
in
enumerate
(
vals
):
try
:
if
v
>
0
:
idx_max
=
i
val
=
self
[
ct
.
c_int
(
i
)].
value
if
v
>
val_max
:
val_max
=
v
if
(
val
>
0
):
idx_max
=
i
if
idx_max
<=
32
:
if
(
val
>
val_max
):
header
=
" %-19s : count distribution"
val_max
=
val
body
=
"%10d -> %-10d : %-8d |%-*s|"
except
:
stars
=
stars_max
break
else
:
header
=
" %-29s : count distribution"
body
=
"%20d -> %-20d : %-8d |%-*s|"
stars
=
int
(
stars_max
/
2
)
if
idx_max
>
0
:
if
idx_max
>
0
:
print
(
" %-15s : count distribution"
%
val_type
);
print
(
header
%
val_type
);
for
i
in
range
(
1
,
idx_max
+
1
):
for
i
in
range
(
1
,
idx_max
+
1
):
low
=
(
1
<<
i
)
>>
1
low
=
(
1
<<
i
)
>>
1
high
=
(
1
<<
i
)
-
1
high
=
(
1
<<
i
)
-
1
if
(
low
==
high
):
if
(
low
==
high
):
low
-=
1
low
-=
1
try
:
val
=
vals
[
i
]
val
=
self
[
ct
.
c_int
(
i
)].
value
print
(
body
%
(
low
,
high
,
val
,
stars
,
print
(
"%8d -> %-8d : %-8d |%-*s|"
%
(
low
,
high
,
val
,
self
.
_stars
(
val
,
val_max
,
stars
)))
stars_max
,
self
.
_stars
(
val
,
val_max
,
stars_max
)))
except
:
break
def
__iter__
(
self
):
def
__iter__
(
self
):
...
@@ -407,7 +429,6 @@ class BPF(object):
...
@@ -407,7 +429,6 @@ class BPF(object):
u"_Bool"
:
ct
.
c_bool
,
u"_Bool"
:
ct
.
c_bool
,
u"char"
:
ct
.
c_char
,
u"char"
:
ct
.
c_char
,
u"wchar_t"
:
ct
.
c_wchar
,
u"wchar_t"
:
ct
.
c_wchar
,
u"char"
:
ct
.
c_byte
,
u"unsigned char"
:
ct
.
c_ubyte
,
u"unsigned char"
:
ct
.
c_ubyte
,
u"short"
:
ct
.
c_short
,
u"short"
:
ct
.
c_short
,
u"unsigned short"
:
ct
.
c_ushort
,
u"unsigned short"
:
ct
.
c_ushort
,
...
@@ -430,7 +451,12 @@ class BPF(object):
...
@@ -430,7 +451,12 @@ class BPF(object):
if
len
(
t
)
==
2
:
if
len
(
t
)
==
2
:
fields
.
append
((
t
[
0
],
BPF
.
_decode_table_type
(
t
[
1
])))
fields
.
append
((
t
[
0
],
BPF
.
_decode_table_type
(
t
[
1
])))
elif
len
(
t
)
==
3
:
elif
len
(
t
)
==
3
:
fields
.
append
((
t
[
0
],
BPF
.
_decode_table_type
(
t
[
1
]),
t
[
2
]))
if
isinstance
(
t
[
2
],
list
):
fields
.
append
((
t
[
0
],
BPF
.
_decode_table_type
(
t
[
1
])
*
t
[
2
][
0
]))
else
:
fields
.
append
((
t
[
0
],
BPF
.
_decode_table_type
(
t
[
1
]),
t
[
2
]))
else
:
raise
Exception
(
"Failed to decode type %s"
%
str
(
t
))
cls
=
type
(
str
(
desc
[
0
]),
(
ct
.
Structure
,),
dict
(
_fields_
=
fields
))
cls
=
type
(
str
(
desc
[
0
]),
(
ct
.
Structure
,),
dict
(
_fields_
=
fields
))
return
cls
return
cls
...
...
tests/cc/CMakeLists.txt
View file @
b1e3b670
...
@@ -38,3 +38,5 @@ add_test(NAME py_test_brb2 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
...
@@ -38,3 +38,5 @@ add_test(NAME py_test_brb2 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
COMMAND
${
TEST_WRAPPER
}
py_brb2_c sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_brb2.py test_brb2.c
)
COMMAND
${
TEST_WRAPPER
}
py_brb2_c sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_brb2.py test_brb2.c
)
add_test
(
NAME py_test_clang WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
add_test
(
NAME py_test_clang WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
COMMAND
${
TEST_WRAPPER
}
py_clang sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_clang.py
)
COMMAND
${
TEST_WRAPPER
}
py_clang sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_clang.py
)
add_test
(
NAME py_test_histogram WORKING_DIRECTORY
${
CMAKE_CURRENT_SOURCE_DIR
}
COMMAND
${
TEST_WRAPPER
}
py_histogram sudo
${
CMAKE_CURRENT_SOURCE_DIR
}
/test_histogram.py
)
tests/cc/test_histogram.py
0 → 100755
View file @
b1e3b670
#!/usr/bin/env python
# Copyright (c) PLUMgrid, Inc.
# Licensed under the Apache License, Version 2.0 (the "License")
from
bcc
import
BPF
from
ctypes
import
c_int
,
c_ulonglong
import
random
import
time
from
unittest
import
main
,
TestCase
class
TestHistogram
(
TestCase
):
def
test_simple
(
self
):
b
=
BPF
(
text
=
"""
#include <uapi/linux/ptrace.h>
#include <linux/bpf.h>
BPF_HISTOGRAM(hist1);
BPF_HASH(stub);
int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) {
hist1.increment(bpf_log2l(*k));
return 0;
}
"""
)
for
i
in
range
(
0
,
32
):
for
j
in
range
(
0
,
random
.
randint
(
1
,
10
)):
try
:
del
b
[
"stub"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
b
[
"hist1"
].
print_log2_hist
()
for
i
in
range
(
32
,
64
):
for
j
in
range
(
0
,
random
.
randint
(
1
,
10
)):
try
:
del
b
[
"stub"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
b
[
"hist1"
].
print_log2_hist
()
def
test_struct
(
self
):
b
=
BPF
(
text
=
"""
#include <uapi/linux/ptrace.h>
#include <linux/bpf.h>
typedef struct { void *map; u64 slot; } Key;
BPF_HISTOGRAM(hist1, Key, 1024);
BPF_HASH(stub1);
BPF_HASH(stub2);
int kprobe__htab_map_delete_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) {
hist1.increment((Key){map, bpf_log2l(*k)});
return 0;
}
"""
)
for
i
in
range
(
0
,
64
):
for
j
in
range
(
0
,
random
.
randint
(
1
,
10
)):
try
:
del
b
[
"stub1"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
try
:
del
b
[
"stub2"
][
c_ulonglong
(
1
<<
i
)]
except
:
pass
b
[
"hist1"
].
print_log2_hist
()
def
test_chars
(
self
):
b
=
BPF
(
text
=
"""
#include <uapi/linux/ptrace.h>
#include <linux/sched.h>
typedef struct { char name[TASK_COMM_LEN]; u64 slot; } Key;
BPF_HISTOGRAM(hist1, Key, 1024);
int kprobe__finish_task_switch(struct pt_regs *ctx, struct task_struct *prev) {
Key k = {.slot = bpf_log2l(prev->real_start_time)};
if (!bpf_get_current_comm(&k.name, sizeof(k.name)))
hist1.increment(k);
return 0;
}
"""
)
for
i
in
range
(
0
,
100
):
time
.
sleep
(
0.01
)
b
[
"hist1"
].
print_log2_hist
()
if
__name__
==
"__main__"
:
main
()
tools/biolatency
View file @
b1e3b670
...
@@ -45,7 +45,7 @@ bpf_text = """
...
@@ -45,7 +45,7 @@ bpf_text = """
#include <uapi/linux/ptrace.h>
#include <uapi/linux/ptrace.h>
#include <linux/blkdev.h>
#include <linux/blkdev.h>
BPF_
TABLE(
\
"
array
\
"
, int, u64, dist, 64
);
BPF_
HISTOGRAM(dist
);
BPF_HASH(start, struct request *);
BPF_HASH(start, struct request *);
// time block I/O
// time block I/O
...
@@ -70,9 +70,7 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req)
...
@@ -70,9 +70,7 @@ int trace_req_completion(struct pt_regs *ctx, struct request *req)
FACTOR
FACTOR
// store as histogram
// store as histogram
int index = bpf_log2l(delta);
dist.increment(bpf_log2l(delta));
u64 *leaf = dist.lookup(&index);
if (leaf) (*leaf)++;
start.delete(&req);
start.delete(&req);
return 0;
return 0;
...
...
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