OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Profiler to compare various compression levels with regards to speed | |
7 and final size when compressing the full set of files from a given | |
8 isolated file. | |
9 """ | |
10 | |
11 import bz2 | |
12 import optparse | |
13 import os | |
14 import shutil | |
15 import subprocess | |
16 import sys | |
17 import tempfile | |
18 import time | |
19 import zlib | |
20 | |
21 ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | |
22 sys.path.insert(0, ROOT_DIR) | |
23 | |
24 from utils import tools | |
25 | |
26 | |
27 def zip_file(compressor_constructor, compression_level, filename): | |
28 compressed_size = 0 | |
29 compressor = compressor_constructor(compression_level) | |
30 with open(filename, 'rb') as f: | |
31 while True: | |
32 chunk = f.read(16 * 1024) | |
33 if not chunk: | |
34 break | |
35 compressed_size += len(compressor.compress(f.read())) | |
36 compressed_size += len(compressor.flush()) | |
37 | |
38 return compressed_size | |
39 | |
40 | |
41 def zip_directory(compressor_constructor, compression_level, root_dir): | |
42 compressed_size = 0 | |
43 for root, _, files in os.walk(root_dir): | |
44 compressed_size += sum(zip_file(compressor_constructor, compression_level, | |
45 os.path.join(root, name)) | |
46 for name in files) | |
47 return compressed_size | |
48 | |
49 | |
50 def profile_compress(zip_module_name, compressor_constructor, | |
51 compression_range, compress_func, compress_target): | |
52 for i in compression_range: | |
53 start_time = time.time() | |
54 compressed_size = compress_func(compressor_constructor, i, compress_target) | |
55 end_time = time.time() | |
56 | |
57 print('%4s at compression level %s, total size %11d, time taken %6.3f' % | |
58 (zip_module_name, i, compressed_size, end_time - start_time)) | |
59 | |
60 | |
61 def tree_files(root_dir): | |
62 file_set = {} | |
63 for root, _, files in os.walk(root_dir): | |
64 for name in files: | |
65 filename = os.path.join(root, name) | |
66 file_set[filename] = os.stat(filename).st_size | |
67 | |
68 return file_set | |
69 | |
70 | |
71 def main(): | |
72 tools.disable_buffering() | |
73 parser = optparse.OptionParser() | |
74 parser.add_option('-s', '--isolated', help='.isolated file to profile with.') | |
75 parser.add_option('--largest_files', type='int', | |
76 help='If this is set, instead of compressing all the ' | |
77 'files, only the large n files will be compressed') | |
78 options, args = parser.parse_args() | |
79 | |
80 if args: | |
81 parser.error('Unknown args passed in; %s' % args) | |
82 if not options.isolated: | |
83 parser.error('The .isolated file must be given.') | |
84 | |
85 temp_dir = None | |
86 try: | |
87 temp_dir = tempfile.mkdtemp() | |
88 | |
89 # Create a directory of the required files | |
90 subprocess.check_call([os.path.join(ROOT_DIR, 'isolate.py'), | |
91 'remap', | |
92 '-s', options.isolated, | |
93 '--outdir', temp_dir]) | |
94 | |
95 file_set = tree_files(temp_dir) | |
96 | |
97 if options.largest_files: | |
98 sorted_by_size = sorted(file_set.iteritems(), key=lambda x: x[1], | |
99 reverse=True) | |
100 files_to_compress = sorted_by_size[:options.largest_files] | |
101 | |
102 for filename, size in files_to_compress: | |
103 print('Compressing %s, uncompressed size %d' % (filename, size)) | |
104 | |
105 profile_compress('zlib', zlib.compressobj, range(10), zip_file, | |
106 filename) | |
107 profile_compress('bz2', bz2.BZ2Compressor, range(1, 10), zip_file, | |
108 filename) | |
109 else: | |
110 print('Number of files: %s' % len(file_set)) | |
111 print('Total size: %s' % sum(file_set.itervalues())) | |
112 | |
113 # Profile! | |
114 profile_compress('zlib', zlib.compressobj, range(10), zip_directory, | |
115 temp_dir) | |
116 profile_compress('bz2', bz2.BZ2Compressor, range(1, 10), zip_directory, | |
117 temp_dir) | |
118 finally: | |
119 shutil.rmtree(temp_dir) | |
120 | |
121 | |
122 if __name__ == '__main__': | |
123 sys.exit(main()) | |
OLD | NEW |