/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/benchmarks/__init__.py

  • Committer: John Arbash Meinel
  • Date: 2006-08-16 18:38:57 UTC
  • mfrom: (1934 +trunk)
  • mto: This revision was merged to the branch mainline in revision 1937.
  • Revision ID: john@arbash-meinel.com-20060816183857-7307edffa7098bd2
[merge] bzr.dev 1934

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
# along with this program; if not, write to the Free Software
15
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
16
 
17
 
 
18
17
"""Benchmark test suite for bzr."""
19
18
 
20
 
import os
21
 
import shutil
22
 
 
23
19
from bzrlib import (
24
 
    add,
25
 
    bzrdir,
26
 
    osutils,
27
20
    plugin,
28
 
    workingtree,
29
21
    )
30
22
from bzrlib.tests.TestUtil import TestLoader
31
23
from bzrlib.tests.blackbox import ExternalBase
33
25
 
34
26
class Benchmark(ExternalBase):
35
27
 
36
 
    CACHE_ROOT = None
37
 
 
38
 
    def get_cache_dir(self, extra):
39
 
        """Get the directory to use for caching the given object."""
40
 
 
41
 
        if Benchmark.CACHE_ROOT is None:
42
 
            Benchmark.CACHE_ROOT = osutils.pathjoin(self.TEST_ROOT, 'CACHE')
43
 
        if not os.path.isdir(Benchmark.CACHE_ROOT):
44
 
            os.mkdir(Benchmark.CACHE_ROOT)
45
 
        cache_dir = osutils.pathjoin(self.CACHE_ROOT, extra)
46
 
        return cache_dir, os.path.exists(cache_dir)
47
 
 
48
28
    def make_kernel_like_tree(self, url=None, root='.',
49
 
                              hardlink_working=False):
 
29
                              link_working=False):
50
30
        """Setup a temporary tree roughly like a kernel tree.
51
31
        
52
32
        :param url: Creat the kernel like tree as a lightweight checkout
53
33
        of a new branch created at url.
54
 
        :param hardlink_working: instead of creating a new copy of all files
 
34
        :param link_working: instead of creating a new copy of all files
55
35
            just hardlink the working tree. Tests must request this, because
56
36
            they must break links if they want to change the files
57
37
        """
58
 
        if url is not None:
59
 
            b = bzrdir.BzrDir.create_branch_convenience(url)
60
 
            d = bzrdir.BzrDir.create(root)
61
 
            bzrlib.branch.BranchReferenceFormat().initialize(d, b)
62
 
            tree = d.create_workingtree()
63
 
        else:
64
 
            tree = bzrdir.BzrDir.create_standalone_workingtree(root)
65
 
 
66
 
        self._link_or_copy_kernel_files(root=root, do_link=hardlink_working)
67
 
        return tree
68
 
 
69
 
    def _make_kernel_files(self, root='.'):
70
 
        # a kernel tree has ~10000 and 500 directory, with most files around 
71
 
        # 3-4 levels deep. 
72
 
        # we simulate this by three levels of dirs named 0-7, givin 512 dirs,
73
 
        # and 20 files each.
74
 
        files = []
75
 
        for outer in range(8):
76
 
            files.append("%s/" % outer)
77
 
            for middle in range(8):
78
 
                files.append("%s/%s/" % (outer, middle))
79
 
                for inner in range(8):
80
 
                    prefix = "%s/%s/%s/" % (outer, middle, inner)
81
 
                    files.append(prefix)
82
 
                    files.extend([prefix + str(foo) for foo in range(20)])
83
 
        cwd = osutils.getcwd()
84
 
        os.chdir(root)
85
 
        self.build_tree(files)
86
 
        os.chdir(cwd)
87
 
 
88
 
    def _cache_kernel_like_tree(self):
89
 
        """Create the kernel_like_tree cache dir if it doesn't exist"""
90
 
        cache_dir, is_cached = self.get_cache_dir('kernel_like_tree')
91
 
        if is_cached:
92
 
            return cache_dir
93
 
        os.mkdir(cache_dir)
94
 
        self._make_kernel_files(root=cache_dir)
95
 
        self._protect_files(cache_dir)
96
 
        return cache_dir
97
 
 
98
 
    def _link_or_copy_kernel_files(self, root, do_link=True):
99
 
        """Hardlink the kernel files from the cached location.
100
 
 
101
 
        If the platform doesn't correctly support hardlinking files, it
102
 
        reverts to just creating new ones.
103
 
        """
104
 
 
105
 
        if not osutils.hardlinks_good() or not do_link:
106
 
            # Turns out that 'shutil.copytree()' is no faster than
107
 
            # just creating them. Probably the python overhead.
108
 
            # Plain _make_kernel_files takes 5s
109
 
            # cp -a takes 3s
110
 
            # using hardlinks takes < 1s.
111
 
            self._make_kernel_files(root=root)
112
 
            return
113
 
 
114
 
        cache_dir = self._cache_kernel_like_tree()
115
 
 
116
 
        # Hardlinking the target directory is *much* faster (7s => <1s).
117
 
        osutils.copy_tree(cache_dir, root,
118
 
                          handlers={'file':os.link})
119
 
 
120
 
    def _clone_tree(self, source, dest, link_bzr=False, link_working=True,
121
 
                    hot_cache=True):
122
 
        """Copy the contents from a given location to another location.
123
 
        Optionally hardlink certain pieces of the tree.
124
 
 
125
 
        :param source: The directory to copy
126
 
        :param dest: The destination
127
 
        :param link_bzr: Should the .bzr/ files be hardlinked?
128
 
        :param link_working: Should the working tree be hardlinked?
129
 
        :param hot_cache: Update the hash-cache when you are done
130
 
        """
131
 
        # We use shutil.copyfile so that we don't copy permissions
132
 
        # because most of our source trees are marked readonly to
133
 
        # prevent modifying in the case of hardlinks
134
 
        handlers = {'file':shutil.copyfile}
135
 
        if osutils.hardlinks_good():
136
 
            if link_working:
137
 
                if link_bzr:
138
 
                    handlers = {'file':os.link}
139
 
                else:
140
 
                    # Don't hardlink files inside bzr
141
 
                    def file_handler(source, dest):
142
 
                        if '.bzr/' in source:
143
 
                            shutil.copyfile(source, dest)
144
 
                        else:
145
 
                            os.link(source, dest)
146
 
                    handlers = {'file':file_handler}
147
 
            elif link_bzr:
148
 
                # Only link files inside .bzr/
149
 
                def file_handler(source, dest):
150
 
                    if '.bzr/' in source:
151
 
                        os.link(source, dest)
152
 
                    else:
153
 
                        shutil.copyfile(source, dest)
154
 
                handlers = {'file':file_handler}
155
 
        osutils.copy_tree(source, dest, handlers=handlers)
156
 
        tree = workingtree.WorkingTree.open(dest)
157
 
        if hot_cache:
158
 
            tree.lock_write()
159
 
            try:
160
 
                # tree._hashcache.scan() just checks and removes
161
 
                # entries that are out of date
162
 
                # we need to actually store new ones
163
 
                for path, ie in tree.inventory.iter_entries_by_dir():
164
 
                    tree.get_file_sha1(ie.file_id, path)
165
 
            finally:
166
 
                tree.unlock()
167
 
        # If we didn't iterate the tree, the hash cache is technically
168
 
        # invalid, and it would be better to remove it, but there is
169
 
        # no public api for that.
170
 
        return tree
171
 
 
172
 
    def _protect_files(self, root):
173
 
        """Chmod all files underneath 'root' to prevent writing
174
 
 
175
 
        :param root: The base directory to modify
176
 
        """
177
 
        for dirinfo, entries in osutils.walkdirs(root):
178
 
            for relpath, name, kind, st, abspath in entries:
179
 
                if kind == 'file':
180
 
                    os.chmod(abspath, 0440)
181
 
 
182
 
    def _cache_kernel_like_added_tree(self):
183
 
        cache_dir, is_cached = self.get_cache_dir('kernel_like_added_tree')
184
 
        if is_cached:
185
 
            return cache_dir
186
 
 
187
 
        # Get a basic tree with working files
188
 
        tree = self.make_kernel_like_tree(root=cache_dir,
189
 
                                          hardlink_working=True)
190
 
        # Add everything to it
191
 
        tree.lock_write()
192
 
        try:
193
 
            add.smart_add_tree(tree, [cache_dir], recurse=True, save=True)
194
 
            self._protect_files(cache_dir+'/.bzr')
195
 
        finally:
196
 
            tree.unlock()
197
 
 
198
 
        return cache_dir
 
38
        from bzrlib.benchmarks.tree_creator.kernel_like import (
 
39
            KernelLikeTreeCreator,
 
40
            )
 
41
        creator = KernelLikeTreeCreator(self, link_working=link_working,
 
42
                                        url=url)
 
43
        return creator.create(root=root)
199
44
 
200
45
    def make_kernel_like_added_tree(self, root='.',
201
 
                                    hardlink_working=True,
 
46
                                    link_working=True,
202
47
                                    hot_cache=True):
203
48
        """Make a kernel like tree, with all files added
204
49
 
205
50
        :param root: Where to create the files
206
 
        :param hardlink_working: Instead of copying all of the working tree
 
51
        :param link_working: Instead of copying all of the working tree
207
52
            files, just hardlink them to the cached files. Tests can unlink
208
53
            files that they will change.
209
54
        :param hot_cache: Run through the newly created tree and make sure
210
55
            the stat-cache is correct. The old way of creating a freshly
211
56
            added tree always had a hot cache.
212
57
        """
213
 
        # There isn't much underneath .bzr, so we don't support hardlinking
214
 
        # it. Testing showed there wasn't much gain, and there is potentially
215
 
        # a problem if someone modifies something underneath us.
216
 
        cache_dir = self._cache_kernel_like_added_tree()
217
 
 
218
 
        return self._clone_tree(cache_dir, root,
219
 
                                link_working=hardlink_working,
220
 
                                hot_cache=hot_cache)
221
 
 
222
 
    def _cache_kernel_like_committed_tree(self):
223
 
        cache_dir, is_cached = self.get_cache_dir('kernel_like_committed_tree')
224
 
        if is_cached:
225
 
            return cache_dir
226
 
 
227
 
        # Get a basic tree with working files
228
 
        tree = self.make_kernel_like_added_tree(root=cache_dir,
229
 
                                                hardlink_working=True,
230
 
                                                hot_cache=False)
231
 
        tree.commit('first post', rev_id='r1')
232
 
 
233
 
        self._protect_files(cache_dir+'/.bzr')
234
 
        return cache_dir
 
58
        from bzrlib.benchmarks.tree_creator.kernel_like import (
 
59
            KernelLikeAddedTreeCreator,
 
60
            )
 
61
        creator = KernelLikeAddedTreeCreator(self, link_working=link_working,
 
62
                                             hot_cache=hot_cache)
 
63
        return creator.create(root=root)
235
64
 
236
65
    def make_kernel_like_committed_tree(self, root='.',
237
 
                                    hardlink_working=True,
238
 
                                    hardlink_bzr=False,
 
66
                                    link_working=True,
 
67
                                    link_bzr=False,
239
68
                                    hot_cache=True):
240
69
        """Make a kernel like tree, with all files added and committed
241
70
 
242
71
        :param root: Where to create the files
243
 
        :param hardlink_working: Instead of copying all of the working tree
 
72
        :param link_working: Instead of copying all of the working tree
244
73
            files, just hardlink them to the cached files. Tests can unlink
245
74
            files that they will change.
246
 
        :param hardlink_bzr: Hardlink the .bzr directory. For readonly 
 
75
        :param link_bzr: Hardlink the .bzr directory. For readonly 
247
76
            operations this is safe, and shaves off a lot of setup time
248
77
        """
249
 
        cache_dir = self._cache_kernel_like_committed_tree()
250
 
 
251
 
        # Now we have a cached tree, just copy it
252
 
        return self._clone_tree(cache_dir, root,
253
 
                                link_bzr=hardlink_bzr,
254
 
                                link_working=hardlink_working,
255
 
                                hot_cache=hot_cache)
256
 
 
257
 
    def _cache_many_commit_tree(self):
258
 
        cache_dir, is_cached = self.get_cache_dir('many_commit_tree')
259
 
        if is_cached:
260
 
            return cache_dir
261
 
 
262
 
        tree = bzrdir.BzrDir.create_standalone_workingtree(cache_dir)
263
 
        tree.lock_write()
264
 
        tree.branch.lock_write()
265
 
        tree.branch.repository.lock_write()
266
 
        try:
267
 
            for i in xrange(1000):
268
 
                tree.commit('no-changes commit %d' % i)
269
 
        finally:
270
 
            try:
271
 
                try:
272
 
                    tree.branch.repository.unlock()
273
 
                finally:
274
 
                    tree.branch.unlock()
275
 
            finally:
276
 
                tree.unlock()
277
 
 
278
 
        return cache_dir
 
78
        from bzrlib.benchmarks.tree_creator.kernel_like import (
 
79
            KernelLikeCommittedTreeCreator,
 
80
            )
 
81
        creator = KernelLikeCommittedTreeCreator(self,
 
82
                                                 link_working=link_working,
 
83
                                                 link_bzr=link_bzr,
 
84
                                                 hot_cache=hot_cache)
 
85
        return creator.create(root=root)
279
86
 
280
87
    def make_many_commit_tree(self, directory_name='.',
281
88
                              hardlink=False):
284
91
        No file changes are included. Not hardlinking the working tree, 
285
92
        because there are no working tree files.
286
93
        """
287
 
        cache_dir = self._cache_many_commit_tree()
288
 
        return self._clone_tree(cache_dir, directory_name,
289
 
                                link_bzr=hardlink,
290
 
                                hot_cache=True)
291
 
 
292
 
    def _cache_heavily_merged_tree(self):
293
 
        cache_dir, is_cached = self.get_cache_dir('heavily_merged_tree')
294
 
        if is_cached:
295
 
            return cache_dir
296
 
 
297
 
        os.mkdir(cache_dir)
298
 
        tree = bzrdir.BzrDir.create_standalone_workingtree(
299
 
                cache_dir + '/tree1')
300
 
        tree.lock_write()
301
 
        try:
302
 
            tree2 = tree.bzrdir.sprout(cache_dir + '/tree2').open_workingtree()
303
 
            tree2.lock_write()
304
 
            try:
305
 
                for i in xrange(250):
306
 
                    revision_id = tree.commit('no-changes commit %d-a' % i)
307
 
                    tree2.branch.fetch(tree.branch, revision_id)
308
 
                    tree2.set_pending_merges([revision_id])
309
 
                    revision_id = tree2.commit('no-changes commit %d-b' % i)
310
 
                    tree.branch.fetch(tree2.branch, revision_id)
311
 
                    tree.set_pending_merges([revision_id])
312
 
                tree.set_pending_merges([])
313
 
            finally:
314
 
                tree2.unlock()
315
 
        finally:
316
 
            tree.unlock()
317
 
        return cache_dir
 
94
        from bzrlib.benchmarks.tree_creator.simple_many_commit import (
 
95
            SimpleManyCommitTreeCreator,
 
96
            )
 
97
        creator = SimpleManyCommitTreeCreator(self, link_bzr=hardlink)
 
98
        return creator.create(root=directory_name)
318
99
 
319
100
    def make_heavily_merged_tree(self, directory_name='.',
320
101
                                 hardlink=False):
326
107
        tree.  Not hardlinking the working tree, because there are no working 
327
108
        tree files.
328
109
        """
329
 
        cache_dir = self._cache_heavily_merged_tree()
330
 
        tree_dir = cache_dir + '/tree1'
331
 
        return self._clone_tree(tree_dir, directory_name,
332
 
                                link_bzr=hardlink,
333
 
                                hot_cache=True)
 
110
        from bzrlib.benchmarks.tree_creator.heavily_merged import (
 
111
            HeavilyMergedTreeCreator,
 
112
            )
 
113
        creator = HeavilyMergedTreeCreator(self, link_bzr=hardlink)
 
114
        return creator.create(root=directory_name)
334
115
 
335
116
 
336
117
def test_suite():
338
119
    testmod_names = [ \
339
120
                   'bzrlib.benchmarks.bench_add',
340
121
                   'bzrlib.benchmarks.bench_bench',
 
122
                   'bzrlib.benchmarks.bench_cache_utf8',
341
123
                   'bzrlib.benchmarks.bench_checkout',
342
124
                   'bzrlib.benchmarks.bench_commit',
343
125
                   'bzrlib.benchmarks.bench_inventory',