d7a0083d8e7ab009c4ebb597c9d9aa76308c868e
[python-delta-tar] / testing / run_benchmark.py
1 #!/usr/bin/env python3
2
3 # Copyright (C) 2014 Intra2net AG
4 #
5 # This program is free software; you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published
7 # by the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 # GNU Lesser General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with this program.  If not, see
17 # <http://www.gnu.org/licenses/lgpl-3.0.html>
18
19 # Authors: Victor Ramirez de la Corte <victor@wadobo.com>
20 #          Eduardo Robles Elvira <edulix@wadobo.com>
21
22 import argparse
23 import os
24 import zlib
25 import fnmatch
26 import cProfile
27 import io
28 import pstats
29
30
31 def main(args = None):
32     '''
33     Main function, parses the command line arguments and launches the appropiate
34     benchmark test.
35     '''
36     parser = argparse.ArgumentParser(description='Profiling test options. ')
37     parser.add_argument('-t', '--test',
38                         choices=['delta-tarfile', 'tarfile', 'zlib',
39                                  'zlib-blocks'],
40                         help='Select option for testing. ')
41     parser.add_argument('-l', '--compression-level', type=int, default=9,
42                         choices=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
43                         help='Select level of compression for zlib. ')
44     parser.add_argument('-p', '--path',
45                         help='path to the file/dir to compress.')
46     parser.add_argument('-P', '--profile', action='store_true',
47                         help='Enable profile')
48     parser.add_argument('-m', '--tarmode',  default="w:gz",
49                         help='Specify tarfile mode [w:gz]')
50     parser.add_argument('-st', '--strategy', default='default',
51                         choices=['default', 'filtered', 'huffman_only'],
52                         help='Select the deflate strategy in zlib related '
53                              'tests.')
54     parser.add_argument(
55         '-s', '--sort',
56         help='Sort output profile',
57         choices=[ 'calls', 'cumulative', 'cumtime', 'file', 'path', 'module',
58             'ncalls', 'pcalls', 'line', 'name', 'nfl', 'stdname', 'time',
59             'tottime'],
60         default="cumulative")
61
62     if not args:
63         pargs = parser.parse_args()
64     else:
65         pargs = parser.parse_args(args)
66
67     compression_level = pargs.compression_level
68     path = pargs.path
69
70     # start profiling
71     if pargs.profile:
72         pr = cProfile.Profile()
73         pr.enable()
74
75     if pargs.test in ['delta-tarfile', 'tarfile']:
76         test_tarfile(pargs.test, compression_level, path, pargs.tarmode)
77     elif pargs.test == 'zlib':
78         test_zlib(compression_level, path, pargs.strategy)
79     elif pargs.test == 'zlib-blocks':
80         test_zlib_blocks(compression_level, path, pargs.strategy)
81     else:
82         parser.print_help()
83
84     # end profiling
85     if pargs.profile:
86         pr.disable()
87         print_profile(pr, pargs.sort)
88
89 def test_tarfile(res, compression_level=9, path='source_dir', tarmode="w:gz"):
90     '''
91     Test that creates a tarfile called test_tarfile.tar.gz
92     '''
93     if res == 'delta-tarfile':
94         deltatar = os.path.abspath("../deltatar")
95         import sys
96         sys.path.append("..")
97         from deltatar import tarfile as TarFile
98     elif res == 'tarfile':
99         import tarfile as TarFile
100
101     print("creating a tarfile with mode = '%s'" % tarmode)
102     with open('test_tarfile.tar.gz', 'wb') as fo:
103         tar = TarFile.open(mode=tarmode, fileobj=fo,
104                            compresslevel=compression_level)
105         tar.add(path)
106
107 def test_zlib(compression_level=9, path='source_dir', strategy='default',
108               BUFSIZE = 16 * 1024):
109     '''
110     Test that compresses a directory with zlib
111     '''
112     if strategy == 'default':
113         strategy = zlib.Z_DEFAULT_STRATEGY
114     elif strategy ==  'filtered':
115         strategy = zlib.Z_FILTERED
116     else:
117         strategy = zlib.Z_HUFFMAN_ONLY
118
119     c = zlib.compressobj(compression_level,
120                             zlib.DEFLATED,
121                             -zlib.MAX_WBITS,
122                             zlib.DEF_MEM_LEVEL,
123                                 strategy)
124
125     def add(path):
126         l = 0
127         l_orig = 0
128         if os.path.isdir(path):
129             for f in os.listdir(path):
130                 l2, l_orig2 = add(os.path.join(path, f))
131                 l += l2
132                 l_orig += l_orig2
133         elif os.path.isfile(path):
134             with open(path, 'rb') as fo:
135                 while True:
136                     buf = fo.read(BUFSIZE)
137                     l_orig += len(buf)
138                     if len(buf) == 0:
139                         return l, l_orig
140                     buf = c.compress(buf)
141                     if buf is not None:
142                         l += len(buf)
143         return l, l_orig
144
145     l, l_orig = add(path)
146     l += len(c.flush())
147     print("total size: %d MiB compressed, %d MiB uncompressed" % (
148         (l / (1024 ** 2)),
149         (l_orig / (1024 ** 2))))
150
151
152 def test_zlib_blocks(compression_level=9, path='source_dir', strategy='default',
153                      BUFSIZE = 16 * 1024):
154     '''
155     Test that compresses a directory with zlib
156     '''
157     if strategy == 'default':
158         strategy = zlib.Z_DEFAULT_STRATEGY
159     elif strategy ==  'filtered':
160         strategy = zlib.Z_FILTERED
161     else:
162         strategy = zlib.Z_HUFFMAN_ONLY
163
164     def add(path):
165         l = 0
166         l_orig = 0
167         if os.path.isdir(path):
168             for f in os.listdir(path):
169                 l2, l_orig2 = add(os.path.join(path, f))
170                 l += l2
171                 l_orig += l_orig2
172         elif os.path.isfile(path):
173             c = zlib.compressobj(compression_level,
174                                 zlib.DEFLATED,
175                                 -zlib.MAX_WBITS,
176                                 zlib.DEF_MEM_LEVEL,
177                                 strategy)
178             with open(path, 'rb') as fo:
179                 while True:
180                     buf = fo.read(BUFSIZE)
181                     l_orig += len(buf)
182                     if len(buf) == 0:
183                         l += len(c.flush())
184                         return l, l_orig
185                     buf = c.compress(buf)
186                     if buf is not None:
187                         l += len(buf)
188         return l, l_orig
189
190     l, l_orig = add(path)
191     print("total size: %d MiB compressed, %d MiB uncompressed" % (
192         (l / (1024 ** 2)),
193         (l_orig / (1024 ** 2))))
194
195 def print_profile(pr, sort):
196     s = io.StringIO()
197     if not sort:
198         sort = 'cumulative'
199     ps = pstats.Stats(pr, stream=s).sort_stats(sort)
200     ps.print_stats(20)
201     print(s.getvalue())
202
203
204 if __name__ == '__main__':
205     main()