Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
neo
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Labels
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Jobs
Commits
Open sidebar
Kirill Smelkov
neo
Commits
f5fec740
Commit
f5fec740
authored
Mar 02, 2018
by
Kirill Smelkov
2
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
X switch node info to labels; start adding that to plot
parent
28d00786
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
169 additions
and
47 deletions
+169
-47
go/neo/t/benchlib.py
go/neo/t/benchlib.py
+98
-15
go/neo/t/benchplot
go/neo/t/benchplot
+41
-4
go/neo/t/neotest
go/neo/t/neotest
+30
-28
No files found.
go/neo/t/benchlib.py
View file @
f5fec740
...
...
@@ -27,6 +27,7 @@ from __future__ import print_function
import
re
,
io
,
numpy
as
np
from
collections
import
OrderedDict
from
cStringIO
import
StringIO
# Benchmark is a collection of benchmark lines.
...
...
@@ -87,24 +88,28 @@ class Stats(object):
# ----------------------------------------
# '<key>: <value>'
_label_re
=
re
.
compile
(
r'(?P<key>\
w+):
\s*'
)
_sp_re
=
re
.
compile
(
r'\
s
')
# parse_label tries to parse line as label.
#
# returns (key, value).
# if line does not match - (None, None) is returned.
def parse_label(line):
m
=
_label_re
.
match
(
line
)
if
m
is
None
:
colon = line.find('
:
')
if colon == -1:
return None, None
key, value = line[:colon], line[colon+1:]
# key must not contain space
if _sp_re.search(key):
return None, None
# FIXME key must be unicode lower
# FIXME key must not contain upper or space
key
=
m
.
group
(
'key'
)
value
=
line
[
m
.
end
():]
value
=
value
.
rstrip
()
# XXX or rstrip only \n ?
# XXX also support '
WARNING
'
value = value.strip() # leading and traling
\
s XXX
f
or trailing - rstrip only
\
n
?
return key, value
...
...
@@ -155,7 +160,8 @@ def _parse_benchline(linev):
#
# r is required to implement `.readlines()`.
#
# returns -> Benchmark.
# returns -> Benchmark, exit_labels.
# (exit_labels is ordered {} with labels state at end of reading)
def
load
(
r
):
labels
=
OrderedDict
()
benchv
=
Benchmark
()
# of BenchLine
...
...
@@ -166,6 +172,10 @@ def load(r):
if
key
is
not
None
:
labels
=
labels
.
copy
()
if
value
:
if
key
==
'WARNING'
:
# warnings accumulate, not replace previous ones
labels
[
key
]
=
labels
.
get
(
key
,
())
+
(
value
,)
else
:
labels
[
key
]
=
value
else
:
labels
.
pop
(
key
,
None
)
# discard
...
...
@@ -178,18 +188,92 @@ def load(r):
benchv
.
append
(
bl
)
continue
# XXX also extract warnings?
return
benchv
return
benchv
,
labels
# load_file loads benchmark data from file @ path.
#
# returns -> Benchmark.
# returns -> Benchmark
, exit_labels
.
def
load_file
(
path
):
with
io
.
open
(
path
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
return
load
(
f
)
# xload loads benchmark data from a reader with neotest extensions handling.
#
# neotest extensions:
#
# - a line starting with `*** neotest:` denotes start of neotest extension block.
# The block consists of labels describing hardware and software on that node. XXX
# The block ends with a blank line.
# Labels in the block are not added to benchmarking lines from main stream.
# The block itself should not contain benchmark lines.
#
# returns -> Benchmark, exit_labels, []extlab.
# (extlab is ordered {} with labels from an extension block)
def
xload
(
r
):
xr
=
_neotestExtReader
(
r
)
b
,
l
=
load
(
xr
)
extv
=
[]
for
lineno
,
text
in
xr
.
extblockv
:
bext
,
lext
=
load
(
StringIO
(
text
.
encode
(
'utf-8'
)))
if
len
(
bext
)
!=
0
:
raise
RuntimeError
(
"%s:%d: neotest extension block contains benchmark line"
\
%
(
getattr
(
r
,
name
,
'?'
),
lineno
))
extv
.
append
(
lext
)
return
b
,
l
,
extv
# _neotestExtReader is a reader that splits neotest extension data from
# benchmarking data stream.
#
# A reader reading from _neotestExtReader sees original data stream with
# extensions filtered-out. The list of extension blocks found can be accessed
# at .extblockv.
class
_neotestExtReader
(
object
):
def
__init__
(
self
,
r
):
self
.
r
=
r
self
.
extblockv
=
[]
# of (lineno, text)
self
.
_lineno
=
0
def
_readline
(
self
):
l
=
self
.
r
.
readline
()
if
l
:
self
.
_lineno
+=
1
return
l
def
readline
(
self
):
l
=
self
.
_readline
()
if
not
l
.
startswith
(
'*** neotest:'
):
return
l
# EOF='' so also match here
# new extension block - read up to empty line or EOF
lineno
,
ext
=
self
.
_lineno
,
[
l
]
while
1
:
l
=
self
.
_readline
()
if
l
.
strip
()
==
""
:
break
ext
.
append
(
l
)
self
.
extblockv
.
append
((
lineno
,
''
.
join
(
ext
)))
return
l
def
readlines
(
self
):
while
1
:
l
=
self
.
readline
()
yield
l
if
not
l
:
break
# EOF
# xload_file loads benchmark data from file @ path with neotest extensions.
#
# returns -> Benchmark, exit_labels, []extlab.
def
xload_file
(
path
):
with
io
.
open
(
path
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
return
xload
(
f
)
# method decorator allows to define methods separate from class.
def
method
(
cls
):
...
...
@@ -198,7 +282,6 @@ def method(cls):
return
deco
# bylabel splits Benchmark into several groups of Benchmarks with specified
# labels having same values across a given group.
#
...
...
@@ -386,7 +469,7 @@ def main():
p
.
add_argument
(
"--split"
,
default
=
""
,
help
=
"split benchmarks by labels (default no split)"
)
args
=
p
.
parse_args
()
B
=
load_file
(
args
.
file
)
B
,
_
=
load_file
(
args
.
file
)
benchstat
(
sys
.
stdout
,
B
,
split
=
args
.
split
.
split
(
","
))
if
__name__
==
'__main__'
:
...
...
go/neo/t/benchplot
View file @
f5fec740
...
...
@@ -22,13 +22,15 @@
import
sys
,
re
from
collections
import
OrderedDict
from
benchlib
import
load_file
,
Unit
from
benchlib
import
x
load_file
,
Unit
import
matplotlib.pyplot
as
plt
from
matplotlib.patches
import
Rectangle
from
mpl_toolkits.axes_grid1.inset_locator
import
zoomed_inset_axes
,
mark_inset
,
\
TransformedBbox
,
BboxPatch
,
BboxConnectorPatch
from
pprint
import
pprint
# BenchSeries represents several runs of a benchmark with different "-<n>".
#
...
...
@@ -257,15 +259,41 @@ def plotlat1(ax, S):
def
main
():
B
=
load_file
(
sys
.
argv
[
1
])
B
,
_
,
extv
=
xload_file
(
sys
.
argv
[
1
])
# extv -> node {}, date
nodemap
=
OrderedDict
()
date
=
None
for
ext
in
extv
:
if
'xnode'
not
in
ext
:
textv
=
[
'%s: %s'
%
(
k
,
v
)
for
k
,
v
in
ext
.
items
()]
raise
RuntimeError
(
'ext block without xnode:
\
n
%s'
%
(
'
\
n
'
.
join
(
textv
),))
xnode
=
ext
[
'xnode'
]
# kirr@deco.navytux.spb.ru (... XXX vvv hacky, not robust
_
=
xnode
.
split
()[
0
]
# kirr@deco.navytux.spb.ru
_
=
_
.
split
(
'@'
)[
1
]
# deco.navytux.spb.ru
node
=
_
.
split
(
'.'
)[
0
]
nodemap
[
node
]
=
ext
if
'date'
in
ext
:
date
=
ext
[
'date'
]
# XXX if date = None -> warning "no date found"
if
date
is
None
:
date
=
"date: ?"
splitby
=
[
'dataset'
,
'cluster'
]
Bl
=
B
.
bylabel
(
splitby
)
for
labkey
in
Bl
:
print
labkey
# FIXME hack
if
labkey
==
():
# cpu benchmarks
continue
Bu
=
Bl
[
labkey
].
byunit
()
fig
=
plt
.
figure
(
figsize
=
(
2
*
7.5
,
10
))
# XXX figsize - temp?
...
...
@@ -315,14 +343,23 @@ def main():
plt
.
text
(
"xxx not found"
)
#fig.legend()
fig
.
legend
([
r0
,
r0
],
[
"aaa"
,
"bbb"
])
# legend showing labels from labkey
# https://matplotlib.org/tutorials/intermediate/legend_guide.html#multiple-legends-on-the-same-axes
lh
=
[
r0
]
*
len
(
labkey
)
ltext
=
[
'%s: %s'
%
(
k
,
v
)
for
k
,
v
in
labkey
]
fig
.
legend
(
lh
,
ltext
,
handlelength
=
0
,
handletextpad
=
0
,
loc
=
"upper right"
)
#fig.tight_layout()
fig
.
subplots_adjust
(
left
=
0.05
,
# no big marging on the left
#wspace=0.1
)
# date
fig
.
text
(
0.003
,
0.995
,
date
,
ha
=
'left'
,
va
=
'top'
)
plt
.
show
()
return
# XXX temp to show only first
...
...
go/neo/t/neotest
View file @
f5fec740
...
...
@@ -498,7 +498,7 @@ else:
local
gitver
=
$(
git
-C
$loc
describe
--long
--dirty
2>/dev/null
)
local
ver
test
"
$gitver
"
!=
""
&&
ver
=
"
$gitver
"
||
ver
=
"
$pyver
"
printf
"
# %-16s: %s
\n
"
"
$showas
"
"
$ver
"
printf
"
sw/%-16s %s
\n
"
"
${
showas
}
:
"
"
$ver
"
}
# proginfo <prog> ... - run `prog ...` or print that prog is missing
...
...
@@ -532,21 +532,21 @@ xhostname() {
# show information about local system (os, hardware, versions, ...)
system_info
()
{
echo
-n
"#
"
;
date
--rfc-2822
echo
-n
"#
`
whoami
`
@
`
hostname
--fqdn
2>/dev/null
||
hostname
`
("
echo
-n
e
"date:
\t
"
;
date
--rfc-2822
echo
-n
e
"xnode:
\t
`
whoami
`
@
`
hostname
--fqdn
2>/dev/null
||
hostname
`
("
echo
-n
"
${
myaddr6v
[0]
}
"
test
"
${#
myaddr6v
[@]
}
"
-eq
1
||
echo
-n
" (+
$((${#
myaddr6v
[@]
}
-
1
))
·ipv6)"
echo
-n
"
${
myaddr4v
[0]
}
"
test
"
${#
myaddr4v
[@]
}
"
-eq
1
||
echo
-n
" (+
$((${#
myaddr4v
[@]
}
-
1
))
·ipv4)"
echo
")"
echo
-n
"# "
;
uname
-a
echo
-n
e
"uname:
\t
"
;
uname
-a
# XXX key name
# cpu
echo
-n
"# cpu:
"
;
grep
"^model name"
/proc/cpuinfo |head
-1
|sed
-e
's/model name\s*: //'
echo
-n
e
"cpu:
\t
"
;
grep
"^model name"
/proc/cpuinfo |head
-1
|sed
-e
's/model name\s*: //'
syscpu
=
/sys/devices/system/cpu
sysidle
=
$syscpu
/cpuidle
cpuvabbrev
()
{
# cpuvabbrev cpu0 cpu1 cpu2 ... cpuN -> cpu[0-N]
cpuvabbrev
()
{
# cpuvabbrev cpu0 cpu1 cpu2 ... cpuN -> cpu
/
[0-N]
test
$#
-le
1
&&
echo
"
$@
"
&&
return
min
=
""
...
...
@@ -562,14 +562,14 @@ system_info() {
fi
max
=
$n
done
echo
"cpu[
$min
-
$max
]"
echo
"cpu
/
[
$min
-
$max
]"
}
freqcpuv
=()
# [] of cpu
freqstr
=
""
# text about cpufreq for cpus in ^^^
freqdump
()
{
test
"
${#
freqcpuv
[@]
}
"
=
0
&&
return
echo
"
#
`
cpuvabbrev
${
freqcpuv
[*]
}
`
:
$freqstr
"
echo
"
`
cpuvabbrev
${
freqcpuv
[*]
}
`
/freq
:
$freqstr
"
freqcpuv
=()
freqstr
=
""
}
...
...
@@ -578,7 +578,7 @@ system_info() {
idlestr
=
""
idledump
()
{
test
"
${#
idlecpuv
[@]
}
"
=
0
&&
return
echo
"
#
`
cpuvabbrev
${
idlecpuv
[*]
}
`
:
$idlestr
"
echo
"
`
cpuvabbrev
${
idlecpuv
[*]
}
`
/idle
:
$idlestr
"
idlecpuv
=()
idlestr
=
""
}
...
...
@@ -588,7 +588,7 @@ system_info() {
f
=
"
$cpu
/cpufreq"
fmin
=
`
fkghz
$f
/scaling_min_freq
`
fmax
=
`
fkghz
$f
/scaling_max_freq
`
fs
=
"
freq:
`
cat
$f
/scaling_driver
`
/
`
cat
$f
/scaling_governor
`
[
$fmin
-
$fmax
]"
fs
=
"
`
cat
$f
/scaling_driver
`
/
`
cat
$f
/scaling_governor
`
[
$fmin
-
$fmax
]"
if
[
"
$fs
"
!=
"
$freqstr
"
]
;
then
freqdump
freqstr
=
"
$fs
"
...
...
@@ -601,7 +601,7 @@ system_info() {
latmax
=
0
while
read
cpu
;
do
is
=
"
idle:
`
cat
$sysidle
/current_driver
`
/
`
cat
$sysidle
/current_governor_ro
`
:"
is
=
"
`
cat
$sysidle
/current_driver
`
/
`
cat
$sysidle
/current_governor_ro
`
:"
while
read
state
;
do
# XXX add target residency?
is+
=
" "
...
...
@@ -620,8 +620,8 @@ system_info() {
< <
(
ls
-vd
$syscpu
/cpu[0-9]
*
)
idledump
test
"
$freqstable
"
=
y
||
echo
"
# cpu: WARNING
: frequency not fixed - benchmark timings won't be stable"
test
"
$latmax
"
-le
10
||
echo
"
# cpu: WARNING
: C-state exit-latency is max
${
latmax
}
μs - up to that can add to networked and IPC request-reply latency"
test
"
$freqstable
"
=
y
||
echo
"
WARNING: cpu
: frequency not fixed - benchmark timings won't be stable"
test
"
$latmax
"
-le
10
||
echo
"
WARNING: cpu
: C-state exit-latency is max
${
latmax
}
μs - up to that can add to networked and IPC request-reply latency"
# disk under .
...
...
@@ -636,14 +636,14 @@ system_info() {
blkdev
=
$1
blkdev1
=
`
basename
$blkdev
`
# /dev/sda -> sda
# XXX lsblk: tmpfs: not a block device
echo
"#
$blkdev1
:
`
lsblk
-dn
-o
MODEL
$blkdev
`
rev
`
lsblk
-dn
-o
REV,SIZE
$blkdev
`
"
printf
"disk/%s: %s
\n
"
"
$blkdev1
"
"
`
lsblk
-dn
-o
MODEL
$blkdev
`
rev
`
lsblk
-dn
-o
REV,SIZE
$blkdev
`
"
}
case
"
$blkdev1
"
in
md
*
)
# software raid
slavev
=
`
ls
-x
/sys/class/block/
$blkdev1
/slaves
`
echo
"#
$blkdev1
(
`
cat
/sys/class/block/
$blkdev1
/md/level
`
) ->
$slavev
"
printf
"disk/%s:
\t
%s
\n
"
"
$blkdev1
"
"
(
`
cat
/sys/class/block/
$blkdev1
/md/level
`
) ->
$slavev
"
# XXX dup wrt dm-*; move recursion to common place
for
s
in
$slavev
;
do
s
=
`
echo
$s
|sed
-e
's/[0-9]*$//'
`
# sda3 -> sda
...
...
@@ -653,7 +653,7 @@ system_info() {
dm-
*
)
# device mapper
slavev
=
`
ls
-x
/sys/class/block/
$blkdev1
/slaves
`
echo
"#
$blkdev1
(
`
cat
/sys/class/block/
$blkdev1
/dm/name
`
) ->
$slavev
"
printf
"disk/%s:
\t
%s
\n
"
"
$blkdev1
"
"
(
`
cat
/sys/class/block/
$blkdev1
/dm/name
`
) ->
$slavev
"
# XXX dup wrt md*; move recursion to common place
for
s
in
$slavev
;
do
s
=
`
echo
$s
|sed
-e
's/[0-9]*$//'
`
# sda3 -> sda
...
...
@@ -671,7 +671,7 @@ system_info() {
find /sys/class/net
-type
l
-not
-lname
'*virtual*'
|sort |
\
while
read
nic
;
do
nicname
=
`
basename
$nic
`
# /sys/class/net/eth0 -> eth0
echo
-n
"
#
$nicname
: "
echo
-n
"
nic/
$nicname
: "
nicdev
=
`
realpath
$nic
/device
`
# /sys/class/net/eth0 -> /sys/devices/pci0000:00/0000:00:1f.6
case
"
$nicdev
"
in
...
...
@@ -700,7 +700,7 @@ system_info() {
featok
=
y
feat
=
`
ethtool
-k
$nicname
2>/dev/null
`
||
featok
=
n
if
[
$featok
!=
y
]
;
then
echo
"
#
$nicname
:
features: ?"
echo
"
nic/
$nicname
/
features: ?"
else
# feat1 name abbrev -> abbrev. value (e.g. "tx" or "!tx")
feat1
()
{
...
...
@@ -719,7 +719,7 @@ system_info() {
esac
}
s
=
"
#
$nicname
:
features:"
s
=
"
nic/
$nicname
/
features:"
# NOTE feature abbrevs are those used by `ethtool -K` to set them
s+
=
"
`
feat1 rx-checksumming rx
`
"
s+
=
"
`
feat1 tx-checksumming tx
`
"
...
...
@@ -748,7 +748,7 @@ system_info() {
# show rx/tx coalescing latency
echo
-n
"
#
$nicname
:
coalesce:"
echo
-n
"
nic/
$nicname
/
coalesce:"
coalok
=
y
coal
=
`
ethtool
-c
$nicname
2>/dev/null
`
||
coalok
=
n
if
[
$coalok
!=
y
]
;
then
...
...
@@ -779,7 +779,7 @@ system_info() {
fi
# show main parameters + GRO flush time
s
=
"
#
$nicname
:
"
s
=
"
nic/
$nicname
/status:
"
s+
=
"
`
cat
$nic
/operstate
`
"
speed
=
`
cat
$nic
/speed 2>/dev/null
`
||
speed
=
?
# returns EINVAL for wifi
s+
=
", speed=
$speed
"
...
...
@@ -798,15 +798,16 @@ system_info() {
# emit NIC warnings
for
warn
in
"
${
nicwarnv
[@]
}
"
;
do
echo
"
#
$nicname
: WARNING
:
$warn
"
echo
"
WARNING: nic/
$nicname
:
$warn
"
done
done
echo
-n
"# "
;
proginfo python
--version
2>&1
# https://bugs.python.org/issue18338
echo
-n
"# "
;
proginfo go version
echo
-n
"# "
;
proginfo python
-c
'import sqlite3 as s; print "sqlite %s (py mod %s)" % (s.sqlite_version, s.version)'
echo
-n
"# "
;
proginfo mysqld
--version
printf
"%-20s"
"sw/python:"
;
proginfo python
--version
2>&1
# https://bugs.python.org/issue18338
printf
"%-20s"
"sw/go:"
;
proginfo go version
printf
"%-20s"
"sw/sqlite:"
;
proginfo python
-c
\
'import sqlite3 as s; print "sqlite %s (py mod %s)" % (s.sqlite_version, s.version)'
printf
"%-20s"
"sw/mysqld:"
;
proginfo mysqld
--version
pyver neoppod neo
pyver zodb
...
...
@@ -1101,6 +1102,7 @@ zbench_go() {
# command: benchmark when client and storage are on the same computer
cmd_bench-local
()
{
echo
-e
">>> bench-local"
echo
-e
"
\n
*** neotest: node"
system_info
echo
-e
"
\n
*** cpu:
\n
"
bench_cpu
...
...
@@ -1195,9 +1197,9 @@ cmd_bench-cluster() {
test
-z
"
$url
"
&&
die
"Usage: neotest bench-cluster [user@]<host>:<path>"
echo
-e
">>> bench-cluster
$url
"
echo
-e
"
\n
#
server:
"
echo
-e
"
\n
#
*** neotest: node: (server)
"
system_info
echo
-e
"
\n
#
client:
"
echo
-e
"
\n
#
*** neotest: node: (client)
"
on
$url
./neotest info-local
echo
-e
"
\n
*** server cpu:"
...
...
Kirill Smelkov
@kirr
mentioned in commit
pygolang@812e7ed7
·
Jun 20, 2018
mentioned in commit
pygolang@812e7ed7
mentioned in commit kirr/pygolang@812e7ed74fb4d07157147cb427f15342d109a537
Toggle commit list
Kirill Smelkov
@kirr
mentioned in commit
0fb3d795
·
Jul 12, 2018
mentioned in commit
0fb3d795
mentioned in commit 0fb3d7958bd677e567f5529486a5d3188d8bc78e
Toggle commit list
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