-
Notifications
You must be signed in to change notification settings - Fork 12
/
Copy pathgenratiotbl.py
executable file
·131 lines (108 loc) · 3.73 KB
/
genratiotbl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python
#
# This script takes directories which contain the hpack-test-case json
# files, and calculates the compression ratio in each file and outputs
# the result in table formatted in rst.
#
# The each directory contains the result of various HPACK compressor.
#
# The table is laid out so that we can see that how input header set
# in one json file is compressed in each compressor.
#
import sys, json, os, re, argparse
class Stat:
def __init__(self, complen, srclen):
self.complen = complen
self.srclen = srclen
def compute_stat(jsdata):
complen = 0
srclen = 0
for item in jsdata['cases']:
complen += len(item['wire']) // 2
srclen += \
sum([len(list(x.keys())[0]) + len(list(x.values())[0]) \
for x in item['headers']])
return Stat(complen, srclen)
def format_result(r):
return '{:.02f} ({}/{}) '.format(float(r.complen)/r.srclen,
r.complen, r.srclen)
if __name__ == '__main__':
ap = argparse.ArgumentParser(description='''\
Generate HPACK compression ratio table in reStructuredText.
An output is written to stdout.
''')
ap.add_argument('dir', nargs='+',
help='A directory containing JSON files')
args = ap.parse_args()
entries = [(os.path.basename(re.sub(r'/+$', '', p)), p) for p in args.dir]
maxnamelen = 0
maxstorynamelen = 0
res = {}
stories = set()
for name, ent in entries:
files = [p for p in os.listdir(ent) if p.endswith('.json')]
res[name] = {}
maxnamelen = max(maxnamelen, len(name))
for fn in files:
stories.add(fn)
maxstorynamelen = max(maxstorynamelen, len(fn))
with open(os.path.join(ent, fn)) as f:
input = f.read()
rv = compute_stat(json.loads(input))
res[name][fn] = rv
maxnamelen = max(maxnamelen, len(format_result(rv)))
stories = list(stories)
stories.sort()
overall = []
for name, _ in entries:
r = Stat(0, 0)
for _, stat in res[name].items():
r.srclen += stat.srclen
r.complen += stat.complen
overall.append(r)
maxnamelen = max(maxnamelen, len(format_result(r)))
storynameformat = '{{:{}}} '.format(maxstorynamelen)
nameformat = '{{:{}}} '.format(maxnamelen)
sys.stdout.write('''\
hpack-test-case compression ratio
=================================
The each cell has ``X (Y/Z)`` format:
X
Y / Z
Y
number of bytes after compression
Z
number of bytes before compression
''')
def write_border():
sys.stdout.write('='*maxstorynamelen)
sys.stdout.write(' ')
for _ in entries:
sys.stdout.write('='*maxnamelen)
sys.stdout.write(' ')
sys.stdout.write('\n')
write_border()
sys.stdout.write(storynameformat.format('story'))
for name, _ in entries:
sys.stdout.write(nameformat.format(name))
sys.stdout.write('\n')
write_border()
for story in stories:
sys.stdout.write(storynameformat.format(story))
srclen = -1
for name, _ in entries:
stats = res[name]
if story not in stats:
sys.stdout.write(nameformat.format('N/A'))
continue
if srclen == -1:
srclen = stats[story].srclen
elif srclen != stats[story].srclen:
raise Exception('Bad srclen')
sys.stdout.write(nameformat.format(format_result(stats[story])))
sys.stdout.write('\n')
sys.stdout.write(storynameformat.format('Overall'))
for r in overall:
sys.stdout.write(nameformat.format(format_result(r)))
sys.stdout.write('\n')
write_border()