Mercurial > hgsubversion
comparison tests/test_util.py @ 1457:019c3e194fba
tests: optimise creating repositories and loading dumps
Previously, we'd use svnadmin for creating repositories and loading
dumps. That tends to be a bit slow, as it forks a new process and
loads the Subversion libraries into it. Instead, we extend our
existing Subversion wrappers and load the dumps using the API.
This is a noticable speedup. The only downside is that we rely on
Subversion and Subvertpy to correctly close all file descriptors; an
assumption which hasn't always held in the past.
I ran some benchmarks on my relatively slow Mac with $TMPDIR on a
ramdisk, and they showed a significant change:
I compared ten runs of each with Subvertpy:
min: -18.8% (299.1s -> 243.0s)
median: -20.0% (307.1s -> 245.6s)
...and three runs of each with SWIG:
min: -22.8% (368.7s -> 284.7s)
median: -25.7% (384.4s -> 285.5s)
(Since the timing measures wall clock time, the minimum time is likely
to be the most accurate and useful measurement.)
| author | Dan Villiom Podlaski Christiansen <danchr@gmail.com> |
|---|---|
| date | Tue, 07 Jun 2016 09:15:53 +0200 |
| parents | 89997a5fc181 |
| children | dcf9eff9b5b7 |
comparison
equal
deleted
inserted
replaced
| 1456:77da55e0baa4 | 1457:019c3e194fba |
|---|---|
| 45 try: | 45 try: |
| 46 from nose import SkipTest | 46 from nose import SkipTest |
| 47 except ImportError: | 47 except ImportError: |
| 48 SkipTest = None | 48 SkipTest = None |
| 49 | 49 |
| 50 from hgsubversion import svnwrap | |
| 50 from hgsubversion import util | 51 from hgsubversion import util |
| 51 from hgsubversion import svnwrap | 52 from hgsubversion import svnwrap |
| 52 | 53 |
| 53 # Documentation for Subprocess.Popen() says: | 54 # Documentation for Subprocess.Popen() says: |
| 54 # "Note that on Windows, you cannot set close_fds to true and | 55 # "Note that on Windows, you cannot set close_fds to true and |
| 532 '''Loads an svnadmin dump into a fresh repo. Return the svn repo | 533 '''Loads an svnadmin dump into a fresh repo. Return the svn repo |
| 533 path. | 534 path. |
| 534 ''' | 535 ''' |
| 535 path = self._makerepopath() | 536 path = self._makerepopath() |
| 536 assert not os.path.exists(path) | 537 assert not os.path.exists(path) |
| 537 subprocess.call(['svnadmin', 'create', path,], | 538 with open(os.path.join(FIXTURES, fixture_name)) as inp: |
| 538 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | 539 svnwrap.create_and_load(path, inp) |
| 539 inp = open(os.path.join(FIXTURES, fixture_name)) | |
| 540 proc = subprocess.Popen(['svnadmin', 'load', path,], stdin=inp, | |
| 541 stdout=subprocess.PIPE, stderr=subprocess.STDOUT) | |
| 542 proc.communicate() | |
| 543 return path | 540 return path |
| 544 | 541 |
| 545 def load_repo_tarball(self, fixture_name): | 542 def load_repo_tarball(self, fixture_name): |
| 546 '''Extracts a tarball of an svn repo and returns the svn repo path.''' | 543 '''Extracts a tarball of an svn repo and returns the svn repo path.''' |
| 547 path = self._makerepopath() | 544 path = self._makerepopath() |
| 594 r = dispatch(cmd) | 591 r = dispatch(cmd) |
| 595 assert not r, 'fetch of %s failed' % projectpath | 592 assert not r, 'fetch of %s failed' % projectpath |
| 596 | 593 |
| 597 return hg.repository(testui(), self.wc_path) | 594 return hg.repository(testui(), self.wc_path) |
| 598 | 595 |
| 599 def load_and_fetch(self, fixture_name, *args, **opts): | 596 def load(self, fixture_name): |
| 600 if fixture_name.endswith('.svndump'): | 597 if fixture_name.endswith('.svndump'): |
| 601 repo_path = self.load_svndump(fixture_name) | 598 repo_path = self.load_svndump(fixture_name) |
| 602 elif fixture_name.endswith('tar.gz'): | 599 elif fixture_name.endswith('tar.gz'): |
| 603 repo_path = self.load_repo_tarball(fixture_name) | 600 repo_path = self.load_repo_tarball(fixture_name) |
| 604 else: | 601 else: |
| 605 assert False, 'Unknown fixture type' | 602 assert False, 'Unknown fixture type' |
| 606 | 603 |
| 604 return repo_path | |
| 605 | |
| 606 def load_and_fetch(self, fixture_name, *args, **opts): | |
| 607 repo_path = self.load(fixture_name) | |
| 607 return self.fetch(repo_path, *args, **opts), repo_path | 608 return self.fetch(repo_path, *args, **opts), repo_path |
| 608 | 609 |
| 609 def _load_fixture_and_fetch(self, *args, **kwargs): | 610 def _load_fixture_and_fetch(self, *args, **kwargs): |
| 610 repo, repo_path = self.load_and_fetch(*args, **kwargs) | 611 repo, repo_path = self.load_and_fetch(*args, **kwargs) |
| 611 return repo | 612 return repo |
