Skip to content

Commit 7cc8377

Browse files
JakkuSakuraVtec234
andauthored
Better plot.py with Python 3 & remove hard code (#569)
* Better plot.py with Python 3 & remove hard code * Update plot.py * Update plot.py * Cleaner names Co-authored-by: Wojciech Nawrocki <wjnawrocki+gh@protonmail.com>
1 parent e97836c commit 7cc8377

File tree

1 file changed

+136
-108
lines changed
  • crossbeam-channel/benchmarks

1 file changed

+136
-108
lines changed

crossbeam-channel/benchmarks/plot.py

+136-108
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,148 @@
1-
#!/usr/bin/env python2
2-
1+
#!/usr/bin/env python3
2+
import random
33
import sys
44
import matplotlib.pyplot as plt
5-
import matplotlib.patches as mpatches
6-
7-
results = []
8-
for f in sys.argv[1:]:
9-
with open(f) as f:
10-
for line in f.readlines():
11-
test, lang, impl, secs, _ = line.split()
12-
results.append((test, lang, impl, float(secs)))
13-
14-
fig = plt.figure(figsize=(10, 10))
155

166

17-
def plot(subplot, title, prefix, runs):
18-
runs.reverse()
7+
def read_data(files):
8+
results = []
9+
for f in files:
10+
with open(f) as f:
11+
for line in f.readlines():
12+
test, lang, impl, secs, _ = line.split()
13+
splt = test.split('_')
14+
results.append((splt[0], '_'.join(splt[1:]), lang, impl, float(secs)))
15+
return results
16+
17+
18+
def get_runs(results, prefix):
19+
runs = set()
20+
for pre, test, lang, impl, secs in results:
21+
if pre == prefix:
22+
runs.add(test)
23+
result = list(runs)
24+
result.sort()
25+
return result
26+
27+
28+
def find(s, x):
29+
for i in range(len(s)):
30+
if s[i] == x:
31+
return i
32+
return None
33+
34+
35+
color_set = {
36+
'aqua': '#00ffff',
37+
'azure': '#f0ffff',
38+
'beige': '#f5f5dc',
39+
'black': '#000000',
40+
'blue': '#0000ff',
41+
'brown': '#a52a2a',
42+
'cyan': '#00ffff',
43+
'darkblue': '#00008b',
44+
'darkcyan': '#008b8b',
45+
'darkgrey': '#a9a9a9',
46+
'darkgreen': '#006400',
47+
'darkkhaki': '#bdb76b',
48+
'darkmagenta': '#8b008b',
49+
'darkolivegreen': '#556b2f',
50+
'darkorange': '#ff8c00',
51+
'darkorchid': '#9932cc',
52+
'darkred': '#8b0000',
53+
'darksalmon': '#e9967a',
54+
'darkviolet': '#9400d3',
55+
'fuchsia': '#ff00ff',
56+
'gold': '#ffd700',
57+
'green': '#008000',
58+
'indigo': '#4b0082',
59+
'khaki': '#f0e68c',
60+
'lightblue': '#add8e6',
61+
'lightcyan': '#e0ffff',
62+
'lightgreen': '#90ee90',
63+
'lightgrey': '#d3d3d3',
64+
'lightpink': '#ffb6c1',
65+
'lightyellow': '#ffffe0',
66+
'lime': '#00ff00',
67+
'magenta': '#ff00ff',
68+
'maroon': '#800000',
69+
'navy': '#000080',
70+
'olive': '#808000',
71+
'orange': '#ffa500',
72+
'pink': '#ffc0cb',
73+
'purple': '#800080',
74+
'red': '#ff0000',
75+
}
76+
saved_color = {}
77+
78+
79+
def get_color(name):
80+
if name not in saved_color:
81+
color = color_set.popitem()
82+
saved_color[name] = color
83+
return saved_color[name][1]
84+
85+
86+
def plot(results, fig, subplot, title, prefix):
87+
runs = get_runs(results, prefix)
88+
89+
ys = [len(runs) * (i + 1) for i in range(len(runs))]
1990

20-
ys = [6 * (i+1) for i in xrange(len(runs))]
2191
ax = fig.add_subplot(subplot)
2292
ax.set_title(title)
2393
ax.set_yticks(ys)
2494
ax.set_yticklabels(runs)
2595
ax.tick_params(which='major', length=0)
2696
ax.set_xlabel('seconds')
2797

28-
go = [0] * len(runs)
29-
mpsc = [0] * len(runs)
30-
futures_channel = [0] * len(runs)
31-
chan = [0] * len(runs)
32-
crossbeam_channel = [0] * len(runs)
33-
34-
for (i, run) in enumerate(runs):
35-
for (test, lang, impl, secs) in results:
36-
if test == prefix + '_' + run:
37-
if lang == 'Go' and impl == 'chan':
38-
go[i] = secs
39-
if lang == 'Rust' and impl == 'mpsc':
40-
mpsc[i] = secs
41-
if lang == 'Rust' and impl == 'futures-channel':
42-
futures_channel[i] = secs
43-
if lang == 'Rust' and impl == 'chan':
44-
chan[i] = secs
45-
if lang == 'Rust' and impl == 'crossbeam-channel':
46-
crossbeam_channel[i] = secs
47-
48-
opts = dict(height=0.7, align='center')
49-
ax.barh([y-2 for y in ys], go, color='skyblue', **opts)
50-
ax.barh([y-1 for y in ys], crossbeam_channel, color='red', **opts)
51-
ax.barh([y+0 for y in ys], chan, color='orange', **opts)
52-
ax.barh([y+1 for y in ys], mpsc, color='black', **opts)
53-
ax.barh([y+2 for y in ys], futures_channel, color='blue', **opts)
54-
55-
m = int(max(go + mpsc + futures_channel + chan + crossbeam_channel) * 1.3)
56-
if m < 10:
57-
ax.set_xticks(range(m + 1))
58-
elif m < 50:
59-
ax.set_xticks([x*5 for x in range(m / 5 + 1)])
60-
elif m < 100:
61-
ax.set_xticks([x*10 for x in range(m / 10 + 1)])
62-
elif m < 100:
63-
ax.set_xticks([x*20 for x in range(m / 20 + 1)])
64-
else:
65-
ax.set_xticks([x*100 for x in range(m / 100 + 1)])
66-
67-
for (x, y) in zip(go, ys):
68-
if x > 0:
69-
ax.text(x+m/200., y-2-0.3, 'Go', fontsize=9)
70-
for (x, y) in zip(crossbeam_channel, ys):
71-
if x > 0:
72-
ax.text(x+m/200., y-1-0.3, 'crossbeam-channel', fontsize=9)
73-
for (x, y) in zip(chan, ys):
74-
if x > 0:
75-
ax.text(x+m/200., y+0-0.3, 'chan', fontsize=9)
76-
for (x, y) in zip(mpsc, ys):
77-
if x > 0:
78-
ax.text(x+m/200., y+1-0.3, 'mpsc', fontsize=9)
79-
for (x, y) in zip(futures_channel, ys):
80-
if x > 0:
81-
ax.text(x+m/200., y+2-0.3, 'futures-channel', fontsize=9)
82-
83-
plot(
84-
221,
85-
"Bounded channel of capacity 0",
86-
'bounded0',
87-
['spsc', 'mpsc', 'mpmc', 'select_rx', 'select_both'],
88-
)
89-
90-
plot(
91-
222,
92-
"Bounded channel of capacity 1",
93-
'bounded1',
94-
['spsc', 'mpsc', 'mpmc', 'select_rx', 'select_both'],
95-
)
96-
97-
plot(
98-
223,
99-
"Bounded channel of capacity N",
100-
'bounded',
101-
['seq', 'spsc', 'mpsc', 'mpmc', 'select_rx', 'select_both'],
102-
)
103-
104-
plot(
105-
224,
106-
"Unbounded channel",
107-
'unbounded',
108-
['seq', 'spsc', 'mpsc', 'mpmc', 'select_rx', 'select_both'],
109-
)
110-
111-
plt.subplots_adjust(
112-
top=0.95,
113-
bottom=0.05,
114-
left=0.1,
115-
right=0.95,
116-
wspace=0.3,
117-
hspace=0.2,
118-
)
119-
plt.savefig('plot.png')
120-
# plt.show()
98+
scores = {}
99+
100+
for pre, test, lang, impl, secs in results:
101+
if pre == prefix:
102+
name = impl if lang == 'Rust' else impl + f' ({lang})'
103+
if name not in scores:
104+
scores[name] = [0] * len(runs)
105+
scores[name][find(runs, test)] = secs
106+
107+
opts = dict(height=0.8, align='center')
108+
x_max = max(max(scores.values(), key=lambda x: max(x)))
109+
for i, (name, score) in enumerate(scores.items()):
110+
yy = [y + i - len(runs) // 2 + 0.2 for y in ys]
111+
ax.barh(yy, score, color=get_color(name), **opts)
112+
for xxx, yyy in zip(score, yy):
113+
if xxx:
114+
ax.text(min(x_max - len(name) * 0.018 * x_max, xxx), yyy - 0.25, name, fontsize=9)
115+
116+
117+
def plot_all(results, descriptions, labels):
118+
fig = plt.figure(figsize=(10, 10))
119+
# TODO support more number subplots
120+
subplot = [221, 222, 223, 224]
121+
for p, d, l in zip(subplot, descriptions, labels):
122+
plot(results, fig, p, d, l)
123+
plt.subplots_adjust(
124+
top=0.95,
125+
bottom=0.05,
126+
left=0.1,
127+
right=0.95,
128+
wspace=0.3,
129+
hspace=0.2,
130+
)
131+
plt.savefig('plot.png')
132+
# plt.show()
133+
134+
135+
def main():
136+
results = read_data(sys.argv[1:])
137+
descriptions = [
138+
'Bounded channel of capacity 0',
139+
'Bounded channel of capacity 1',
140+
'Bounded channel of capacity N',
141+
'Unbounded channel',
142+
]
143+
labels = ['bounded0', 'bounded1', 'bounded', 'unbounded']
144+
plot_all(results, descriptions, labels)
145+
146+
147+
if __name__ == '__main__':
148+
main()

0 commit comments

Comments
 (0)