121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			121 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
| #!/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__':
 | |
|     ignores = [ '.git', 'raw-data', 'util' ]
 | |
| 
 | |
|     basedir = os.path.dirname(os.path.abspath(__file__)) + '/../'
 | |
|     entries = [(os.path.basename(re.sub(r'/+$', '', p)), p) for p in os.listdir(basedir)]
 | |
|     entries.sort()
 | |
| 
 | |
|     maxnamelen = 0
 | |
|     maxstorynamelen = 0
 | |
|     res = {}
 | |
| 
 | |
|     stories = set()
 | |
|     for name, ent in entries:
 | |
|         entdir = basedir + ent
 | |
|         if (not os.path.isdir(entdir)) or (ent in ignores):
 | |
|             continue
 | |
| 
 | |
|         files = [p for p in os.listdir(entdir) 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(entdir, 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 res:
 | |
|         r = Stat(0, 0)
 | |
|         for _, stat in res[name].items():
 | |
|             r.srclen += stat.srclen
 | |
|             r.complen += stat.complen
 | |
|         overall[name] = r
 | |
|         maxnamelen = max(maxnamelen, len(format_result(r)))
 | |
| 
 | |
|     storynameformat = '|{{:{}}} |'.format(maxstorynamelen)
 | |
|     nameformat = '{{:{}}} |'.format(maxnamelen)
 | |
| 
 | |
|     sys.stdout.write('''\
 | |
| The each cell has X (Y/Z) format:  
 | |
| 
 | |
| **X**: Y / Z  
 | |
| **Y**: Number of bytes after compression  
 | |
| **Z**: Number of bytes before compression  
 | |
| 
 | |
| ''')
 | |
| 
 | |
|     names = res.keys()
 | |
|     names.sort()
 | |
| 
 | |
|     sys.stdout.write(storynameformat.format('story'))
 | |
|     for name in names:
 | |
|         sys.stdout.write(nameformat.format(name))
 | |
|     sys.stdout.write('\n')
 | |
| 
 | |
|     sys.stdout.write('|')
 | |
|     sys.stdout.write('-'*(maxstorynamelen+1))
 | |
|     sys.stdout.write('|')
 | |
|     for _ in names:
 | |
|         sys.stdout.write('-'*(maxnamelen+1))
 | |
|         sys.stdout.write('|')
 | |
|     sys.stdout.write('\n')
 | |
| 
 | |
|     for story in stories:
 | |
|         sys.stdout.write(storynameformat.format(story))
 | |
|         srclen = -1
 | |
|         for name in names:
 | |
|             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 name in names:
 | |
|         sys.stdout.write(nameformat.format(format_result(overall[name])))
 | |
|     sys.stdout.write('\n')
 | |
| 
 |