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
916782b6
Commit
916782b6
authored
Mar 05, 2018
by
Kirill Smelkov
2
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
X normalize/convert units, so that disk and ping/tcp latencies could be plotted too
parent
89682f01
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
104 additions
and
24 deletions
+104
-24
go/neo/t/benchlib.py
go/neo/t/benchlib.py
+78
-9
go/neo/t/benchplot
go/neo/t/benchplot
+26
-15
No files found.
go/neo/t/benchlib.py
View file @
916782b6
...
@@ -58,7 +58,7 @@ class Measure(object):
...
@@ -58,7 +58,7 @@ class Measure(object):
# Unit is a symbolic unit, like "ns/op", "µs/object" or "L1-miss-ns/op"
# Unit is a symbolic unit, like "ns/op", "µs/object" or "L1-miss-ns/op"
class
Unit
(
object
):
class
Unit
(
object
):
def
__init__
(
self
,
unit
):
def
__init__
(
self
,
unit
):
self
.
unit
=
unit
# XXX normalize e.g. "µs" and "ns" to "time"
self
.
unit
=
unit
# eq, hash - so that Unit can be used as key in dict or set
# eq, hash - so that Unit can be used as key in dict or set
def
__eq__
(
self
,
other
):
def
__eq__
(
self
,
other
):
...
@@ -89,6 +89,13 @@ class Stats(object):
...
@@ -89,6 +89,13 @@ class Stats(object):
# ----------------------------------------
# ----------------------------------------
# method decorator allows to define methods separate from class.
def
method
(
cls
):
def
deco
(
f
):
setattr
(
cls
,
f
.
func_name
,
f
)
return
deco
_sp_re
=
re
.
compile
(
r'\
s
')
_sp_re
=
re
.
compile
(
r'\
s
')
# parse_label tries to parse line as label.
# parse_label tries to parse line as label.
...
@@ -130,6 +137,7 @@ def parse_benchline(line):
...
@@ -130,6 +137,7 @@ def parse_benchline(line):
try:
try:
return _parse_benchline(linev)
return _parse_benchline(linev)
except Exception:
except Exception:
# FIXME -> more fine-grained catch, not to skip programming mistakes
return None
return None
def _parse_benchline(linev):
def _parse_benchline(linev):
...
@@ -152,11 +160,55 @@ def _parse_benchline(linev):
...
@@ -152,11 +160,55 @@ def _parse_benchline(linev):
value
=
float
(
value
)
value
=
float
(
value
)
unit
=
Unit
(
unit
)
unit
=
Unit
(
unit
)
measurev
.
append
(
Measure
(
value
,
unit
))
unit
,
scale
=
unit
.
normalize
()
measurev
.
append
(
Measure
(
value
*
scale
,
unit
))
return
BenchLine
(
name
,
niter
,
measurev
)
return
BenchLine
(
name
,
niter
,
measurev
)
# normalize converts unit into normalized Unit & scale.
#
# It returns base unit and scaling factor to convert values from original
# unit to base one.
#
# For example
#
# "µs" -> "s", 1E-6
# "ms/op" -> "s/op", 1E-3
# "user-s/op" -> "user-s/op", 1
#
# returns -> Unit, scale.
@
method
(
Unit
)
def
normalize
(
self
):
# split unit string into prefix and just unit
unit
=
self
.
unit
unitv
=
unit
.
rsplit
(
'-'
,
1
)
# "L1-miss-ns/op" -> "L1-miss-", "ns/op"
unit
=
unitv
[
-
1
]
# unit -> nom/denom/... ; scale nom to base
fracv
=
unit
.
split
(
'/'
,
1
)
rescale
=
1
_
=
_unitTab
.
get
(
fracv
[
0
])
if
_
is
not
None
:
fracv
[
0
]
=
_
[
0
]
rescale
=
_
[
1
]
# rebuild whole unit string
unitv
[
-
1
]
=
'/'
.
join
(
fracv
)
unit
=
'-'
.
join
(
unitv
)
return
Unit
(
unit
),
rescale
# {} unit -> (base_unit, rescale)
_unitTab
=
{
"ns"
:
(
"s"
,
1E-9
),
u"µs"
:
(
"s"
,
1E-6
),
"us"
:
(
"s"
,
1E-6
),
"ms"
:
(
"s"
,
1E-3
),
}
# load loads benchmark data from a reader.
# load loads benchmark data from a reader.
#
#
# r is required to implement `.readlines()`.
# r is required to implement `.readlines()`.
...
@@ -276,13 +328,6 @@ def xload_file(path):
...
@@ -276,13 +328,6 @@ def xload_file(path):
# method decorator allows to define methods separate from class.
def
method
(
cls
):
def
deco
(
f
):
setattr
(
cls
,
f
.
func_name
,
f
)
return
deco
# bylabel splits Benchmark into several groups of Benchmarks with specified
# bylabel splits Benchmark into several groups of Benchmarks with specified
# labels having same values across a given group.
# labels having same values across a given group.
#
#
...
@@ -351,6 +396,30 @@ def byunit(self):
...
@@ -351,6 +396,30 @@ def byunit(self):
return
byunit
return
byunit
# convert_unit converts benchmark values to be in specified unit.
#
# all original values must have units compatible with the conversion.
#
# returns -> new Benchmark with converted units.
@
method
(
Benchmark
)
def
convert_unit
(
self
,
unit
):
B
=
Benchmark
()
U
=
Unit
(
unit
)
u
,
uscale
=
U
.
normalize
()
for
b
in
self
:
measurev
=
[]
for
m
in
b
.
measurev
:
mu
,
muscale
=
m
.
unit
.
normalize
()
if
mu
!=
u
:
raise
ValueError
(
'convert unit: units are not convertible: (%s, %s)'
%
(
unit
,
m
.
unit
))
measurev
.
append
(
Measure
(
m
.
value
*
muscale
/
uscale
,
U
))
B
.
append
(
BenchLine
(
b
.
name
,
b
.
niter
,
measurev
,
b
.
labels
))
return
B
# stats returns statistics about values in benchmark collection.
# stats returns statistics about values in benchmark collection.
#
#
...
...
go/neo/t/benchplot
View file @
916782b6
...
@@ -212,12 +212,12 @@ def Bmerge(B, merger):
...
@@ -212,12 +212,12 @@ def Bmerge(B, merger):
for name_ in name_v:
for name_ in name_v:
b_ = Bname.get(name_)
b_ = Bname.get(name_)
if b_ is not None:
if b_ is not None:
# ok to merge if either probably same or the difference is <
1µs # XXX 0.5
# ok to merge if either probably same or the difference is <
0.5µs
s_ = b_.stats()
s_ = b_.stats()
assert s.unit == s_.unit, (s.unit, s_.unit)
assert s.unit == s_.unit, (s.unit, s_.unit)
t = ttest_ind_from_stats(s.avg, s.std, s.ninliers, s_.avg, s_.std, s_.ninliers)
t = ttest_ind_from_stats(s.avg, s.std, s.ninliers, s_.avg, s_.std, s_.ninliers)
if t.pvalue >= 0.3 or (s.unit == usop and abs(s.avg - s_.avg) < 0.5):
if t.pvalue >= 0.3 or (s.unit == usop and abs(s.avg - s_.avg) < 0.5):
print '
merging
%
s
(
%
s
)
\
t
+
%
s
(
%
s
)
(
%
s
)
' % (name, s, name_, s_, t)
#
print '
merging
%
s
(
%
s
)
\
t
+
%
s
(
%
s
)
(
%
s
)
' % (name, s, name_, s_, t)
bmerge.extend(b_)
bmerge.extend(b_)
namev.append(name_)
namev.append(name_)
...
@@ -298,14 +298,17 @@ _stylefor = {
...
@@ -298,14 +298,17 @@ _stylefor = {
}
}
_stylefor_re
=
[(
re
.
compile
(
_
),
sty
)
for
_
,
sty
in
[
_stylefor_re
=
[(
re
.
compile
(
_
),
sty
)
for
_
,
sty
in
[
(
r'crc32/(py|\
*)/
4K'
,
_
(
color
=
'C5'
)),
(
r'crc32/(py|\
*)/
4K'
,
_
(
color
=
'C5'
)),
(
r'crc32/go/4K'
,
_
(
color
=
'C5'
,
ls
=
'dashed'
)),
(
r'crc32/go/4K'
,
_
(
color
=
'C5'
,
ls
=
'dashed'
)),
(
r'sha1/(py\
|*)/
4K'
,
_
(
color
=
'C6'
)),
(
r'sha1/(py\
|*)/
4K'
,
_
(
color
=
'C6'
)),
(
r'sha1/go/4K'
,
_
(
color
=
'C6'
,
ls
=
'dashed'
)),
(
r'sha1/go/4K'
,
_
(
color
=
'C6'
,
ls
=
'dashed'
)),
(
r'unzlib/(py|\
*)/wczd
ata'
,
_
(
color
=
'C7'
)),
(
r'unzlib/(py|\
*)/wczd
ata'
,
_
(
color
=
'C7'
)),
(
r'unzlib/go/wczdata'
,
_
(
color
=
'C7'
,
ls
=
'dashed'
)),
(
r'unzlib/go/wczdata'
,
_
(
color
=
'C7'
,
ls
=
'dashed'
)),
(
r'unzlib/(py|\
*)/p
rod1-avg'
,
_
(
color
=
'C8'
)),
(
r'unzlib/(py|\
*)/p
rod1-avg'
,
_
(
color
=
'C8'
)),
(
r'unzlib/go/prod1-avg'
,
_
(
color
=
'C8'
,
ls
=
'dashed'
)),
(
r'unzlib/go/prod1-avg'
,
_
(
color
=
'C8'
,
ls
=
'dashed'
)),
(
r'disk/randread/direct/4K-avg'
,
_
(
color
=
'C9'
)),
(
r'disk/randread/pagecache/4K-avg'
,
_
(
color
=
'C9'
,
ls
=
'dashed'
)),
]]
]]
del
_
del
_
...
@@ -424,7 +427,7 @@ def plotlat1(ax, S):
...
@@ -424,7 +427,7 @@ def plotlat1(ax, S):
# plotnode1 plots latencies of base CPU/disk operations on the nodes.
# plotnode1 plots latencies of base CPU/disk operations on the nodes.
def
plotnode1
(
ax
,
B
,
w
=
0.05
,
details
=
False
):
def
plotnode1
(
ax
,
B
,
w
=
0.05
,
details
=
False
):
Bu
=
B
.
byunit
()
Bu
=
B
.
byunit
()
Bn
=
Bu
[
usop
].
byname
()
# XXX µs/op hardcoded. FIXME disk/*
Bn
=
Bu
[
Unit
(
"s/op"
)].
convert_unit
(
u"µs/op"
).
byname
()
S
=
dict
((
_
,
Bn
[
_
].
stats
())
for
_
in
Bn
)
# {} name -> stats
S
=
dict
((
_
,
Bn
[
_
].
stats
())
for
_
in
Bn
)
# {} name -> stats
yticks
=
set
()
yticks
=
set
()
...
@@ -437,8 +440,10 @@ def plotnode1(ax, B, w=0.05, details=False):
...
@@ -437,8 +440,10 @@ def plotnode1(ax, B, w=0.05, details=False):
for
name
in
namev
:
for
name
in
namev
:
if
_lat1_skipname
(
name
):
if
_lat1_skipname
(
name
):
continue
continue
b
=
Bn
[
name
]
s
=
b
.
stats
()
s
=
S
[
name
]
#if details:
# print '%s:\t%s' % (name, s)
node
,
xname
=
name
.
split
(
'/'
,
1
)
node
,
xname
=
name
.
split
(
'/'
,
1
)
yticks
.
add
(
s
.
avg
)
yticks
.
add
(
s
.
avg
)
...
@@ -589,9 +594,9 @@ def main():
...
@@ -589,9 +594,9 @@ def main():
ax2
=
plt
.
subplot2grid
((
7
,
2
),
(
0
,
1
),
rowspan
=
6
)
ax2
=
plt
.
subplot2grid
((
7
,
2
),
(
0
,
1
),
rowspan
=
6
)
ax2
.
set_title
(
u'latency, µs/object (↓ is better)'
)
ax2
.
set_title
(
u'latency, µs/object (↓ is better)'
)
Slat
=
xseriesof
(
Bu
[
Unit
(
u'latency-
µs/object'
)]
)
Slat
=
xseriesof
(
Bu
[
Unit
(
u'latency-
s/object'
)].
convert_unit
(
u'latency-µs/object'
)
)
if
Slat
is
None
:
if
Slat
is
None
:
raise
RuntimeError
(
'%s: latency-
µ
s/object: series not found'
%
(
labkey
,))
raise
RuntimeError
(
'%s: latency-s/object: series not found'
%
(
labkey
,))
plotseries
(
ax2
,
labkey
,
Slat
)
plotseries
(
ax2
,
labkey
,
Slat
)
...
@@ -630,6 +635,12 @@ def main():
...
@@ -630,6 +635,12 @@ def main():
ax211
.
set_xticks
([])
ax211
.
set_xticks
([])
ax211
.
set_xticklabels
([])
ax211
.
set_xticklabels
([])
plotnode1
(
ax211
,
B
,
w
=
0.007
,
details
=
True
)
plotnode1
(
ax211
,
B
,
w
=
0.007
,
details
=
True
)
# small title for ax211
#ax211.text(0.5, 1.005, 'basic ops, µs', ha='center', fontsize='x-small', transform=ax211.transAxes)
bb
=
ax211
.
get_legend
().
get_bbox_to_anchor
()
xc
,
ymax
=
ax211
.
transAxes
.
inverted
().
transform
(((
bb
.
xmin
+
bb
.
xmax
)
/
2.
,
bb
.
ymax
))
xc
+=
1.5
# FIXME because bb.xmax = xmin
ax211
.
text
(
xc
,
ymax
+
0.005
,
'basic ops, µs/op'
,
ha
=
'center'
,
fontsize
=
'x-small'
,
transform
=
ax211
.
transAxes
)
# mark_inset(ax21, ax211, ...)
# mark_inset(ax21, ax211, ...)
rect
=
TransformedBbox
(
ax211
.
viewLim
,
ax21
.
transData
)
rect
=
TransformedBbox
(
ax211
.
viewLim
,
ax21
.
transData
)
...
...
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