• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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#
14import sys, json, os, re
15
16class Stat:
17
18    def __init__(self, complen, srclen):
19        self.complen = complen
20        self.srclen = srclen
21
22def 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
32def format_result(r):
33    return '{:.02f} ({}/{}) '.format(r.complen/r.srclen, r.complen, r.srclen)
34
35if __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('''\
63hpack-test-case compression ratio
64=================================
65
66The each cell has ``X (Y/Z)`` format:
67
68X
69  Y / Z
70Y
71  number of bytes after compression
72Z
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()
110