xref: /aosp_15_r20/external/regex-re2/benchlog/benchplot.py (revision ccdc9c3e24c519bfa4832a66aa2e83a52c19f295)
1*ccdc9c3eSSadaf Ebrahimi#!/usr/bin/env python
2*ccdc9c3eSSadaf Ebrahimi
3*ccdc9c3eSSadaf Ebrahimiimport argparse     # for ArgumentParser
4*ccdc9c3eSSadaf Ebrahimiimport subprocess   # for Popen
5*ccdc9c3eSSadaf Ebrahimiimport tempfile     # for NamedTemporaryFile
6*ccdc9c3eSSadaf Ebrahimiimport os           # for remove
7*ccdc9c3eSSadaf Ebrahimi
8*ccdc9c3eSSadaf Ebrahimiclass gnuplot(object):
9*ccdc9c3eSSadaf Ebrahimi
10*ccdc9c3eSSadaf Ebrahimi    output = "result.png"
11*ccdc9c3eSSadaf Ebrahimi
12*ccdc9c3eSSadaf Ebrahimi    script = """
13*ccdc9c3eSSadaf Ebrahimi             set terminal png size 1024, 768
14*ccdc9c3eSSadaf Ebrahimi             set output "{}.png"
15*ccdc9c3eSSadaf Ebrahimi             set title "re2 benchlog"
16*ccdc9c3eSSadaf Ebrahimi             set datafile separator ";"
17*ccdc9c3eSSadaf Ebrahimi             set grid x y
18*ccdc9c3eSSadaf Ebrahimi             set ylabel "MB/s"
19*ccdc9c3eSSadaf Ebrahimi             set autoscale
20*ccdc9c3eSSadaf Ebrahimi             plot """
21*ccdc9c3eSSadaf Ebrahimi
22*ccdc9c3eSSadaf Ebrahimi    template = """'{}' using 1:5:xticlabels(2) with linespoints linewidth 3 title "{}",\\\n"""
23*ccdc9c3eSSadaf Ebrahimi
24*ccdc9c3eSSadaf Ebrahimi    benchdata = dict()
25*ccdc9c3eSSadaf Ebrahimi    tempfiles = []
26*ccdc9c3eSSadaf Ebrahimi
27*ccdc9c3eSSadaf Ebrahimi    def __enter__(self):
28*ccdc9c3eSSadaf Ebrahimi        return self
29*ccdc9c3eSSadaf Ebrahimi
30*ccdc9c3eSSadaf Ebrahimi    def __exit__(self, type, value, traceback):
31*ccdc9c3eSSadaf Ebrahimi        """
32*ccdc9c3eSSadaf Ebrahimi        remove all temporary files
33*ccdc9c3eSSadaf Ebrahimi        """
34*ccdc9c3eSSadaf Ebrahimi
35*ccdc9c3eSSadaf Ebrahimi        for filename in self.tempfiles:
36*ccdc9c3eSSadaf Ebrahimi            os.remove(filename)
37*ccdc9c3eSSadaf Ebrahimi
38*ccdc9c3eSSadaf Ebrahimi    def parse_re2_benchlog(self, filename):
39*ccdc9c3eSSadaf Ebrahimi        """
40*ccdc9c3eSSadaf Ebrahimi        parse the input benchlog and return a dictionary contain bench data
41*ccdc9c3eSSadaf Ebrahimi        """
42*ccdc9c3eSSadaf Ebrahimi
43*ccdc9c3eSSadaf Ebrahimi        benchdata = self.benchdata
44*ccdc9c3eSSadaf Ebrahimi
45*ccdc9c3eSSadaf Ebrahimi        with open(filename) as f:
46*ccdc9c3eSSadaf Ebrahimi
47*ccdc9c3eSSadaf Ebrahimi            for raw in f.readlines():
48*ccdc9c3eSSadaf Ebrahimi
49*ccdc9c3eSSadaf Ebrahimi                data = raw.split('\t')
50*ccdc9c3eSSadaf Ebrahimi
51*ccdc9c3eSSadaf Ebrahimi                if len(data) == 4:
52*ccdc9c3eSSadaf Ebrahimi
53*ccdc9c3eSSadaf Ebrahimi                    data = data[0].split('/') + data[1:]
54*ccdc9c3eSSadaf Ebrahimi                    data = list(map(str.strip, data))
55*ccdc9c3eSSadaf Ebrahimi
56*ccdc9c3eSSadaf Ebrahimi                    if not benchdata.get(data[0]):
57*ccdc9c3eSSadaf Ebrahimi                        benchdata[data[0]] = [ data[1:] ]
58*ccdc9c3eSSadaf Ebrahimi                    else:
59*ccdc9c3eSSadaf Ebrahimi                        benchdata[data[0]].append(data[1:])
60*ccdc9c3eSSadaf Ebrahimi
61*ccdc9c3eSSadaf Ebrahimi    def gen_csv(self):
62*ccdc9c3eSSadaf Ebrahimi        """
63*ccdc9c3eSSadaf Ebrahimi        generate temporary csv files
64*ccdc9c3eSSadaf Ebrahimi        """
65*ccdc9c3eSSadaf Ebrahimi
66*ccdc9c3eSSadaf Ebrahimi        for name, data in self.benchdata.items():
67*ccdc9c3eSSadaf Ebrahimi
68*ccdc9c3eSSadaf Ebrahimi            with tempfile.NamedTemporaryFile(delete=False) as f:
69*ccdc9c3eSSadaf Ebrahimi
70*ccdc9c3eSSadaf Ebrahimi                for index, line in enumerate(data):
71*ccdc9c3eSSadaf Ebrahimi                    f.write('{};{}\n'.format(index, ';'.join(line)).encode())
72*ccdc9c3eSSadaf Ebrahimi
73*ccdc9c3eSSadaf Ebrahimi                self.tempfiles.append(f.name)
74*ccdc9c3eSSadaf Ebrahimi                self.script = self.script + self.template.format(f.name, name)
75*ccdc9c3eSSadaf Ebrahimi
76*ccdc9c3eSSadaf Ebrahimi    def run(self):
77*ccdc9c3eSSadaf Ebrahimi        self.gen_csv()
78*ccdc9c3eSSadaf Ebrahimi        script = self.script[:-3].format(self.output)
79*ccdc9c3eSSadaf Ebrahimi        command = subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
80*ccdc9c3eSSadaf Ebrahimi        command.communicate(script.encode())
81*ccdc9c3eSSadaf Ebrahimi
82*ccdc9c3eSSadaf Ebrahimi
83*ccdc9c3eSSadaf Ebrahimiif __name__ == '__main__':
84*ccdc9c3eSSadaf Ebrahimi
85*ccdc9c3eSSadaf Ebrahimi    parser = argparse.ArgumentParser(description='generate plots for benchlog')
86*ccdc9c3eSSadaf Ebrahimi    parser.add_argument('benchlog', type=str, help='benchlog generated by re2')
87*ccdc9c3eSSadaf Ebrahimi    args = parser.parse_args()
88*ccdc9c3eSSadaf Ebrahimi
89*ccdc9c3eSSadaf Ebrahimi    try:
90*ccdc9c3eSSadaf Ebrahimi        subprocess.Popen(['gnuplot'], stdin=subprocess.PIPE)
91*ccdc9c3eSSadaf Ebrahimi    except FileNotFoundError:
92*ccdc9c3eSSadaf Ebrahimi        print('you can install "gnuplot" to generate plots automatically')
93*ccdc9c3eSSadaf Ebrahimi        exit(1)
94*ccdc9c3eSSadaf Ebrahimi
95*ccdc9c3eSSadaf Ebrahimi    with gnuplot() as plot:
96*ccdc9c3eSSadaf Ebrahimi        plot.output = args.benchlog
97*ccdc9c3eSSadaf Ebrahimi        plot.parse_re2_benchlog(args.benchlog)
98*ccdc9c3eSSadaf Ebrahimi        plot.run()
99