tizen 2.4 release
[external/nghttp2.git] / python / calcratio.py
1 #!/usr/bin/env python
2 #
3 # This script takes directories which contain the hpack-test-case json
4 # files, and calculates the compression ratio in each file and outputs
5 # the result in table formatted in rst.
6 #
7 # The each directory contains the result of various HPACK compressor.
8 #
9 # The table is laid out so that we can see that how input header set
10 # in one json file is compressed in each compressor.
11 #
12 # For hpack-test-case, see https://github.com/Jxck/hpack-test-case
13 #
14 import sys, json, os, re
15
16 class Stat:
17
18     def __init__(self, complen, srclen):
19         self.complen = complen
20         self.srclen = srclen
21
22 def compute_stat(jsdata):
23     complen = 0
24     srclen = 0
25     for item in jsdata['cases']:
26         complen += len(item['wire']) // 2
27         srclen += \
28                   sum([len(list(x.keys())[0]) + len(list(x.values())[0]) \
29                        for x in item['headers']])
30     return Stat(complen, srclen)
31
32 def format_result(r):
33     return '{:.02f} ({}/{}) '.format(r.complen/r.srclen, r.complen, r.srclen)
34
35 if __name__ == '__main__':
36     entries = [(os.path.basename(re.sub(r'/+$', '', p)), p) \
37                for p in sys.argv[1:]]
38     maxnamelen = 0
39     maxstorynamelen = 0
40     res = {}
41
42     stories = set()
43     for name, ent in entries:
44         files = [p for p in os.listdir(ent) if p.endswith('.json')]
45         res[name] = {}
46         maxnamelen = max(maxnamelen, len(name))
47         for fn in files:
48             stories.add(fn)
49             maxstorynamelen = max(maxstorynamelen, len(fn))
50             with open(os.path.join(ent, fn)) as f:
51                 input = f.read()
52             rv = compute_stat(json.loads(input))
53             res[name][fn] = rv
54             maxnamelen = max(maxnamelen, len(format_result(rv)))
55     stories = list(stories)
56     stories.sort()
57
58     storynameformat = '{{:{}}} '.format(maxstorynamelen)
59     nameformat = '{{:{}}} '.format(maxnamelen)
60
61
62     sys.stdout.write('''\
63 hpack-test-case compression ratio
64 =================================
65
66 The each cell has ``X (Y/Z)`` format:
67
68 X
69   Y / Z
70 Y
71   number of bytes after compression
72 Z
73   number of bytes before compression
74
75 ''')
76
77     def write_border():
78         sys.stdout.write('='*maxstorynamelen)
79         sys.stdout.write(' ')
80         for _ in entries:
81             sys.stdout.write('='*maxnamelen)
82             sys.stdout.write(' ')
83         sys.stdout.write('\n')
84
85     write_border()
86
87     sys.stdout.write(storynameformat.format('story'))
88     for name, _ in entries:
89         sys.stdout.write(nameformat.format(name))
90     sys.stdout.write('\n')
91
92     write_border()
93
94     for story in stories:
95         sys.stdout.write(storynameformat.format(story))
96         srclen = -1
97         for name, _ in entries:
98             stats = res[name]
99             if story not in stats:
100                 sys.stdout.write(nameformat.format('N/A'))
101                 continue
102             if srclen == -1:
103                 srclen = stats[story].srclen
104             elif srclen != stats[story].srclen:
105                 raise Exception('Bad srclen')
106             sys.stdout.write(nameformat.format(format_result(stats[story])))
107         sys.stdout.write('\n')
108
109     write_border()