/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar
1707.2.2 by Robert Collins
Start on bench_add, an add benchtest.
1
# Copyright (C) 2006 by Canonical Ltd
2
#
3
# This program is free software; you can redistribute it and/or modify
4
# it under the terms of the GNU General Public License as published by
5
# the Free Software Foundation; either version 2 of the License, or
6
# (at your option) any later version.
7
#
8
# This program is distributed in the hope that it will be useful,
9
# but WITHOUT ANY WARRANTY; without even the implied warranty of
10
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
# GNU General Public License for more details.
12
#
13
# You should have received a copy of the GNU General Public License
14
# along with this program; if not, write to the Free Software
15
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16
17
18
"""Benchmark test suite for bzr."""
19
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
20
import os
21
import shutil
22
23
from bzrlib import (
24
    add,
25
    bzrdir,
26
    osutils,
27
    plugin,
28
    workingtree,
29
    )
1773.4.1 by Martin Pool
Add pyflakes makefile target; fix many warnings
30
from bzrlib.tests.TestUtil import TestLoader
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
31
from bzrlib.tests.blackbox import ExternalBase
32
1841.1.1 by John Arbash Meinel
Allow plugins to provide benchmarks just like they do tests
33
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
34
class Benchmark(ExternalBase):
35
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
36
    _cached_kernel_like_tree = None
37
    _cached_kernel_like_added_tree = None
38
39
    def make_kernel_like_tree(self, url=None, root='.',
40
                              hardlink_working=False):
1725.2.5 by Robert Collins
Bugfix create_branch_convenience at the root of a file system to not loop
41
        """Setup a temporary tree roughly like a kernel tree.
42
        
43
        :param url: Creat the kernel like tree as a lightweight checkout
44
        of a new branch created at url.
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
45
        :param hardlink_working: instead of creating a new copy of all files
46
            just hardlink the working tree. Tests must request this, because
47
            they must break links if they want to change the files
1725.2.5 by Robert Collins
Bugfix create_branch_convenience at the root of a file system to not loop
48
        """
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
49
        if url is not None:
50
            b = bzrdir.BzrDir.create_branch_convenience(url)
51
            d = bzrdir.BzrDir.create(root)
52
            bzrlib.branch.BranchReferenceFormat().initialize(d, b)
53
            tree = d.create_workingtree()
54
        else:
55
            tree = bzrdir.BzrDir.create_standalone_workingtree(root)
56
57
        self._link_or_copy_kernel_files(root=root, do_link=hardlink_working)
58
        return tree
59
60
    def _make_kernel_files(self, root='.'):
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
61
        # a kernel tree has ~10000 and 500 directory, with most files around 
62
        # 3-4 levels deep. 
63
        # we simulate this by three levels of dirs named 0-7, givin 512 dirs,
64
        # and 20 files each.
65
        files = []
66
        for outer in range(8):
67
            files.append("%s/" % outer)
68
            for middle in range(8):
69
                files.append("%s/%s/" % (outer, middle))
70
                for inner in range(8):
71
                    prefix = "%s/%s/%s/" % (outer, middle, inner)
72
                    files.append(prefix)
73
                    files.extend([prefix + str(foo) for foo in range(20)])
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
74
        cwd = osutils.getcwd()
75
        os.chdir(root)
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
76
        self.build_tree(files)
1908.2.2 by John Arbash Meinel
Allow caching basic kernel-like trees
77
        os.chdir(cwd)
78
79
    def _link_or_copy_kernel_files(self, root, do_link=True):
80
        """Hardlink the kernel files from the cached location.
81
82
        If the platform doesn't correctly support hardlinking files, it
83
        reverts to just creating new ones.
84
        """
85
86
        if not osutils.hardlinks_good() or not do_link:
87
            # Turns out that 'shutil.copytree()' is no faster than
88
            # just creating them. Probably the python overhead.
89
            # Plain _make_kernel_files takes 5s
90
            # cp -a takes 3s
91
            # using hardlinks takes < 1s.
92
            self._make_kernel_files(root=root)
93
            return
94
95
        if Benchmark._cached_kernel_like_tree is None:
96
            cache_dir = osutils.pathjoin(self.TEST_ROOT,
97
                                         'cached_kernel_like_tree')
98
            os.mkdir(cache_dir)
99
            self._make_kernel_files(root=cache_dir)
100
            Benchmark._cached_kernel_like_tree = cache_dir
101
102
        # Hardlinking the target directory is *much* faster (7s => <1s).
103
        osutils.copy_tree(Benchmark._cached_kernel_like_tree, root,
104
                          handlers={'file':os.link})
105
106
    def make_kernel_like_added_tree(self, root='.',
107
                                    hardlink_working=True):
108
        """Make a kernel like tree, with all files added
109
110
        :param root: Where to create the files
111
        :param hardlink_working: Instead of copying all of the working tree
112
            files, just hardlink them to the cached files. Tests can unlink
113
            files that they will change.
114
        """
115
        if Benchmark._cached_kernel_like_added_tree is None:
116
            cache_dir = osutils.pathjoin(self.TEST_ROOT,
117
                                         'cached_kernel_like_added_tree')
118
            # Get a basic tree with working files
119
            tree = self.make_kernel_like_tree(root=cache_dir,
120
                                              hardlink_working=True)
121
            # Add everything to it
122
            add.smart_add_tree(tree, [cache_dir], recurse=True, save=True)
123
            Benchmark._cached_kernel_like_added_tree = cache_dir
124
125
        # Now we have a cached tree, just copy it
126
        handlers = {} # Copy all files
127
        if osutils.hardlinks_good() and hardlink_working:
128
            # Hardlink only working files (not files underneath .bzr)
129
            def file_handler(source, dest):
130
                if '.bzr/' in source:
131
                    shutil.copy2(source, dest)
132
                else:
133
                    os.link(source, dest)
134
            handlers = {'file':file_handler}
135
136
        osutils.copy_tree(Benchmark._cached_kernel_like_added_tree, root,
137
                          handlers=handlers)
138
        return workingtree.WorkingTree.open(root)
1707.2.2 by Robert Collins
Start on bench_add, an add benchtest.
139
1756.1.2 by Aaron Bentley
Show logs using get_revisions
140
    def make_many_commit_tree(self, directory_name='.'):
1756.2.21 by Aaron Bentley
Clean up merge log benchmark
141
        """Create a tree with many commits.
1756.1.2 by Aaron Bentley
Show logs using get_revisions
142
        
143
        No files change are included.
144
        """
1711.2.82 by John Arbash Meinel
minor fix from Jan Balster to get --benchmark to work again
145
        tree = bzrdir.BzrDir.create_standalone_workingtree(directory_name)
1756.1.2 by Aaron Bentley
Show logs using get_revisions
146
        tree.lock_write()
147
        tree.branch.lock_write()
148
        tree.branch.repository.lock_write()
149
        try:
150
            for i in xrange(1000):
151
                tree.commit('no-changes commit %d' % i)
152
        finally:
153
            try:
154
                try:
155
                    tree.branch.repository.unlock()
156
                finally:
157
                    tree.branch.unlock()
158
            finally:
159
                tree.unlock()
160
        return tree
161
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
162
    def make_heavily_merged_tree(self, directory_name='.'):
1756.2.21 by Aaron Bentley
Clean up merge log benchmark
163
        """Create a tree in which almost every commit is a merge.
164
       
165
        No files change are included.  This produces two trees, 
166
        one of which is returned.  Except for the first commit, every
167
        commit in its revision-history is a merge another commit in the other
168
        tree.
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
169
        """
1711.2.82 by John Arbash Meinel
minor fix from Jan Balster to get --benchmark to work again
170
        tree = bzrdir.BzrDir.create_standalone_workingtree(directory_name)
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
171
        tree.lock_write()
172
        try:
1756.2.21 by Aaron Bentley
Clean up merge log benchmark
173
            tree2 = tree.bzrdir.sprout('tree2').open_workingtree()
174
            tree2.lock_write()
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
175
            try:
1756.2.21 by Aaron Bentley
Clean up merge log benchmark
176
                for i in xrange(250):
177
                    revision_id = tree.commit('no-changes commit %d-a' % i)
178
                    tree2.branch.fetch(tree.branch, revision_id)
179
                    tree2.set_pending_merges([revision_id])
180
                    revision_id = tree2.commit('no-changes commit %d-b' % i)
181
                    tree.branch.fetch(tree2.branch, revision_id)
182
                    tree.set_pending_merges([revision_id])
183
                tree.set_pending_merges([])
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
184
            finally:
185
                tree.unlock()
1756.2.21 by Aaron Bentley
Clean up merge log benchmark
186
        finally:
187
            tree2.unlock()
1756.2.19 by Aaron Bentley
Add benchmarks for merged trees
188
        return tree
189
1707.2.2 by Robert Collins
Start on bench_add, an add benchtest.
190
191
def test_suite():
192
    """Build and return a TestSuite which contains benchmark tests only."""
193
    testmod_names = [ \
194
                   'bzrlib.benchmarks.bench_add',
1755.2.1 by Robert Collins
Add a benchmark for make_kernel_like_tree.
195
                   'bzrlib.benchmarks.bench_bench',
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
196
                   'bzrlib.benchmarks.bench_checkout',
1714.1.5 by Robert Collins
Add commit benchmark.
197
                   'bzrlib.benchmarks.bench_commit',
1757.2.10 by Robert Collins
Give all inventory entries __slots__ that are useful with the current codebase.
198
                   'bzrlib.benchmarks.bench_inventory',
1756.1.7 by Aaron Bentley
Merge bzr.dev
199
                   'bzrlib.benchmarks.bench_log',
1756.1.2 by Aaron Bentley
Show logs using get_revisions
200
                   'bzrlib.benchmarks.bench_osutils',
1752.1.2 by Aaron Bentley
Benchmark the rocks command
201
                   'bzrlib.benchmarks.bench_rocks',
1714.1.4 by Robert Collins
Add new benchmarks for status and commit.
202
                   'bzrlib.benchmarks.bench_status',
1534.10.33 by Aaron Bentley
Add canonicalize_path benchmark
203
                   'bzrlib.benchmarks.bench_transform',
1732.1.11 by John Arbash Meinel
Trying multiple things to get WorkingTree.list_files time down
204
                   'bzrlib.benchmarks.bench_workingtree',
1707.2.2 by Robert Collins
Start on bench_add, an add benchtest.
205
                   ]
1841.1.1 by John Arbash Meinel
Allow plugins to provide benchmarks just like they do tests
206
    suite = TestLoader().loadTestsFromModuleNames(testmod_names) 
207
208
    # Load any benchmarks from plugins
1711.2.78 by John Arbash Meinel
Cleanup the imports in bzrlib.benchmark
209
    for name, module in plugin.all_plugins().items():
210
        if getattr(module, 'bench_suite', None) is not None:
211
            suite.addTest(module.bench_suite())
1841.1.1 by John Arbash Meinel
Allow plugins to provide benchmarks just like they do tests
212
213
    return suite