|
1 |
| -#!/usr/bin/env python2 |
2 |
| - |
| 1 | +#!/usr/bin/env python3 |
| 2 | +import random |
3 | 3 | import sys
|
4 | 4 | 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)) |
15 | 5 |
|
16 | 6 |
|
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))] |
19 | 90 |
|
20 |
| - ys = [6 * (i+1) for i in xrange(len(runs))] |
21 | 91 | ax = fig.add_subplot(subplot)
|
22 | 92 | ax.set_title(title)
|
23 | 93 | ax.set_yticks(ys)
|
24 | 94 | ax.set_yticklabels(runs)
|
25 | 95 | ax.tick_params(which='major', length=0)
|
26 | 96 | ax.set_xlabel('seconds')
|
27 | 97 |
|
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