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
64258256
Commit
64258256
authored
Mar 29, 2016
by
Zaafar Ahmed
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
optimised the percpu support patch.
removed kernel checks.
parent
b0e40388
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
90 additions
and
100 deletions
+90
-100
src/cc/frontends/clang/b_frontend_action.cc
src/cc/frontends/clang/b_frontend_action.cc
+2
-4
src/python/bcc/__init__.py
src/python/bcc/__init__.py
+2
-2
src/python/bcc/table.py
src/python/bcc/table.py
+86
-94
No files found.
src/cc/frontends/clang/b_frontend_action.cc
View file @
64258256
...
@@ -571,11 +571,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
...
@@ -571,11 +571,9 @@ bool BTypeVisitor::VisitVarDecl(VarDecl *Decl) {
}
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/pc_hash"
)
{
}
else
if
(
A
->
getName
()
==
"maps/pc_hash"
)
{
if
(
KERNEL_VERSION
(
major
,
minor
,
0
)
>=
KERNEL_VERSION
(
4
,
5
,
0
))
map_type
=
BPF_MAP_TYPE_PERCPU_HASH
;
map_type
=
BPF_MAP_TYPE_PERCPU_HASH
;
}
else
if
(
A
->
getName
()
==
"maps/pc_array"
)
{
}
else
if
(
A
->
getName
()
==
"maps/pc_array"
)
{
if
(
KERNEL_VERSION
(
major
,
minor
,
0
)
>=
KERNEL_VERSION
(
4
,
5
,
0
))
map_type
=
BPF_MAP_TYPE_PERCPU_ARRAY
;
map_type
=
BPF_MAP_TYPE_PERCPU_ARRAY
;
}
else
if
(
A
->
getName
()
==
"maps/histogram"
)
{
}
else
if
(
A
->
getName
()
==
"maps/histogram"
)
{
if
(
table
.
key_desc
==
"
\"
int
\"
"
)
if
(
table
.
key_desc
==
"
\"
int
\"
"
)
map_type
=
BPF_MAP_TYPE_ARRAY
;
map_type
=
BPF_MAP_TYPE_ARRAY
;
...
...
src/python/bcc/__init__.py
View file @
64258256
...
@@ -228,7 +228,7 @@ class BPF(object):
...
@@ -228,7 +228,7 @@ class BPF(object):
cls
=
type
(
str
(
desc
[
0
]),
(
base
,),
dict
(
_fields_
=
fields
))
cls
=
type
(
str
(
desc
[
0
]),
(
base
,),
dict
(
_fields_
=
fields
))
return
cls
return
cls
def
get_table
(
self
,
name
,
keytype
=
None
,
leaftype
=
None
,
func_
reducer
=
None
):
def
get_table
(
self
,
name
,
keytype
=
None
,
leaftype
=
None
,
reducer
=
None
):
map_id
=
lib
.
bpf_table_id
(
self
.
module
,
name
.
encode
(
"ascii"
))
map_id
=
lib
.
bpf_table_id
(
self
.
module
,
name
.
encode
(
"ascii"
))
map_fd
=
lib
.
bpf_table_fd
(
self
.
module
,
name
.
encode
(
"ascii"
))
map_fd
=
lib
.
bpf_table_fd
(
self
.
module
,
name
.
encode
(
"ascii"
))
if
map_fd
<
0
:
if
map_fd
<
0
:
...
@@ -243,7 +243,7 @@ class BPF(object):
...
@@ -243,7 +243,7 @@ class BPF(object):
if
not
leaf_desc
:
if
not
leaf_desc
:
raise
Exception
(
"Failed to load BPF Table %s leaf desc"
%
name
)
raise
Exception
(
"Failed to load BPF Table %s leaf desc"
%
name
)
leaftype
=
BPF
.
_decode_table_type
(
json
.
loads
(
leaf_desc
.
decode
()))
leaftype
=
BPF
.
_decode_table_type
(
json
.
loads
(
leaf_desc
.
decode
()))
return
Table
(
self
,
map_id
,
map_fd
,
keytype
,
leaftype
,
func_
reducer
)
return
Table
(
self
,
map_id
,
map_fd
,
keytype
,
leaftype
,
reducer
=
reducer
)
def
__getitem__
(
self
,
key
):
def
__getitem__
(
self
,
key
):
if
key
not
in
self
.
tables
:
if
key
not
in
self
.
tables
:
...
...
src/python/bcc/table.py
View file @
64258256
...
@@ -74,8 +74,8 @@ def _print_log2_hist(vals, val_type):
...
@@ -74,8 +74,8 @@ def _print_log2_hist(vals, val_type):
_stars
(
val
,
val_max
,
stars
)))
_stars
(
val
,
val_max
,
stars
)))
def
Table
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
,
func_reducer
):
def
Table
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
,
**
kwargs
):
"""Table(bpf, map_id, map_fd, keytype, leaftype,
func_reducer
)
"""Table(bpf, map_id, map_fd, keytype, leaftype,
**kwargs
)
Create a python object out of a reference to a bpf table handle"""
Create a python object out of a reference to a bpf table handle"""
...
@@ -90,11 +90,9 @@ def Table(bpf, map_id, map_fd, keytype, leaftype, func_reducer):
...
@@ -90,11 +90,9 @@ def Table(bpf, map_id, map_fd, keytype, leaftype, func_reducer):
elif
ttype
==
BPF_MAP_TYPE_PERF_EVENT_ARRAY
:
elif
ttype
==
BPF_MAP_TYPE_PERF_EVENT_ARRAY
:
t
=
PerfEventArray
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
)
t
=
PerfEventArray
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
)
elif
ttype
==
BPF_MAP_TYPE_PERCPU_HASH
:
elif
ttype
==
BPF_MAP_TYPE_PERCPU_HASH
:
t
=
PerCpuHash
(
bpf
,
map_id
,
map_fd
,
keytype
,
t
=
PerCpuHash
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
,
**
kwargs
)
leaftype
,
func
=
func_reducer
)
elif
ttype
==
BPF_MAP_TYPE_PERCPU_ARRAY
:
elif
ttype
==
BPF_MAP_TYPE_PERCPU_ARRAY
:
t
=
PerCpuArray
(
bpf
,
map_id
,
map_fd
,
keytype
,
t
=
PerCpuArray
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
,
**
kwargs
)
leaftype
,
func
=
func_reducer
)
elif
ttype
==
BPF_MAP_TYPE_STACK_TRACE
:
elif
ttype
==
BPF_MAP_TYPE_STACK_TRACE
:
t
=
StackTrace
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
)
t
=
StackTrace
(
bpf
,
map_id
,
map_fd
,
keytype
,
leaftype
)
if
t
==
None
:
if
t
==
None
:
...
@@ -149,9 +147,9 @@ class TableBase(MutableMapping):
...
@@ -149,9 +147,9 @@ class TableBase(MutableMapping):
raise
Exception
(
"Could not scanf leaf"
)
raise
Exception
(
"Could not scanf leaf"
)
return
leaf
return
leaf
def
__getitem__
(
self
,
key
,
leaf
=
None
):
def
__getitem__
(
self
,
key
):
key_p
=
ct
.
pointer
(
key
)
key_p
=
ct
.
pointer
(
key
)
if
not
leaf
:
leaf
=
self
.
Leaf
()
leaf
=
self
.
Leaf
()
leaf_p
=
ct
.
pointer
(
leaf
)
leaf_p
=
ct
.
pointer
(
leaf
)
res
=
lib
.
bpf_lookup_elem
(
self
.
map_fd
,
res
=
lib
.
bpf_lookup_elem
(
self
.
map_fd
,
ct
.
cast
(
key_p
,
ct
.
c_void_p
),
ct
.
cast
(
key_p
,
ct
.
c_void_p
),
...
@@ -312,9 +310,9 @@ class ArrayBase(TableBase):
...
@@ -312,9 +310,9 @@ class ArrayBase(TableBase):
def
__len__
(
self
):
def
__len__
(
self
):
return
self
.
max_entries
return
self
.
max_entries
def
__getitem__
(
self
,
key
,
leaf
=
None
):
def
__getitem__
(
self
,
key
):
key
=
self
.
_normalize_key
(
key
)
key
=
self
.
_normalize_key
(
key
)
return
super
(
ArrayBase
,
self
).
__getitem__
(
key
,
leaf
)
return
super
(
ArrayBase
,
self
).
__getitem__
(
key
)
def
__setitem__
(
self
,
key
,
leaf
):
def
__setitem__
(
self
,
key
,
leaf
):
key
=
self
.
_normalize_key
(
key
)
key
=
self
.
_normalize_key
(
key
)
...
@@ -408,127 +406,121 @@ class PerfEventArray(ArrayBase):
...
@@ -408,127 +406,121 @@ class PerfEventArray(ArrayBase):
class
PerCpuHash
(
HashTable
):
class
PerCpuHash
(
HashTable
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
func_reducer
=
kwargs
[
'func'
]
self
.
reducer
=
kwargs
[
"reducer"
]
del
kwargs
[
'func'
]
del
kwargs
[
"reducer"
]
self
.
total_cpu
=
multiprocessing
.
cpu_count
()
self
.
alignment
=
int
(
check_output
([
"grep"
,
"-m"
,
"1"
,
"cache_alignment"
,
"/proc/cpuinfo"
]).
split
(
' '
,
2
)[
1
])
/
8
super
(
PerCpuHash
,
self
).
__init__
(
*
args
,
**
kwargs
)
super
(
PerCpuHash
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
leafsize
=
ct
.
sizeof
(
self
.
Leaf
)
self
.
sLeaf
=
self
.
Leaf
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
)
and
self
.
leafsize
%
self
.
alignment
is
not
0
:
self
.
total_cpu
=
multiprocessing
.
cpu_count
()
# Struct that are not aligned to cache.
# This needs to be 8 as hard coded into the linux kernel.
raise
IndexError
(
"Struct must be aligned to %s, please add some padding"
%
self
.
alignment
)
self
.
alignment
=
ct
.
sizeof
(
self
.
sLeaf
)
%
8
if
self
.
alignment
is
0
:
self
.
Leaf
=
self
.
sLeaf
*
self
.
total_cpu
else
:
# Currently Float, Char, un-aligned structs are not supported
if
self
.
sLeaf
==
ct
.
c_uint
:
self
.
Leaf
=
ct
.
c_uint64
*
self
.
total_cpu
elif
self
.
sLeaf
==
ct
.
c_int
:
self
.
Leaf
=
ct
.
c_int64
*
self
.
total_cpu
else
:
raise
IndexError
(
"Leaf must be aligned to 8 bytes"
)
def
__getitem__
(
self
,
key
):
def
__getitem__
(
self
,
key
):
if
self
.
leafsize
%
self
.
alignment
is
0
:
result
=
super
(
PerCpuHash
,
self
).
__getitem__
(
key
)
# Struct/DataTypes that are aligned to cache
if
self
.
alignment
is
0
:
leaf_arr
=
(
self
.
Leaf
*
self
.
total_cpu
)()
ret
=
result
else
:
else
:
# DataTypes that are not aligned to cache
ret
=
(
self
.
sLeaf
*
self
.
total_cpu
)()
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
if
(
self
.
func_reducer
):
super
(
PerCpuHash
,
self
).
__getitem__
(
key
,
leaf_arr
)
leaf_ret
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_ret
[
i
]
=
leaf_arr
[
i
]
ret
[
i
]
=
result
[
i
]
return
reduce
(
self
.
func_reducer
,
leaf_ret
)
if
(
self
.
reducer
):
return
reduce
(
self
.
reducer
,
ret
)
else
:
else
:
super
(
PerCpuHash
,
self
).
__getitem__
(
key
,
leaf_arr
)
return
ret
leaf_ret
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_ret
[
i
]
=
leaf_arr
[
i
]
return
leaf_ret
def
__setitem__
(
self
,
key
,
leaf
):
def
__setitem__
(
self
,
key
,
leaf
):
if
self
.
leafsize
%
self
.
alignment
is
0
:
super
(
PerCpuHash
,
self
).
__setitem__
(
key
,
leaf
)
leaf_arr
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_arr
[
i
]
=
leaf
else
:
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_arr
[
i
]
=
leaf
.
value
super
(
PerCpuHash
,
self
).
__setitem__
(
key
,
leaf_arr
)
def
sum
(
self
,
key
):
def
sum
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
temp
=
self
.
reducer
return
self
.
Leaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
super
(
PerCpuHash
,
self
).
__getitem__
(
key
,
leaf_arr
)))
self
.
reducer
=
None
result
=
self
.
__getitem__
(
key
)
self
.
reducer
=
temp
return
self
.
sLeaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
result
))
def
max
(
self
,
key
):
def
max
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
raise
IndexError
(
"Leaf must be an integer type for default max functions"
)
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
temp
=
self
.
reducer
return
self
.
Leaf
(
max
(
super
(
PerCpuHash
,
self
).
__getitem__
(
key
,
leaf_arr
)))
self
.
reducer
=
None
result
=
self
.
__getitem__
(
key
)
self
.
reducer
=
temp
return
self
.
sLeaf
(
max
(
result
))
def
average
(
self
,
key
):
def
average
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
result
=
self
.
sum
(
key
)
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
result
.
value
/=
self
.
total_cpu
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
return
result
return
self
.
Leaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
super
(
PerCpuHash
,
self
).
__getitem__
(
key
,
leaf_arr
))
/
self
.
total_cpu
)
class
PerCpuArray
(
ArrayBase
):
class
PerCpuArray
(
ArrayBase
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
self
.
func_reducer
=
kwargs
[
'func'
]
self
.
reducer
=
kwargs
[
"reducer"
]
del
kwargs
[
'func'
]
del
kwargs
[
"reducer"
]
self
.
total_cpu
=
multiprocessing
.
cpu_count
()
self
.
alignment
=
int
(
check_output
([
"grep"
,
"-m"
,
"1"
,
"cache_alignment"
,
"/proc/cpuinfo"
]).
split
(
' '
,
2
)[
1
])
/
8
super
(
PerCpuArray
,
self
).
__init__
(
*
args
,
**
kwargs
)
super
(
PerCpuArray
,
self
).
__init__
(
*
args
,
**
kwargs
)
self
.
leafsize
=
ct
.
sizeof
(
self
.
Leaf
)
self
.
sLeaf
=
self
.
Leaf
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
)
and
self
.
leafsize
%
self
.
alignment
is
not
0
:
self
.
total_cpu
=
multiprocessing
.
cpu_count
()
# Struct that are not aligned to cache.
# This needs to be 8 as hard coded into the linux kernel.
raise
IndexError
(
"Struct must be aligned to %s, please add some padding"
%
self
.
alignment
)
self
.
alignment
=
ct
.
sizeof
(
self
.
sLeaf
)
%
8
if
self
.
alignment
is
0
:
self
.
Leaf
=
self
.
sLeaf
*
self
.
total_cpu
else
:
# Currently Float, Char, un-aligned structs are not supported
if
self
.
sLeaf
==
ct
.
c_uint
:
self
.
Leaf
=
ct
.
c_uint64
*
self
.
total_cpu
elif
self
.
sLeaf
==
ct
.
c_int
:
self
.
Leaf
=
ct
.
c_int64
*
self
.
total_cpu
else
:
raise
IndexError
(
"Leaf must be aligned to 8 bytes"
)
def
__getitem__
(
self
,
key
):
def
__getitem__
(
self
,
key
):
if
self
.
leafsize
%
self
.
alignment
is
0
:
result
=
super
(
PerCpuArray
,
self
).
__getitem__
(
key
)
# Struct/DataTypes that are aligned to cache
if
self
.
alignment
is
0
:
leaf_arr
=
(
self
.
Leaf
*
self
.
total_cpu
)()
ret
=
result
else
:
else
:
# DataTypes that are not aligned to cache
ret
=
(
self
.
sLeaf
*
self
.
total_cpu
)()
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
if
(
self
.
func_reducer
):
super
(
PerCpuArray
,
self
).
__getitem__
(
key
,
leaf_arr
)
leaf_ret
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_ret
[
i
]
=
leaf_arr
[
i
]
ret
[
i
]
=
result
[
i
]
return
reduce
(
self
.
func_reducer
,
leaf_ret
)
if
(
self
.
reducer
):
return
reduce
(
self
.
reducer
,
ret
)
else
:
else
:
super
(
PerCpuArray
,
self
).
__getitem__
(
key
,
leaf_arr
)
return
ret
leaf_ret
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_ret
[
i
]
=
leaf_arr
[
i
]
return
leaf_ret
def
__setitem__
(
self
,
key
,
leaf
):
def
__setitem__
(
self
,
key
,
leaf
):
if
self
.
leafsize
%
self
.
alignment
is
0
:
super
(
PerCpuArray
,
self
).
__setitem__
(
key
,
leaf
)
leaf_arr
=
(
self
.
Leaf
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_arr
[
i
]
=
leaf
else
:
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
for
i
in
range
(
0
,
self
.
total_cpu
):
leaf_arr
[
i
]
=
leaf
.
value
super
(
PerCpuArray
,
self
).
__setitem__
(
key
,
leaf_arr
)
def
sum
(
self
,
key
):
def
sum
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
temp
=
self
.
reducer
return
self
.
Leaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
super
(
PerCpuArray
,
self
).
__getitem__
(
key
,
leaf_arr
)))
self
.
reducer
=
None
result
=
self
.
__getitem__
(
key
)
self
.
reducer
=
temp
return
self
.
sLeaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
result
))
def
max
(
self
,
key
):
def
max
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
raise
IndexError
(
"Leaf must be an integer type for default max functions"
)
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
temp
=
self
.
reducer
return
self
.
Leaf
(
max
(
super
(
PerCpuArray
,
self
).
__getitem__
(
key
,
leaf_arr
)))
self
.
reducer
=
None
result
=
self
.
__getitem__
(
key
)
self
.
reducer
=
temp
return
self
.
sLeaf
(
max
(
result
))
def
average
(
self
,
key
):
def
average
(
self
,
key
):
if
isinstance
(
self
.
Leaf
(),
ct
.
Structure
):
result
=
self
.
sum
(
key
)
raise
IndexError
(
"Leaf must be an integer type for default sum functions"
)
result
.
value
/=
self
.
total_cpu
leaf_arr
=
(
ct
.
c_uint64
*
self
.
total_cpu
)()
return
result
return
self
.
Leaf
(
reduce
(
lambda
x
,
y
:
x
+
y
,
super
(
PerCpuArray
,
self
).
__getitem__
(
key
,
leaf_arr
))
/
self
.
total_cpu
)
class
StackTrace
(
TableBase
):
class
StackTrace
(
TableBase
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
...
...
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