first public release
[dpdk.git] / app / test / graph_mempool.py
1 #!/usr/bin/env python
2
3 #   BSD LICENSE
4
5 #   Copyright(c) 2010-2012 Intel Corporation. All rights reserved.
6 #   All rights reserved.
7
8 #   Redistribution and use in source and binary forms, with or without 
9 #   modification, are permitted provided that the following conditions 
10 #   are met:
11
12 #     * Redistributions of source code must retain the above copyright 
13 #       notice, this list of conditions and the following disclaimer.
14 #     * Redistributions in binary form must reproduce the above copyright 
15 #       notice, this list of conditions and the following disclaimer in 
16 #       the documentation and/or other materials provided with the 
17 #       distribution.
18 #     * Neither the name of Intel Corporation nor the names of its 
19 #       contributors may be used to endorse or promote products derived 
20 #       from this software without specific prior written permission.
21
22 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
23 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
24 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 
25 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
26 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
27 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
28 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
29 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
30 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
31 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
32 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 #  version: DPDK.L.1.2.3-3
35
36 import sys, re
37 import numpy as np
38 import matplotlib
39 matplotlib.use('Agg') # we don't want to use X11
40 import matplotlib.pyplot as plt
41 from matplotlib.ticker import FuncFormatter
42
43 INT = "([-+]?[0-9][0-9]*)"
44
45 class MempoolTest:
46     l = []
47
48     def __init__(self):
49         pass
50
51     # sort a test case list
52     def sort(self, x, y):
53         for t in [ "cache", "cores", "n_get_bulk", "n_put_bulk",
54                    "n_keep", "rate" ]:
55             if x[t] > y[t]:
56                 return 1
57             if x[t] < y[t]:
58                 return -1
59         return 0
60
61     # add a test case
62     def add(self, **args):
63         self.l.append(args)
64
65     # get an ordered list matching parameters
66     # ex: r.get(enq_core=1, deq_core=1)
67     def get(self, **args):
68         retlist = []
69         for t in self.l:
70             add_it = 1
71             for a in args:
72                 if args[a] != t[a]:
73                     add_it = 0
74                     break
75             if add_it:
76                 retlist.append(t)
77         retlist.sort(cmp=self.sort)
78         return retlist
79
80     # return an ordered list of all values for this param or param list
81     # ex: r.get_value_list("enq_core")
82     def get_value_list(self, param):
83         retlist = []
84         if type(param) is not list:
85             param = [param]
86         for t in self.l:
87             entry = []
88             for p in param:
89                 entry.append(t[p])
90             if len(entry) == 1:
91                 entry = entry[0]
92             else:
93                 entry = tuple(entry)
94             if not entry in retlist:
95                 retlist.append(entry)
96         retlist.sort()
97         return retlist
98
99 # read the file and return a MempoolTest object containing all data
100 def read_data_from_file(filename):
101
102     mempool_test = MempoolTest()
103
104     # parse the file: it produces a list of dict containing the data for
105     # each test case (each dict in the list corresponds to a line)
106     f = open(filename)
107     while True:
108         l = f.readline()
109
110         if l == "":
111             break
112
113         regexp  = "mempool_autotest "
114         regexp += "cache=%s cores=%s "%(INT, INT)
115         regexp += "n_get_bulk=%s n_put_bulk=%s "%(INT, INT)
116         regexp += "n_keep=%s rate_persec=%s"%(INT, INT)
117         m = re.match(regexp, l)
118         if m == None:
119             continue
120
121         mempool_test.add(cache = int(m.groups()[0]),
122                          cores = int(m.groups()[1]),
123                          n_get_bulk = int(m.groups()[2]),
124                          n_put_bulk = int(m.groups()[3]),
125                          n_keep = int(m.groups()[4]),
126                          rate = int(m.groups()[5]))
127
128     f.close()
129     return mempool_test
130
131 def millions(x, pos):
132     return '%1.1fM' % (x*1e-6)
133
134 # graph one, with specific parameters -> generate a .svg file
135 def graph_one(str, mempool_test, cache, cores, n_keep):
136     filename = "mempool_%d_%d_%d.svg"%(cache, cores, n_keep)
137
138     n_get_bulk_list = mempool_test.get_value_list("n_get_bulk")
139     N_n_get_bulk = len(n_get_bulk_list)
140     get_names = map(lambda x:"get=%d"%x, n_get_bulk_list)
141
142     n_put_bulk_list = mempool_test.get_value_list("n_put_bulk")
143     N_n_put_bulk = len(n_put_bulk_list)
144     put_names = map(lambda x:"put=%d"%x, n_put_bulk_list)
145
146     N = N_n_get_bulk * (N_n_put_bulk + 1)
147     rates = []
148
149     colors = []
150     for n_get_bulk in mempool_test.get_value_list("n_get_bulk"):
151         col = 0.
152         for n_put_bulk in mempool_test.get_value_list("n_put_bulk"):
153             col += 0.9 / len(mempool_test.get_value_list("n_put_bulk"))
154             r = mempool_test.get(cache=cache, cores=cores,
155                                  n_get_bulk=n_get_bulk,
156                                  n_put_bulk=n_put_bulk, n_keep=n_keep)
157             if len(r) != 0:
158                 r = r[0]["rate"]
159                 rates.append(r)
160             colors.append((1. - col, 0.2, col, 1.)) # rgba
161
162         rates.append(0)
163         colors.append((0.,0.,0.,0.))
164
165     ind = np.arange(N)  # the x locations for the groups
166     width = 1           # the width of the bars: can also be len(x) sequence
167
168
169     formatter = FuncFormatter(millions)
170     fig = plt.figure()
171     p = plt.bar(ind, tuple(rates), width, color=tuple(colors))
172     fig.axes[0].yaxis.set_major_formatter(formatter)
173
174     plt.ylabel('Obj/sec')
175     #plt.ylim(0, 400000000.)
176     title  = "Mempool autotest \"%s\"\n"%(str)
177     title += "cache=%d, core(s)=%d, n_keep=%d"%(cache, cores, n_keep)
178     plt.title(title)
179     ind_names = np.arange(N_n_get_bulk) * (N_n_put_bulk+1) + (N_n_put_bulk+1) / 2
180     plt.xticks(ind_names, tuple(get_names))
181     plt.legend(tuple([p[i] for i in range(N_n_put_bulk)]), tuple(put_names),
182                loc="upper left")
183     plt.savefig(filename)
184
185 if len(sys.argv) != 3:
186     print "usage: graph_mempool.py file title"
187     sys.exit(1)
188
189 mempool_test = read_data_from_file(sys.argv[1])
190
191 for cache, cores, n_keep in mempool_test.get_value_list(["cache", "cores",
192                                                          "n_keep"]):
193     graph_one(sys.argv[2], mempool_test, cache, cores, n_keep)