diff --git a/gramps2/ChangeLog b/gramps2/ChangeLog index 9e96561f5..173412d37 100644 --- a/gramps2/ChangeLog +++ b/gramps2/ChangeLog @@ -1,3 +1,7 @@ +2005-12-16 Richard Taylor + * test/GrampsDbBase_Test.py: added a crude performance test. + * test/RunAllTests.py: fixed log level setting. + 2005-12-16 Richard Taylor * src/GrampsBSDDB.py: reindex_reference_map added to rebuild the reference_map when upgrading database diff --git a/gramps2/test/GrampsDbBase_Test.py b/gramps2/test/GrampsDbBase_Test.py index ae82a83d2..5826bac50 100644 --- a/gramps2/test/GrampsDbBase_Test.py +++ b/gramps2/test/GrampsDbBase_Test.py @@ -3,6 +3,7 @@ import logging import os import tempfile import shutil +import time import sys sys.path.append('../src') @@ -26,8 +27,44 @@ class ReferenceMapTest (unittest.TestCase): def tearDown(self): shutil.rmtree(self._tmpdir) + def _populate_database(self, + num_sources = 1, + num_persons = 0, + num_families = 0, + num_events = 0, + num_places = 0, + num_media_objects = 0, + num_links = 1): - def _add_person_and_source(self): + # start with sources + sources = [] + for i in xrange(0,num_sources): + sources.append(self._add_source()) + + # now for each of the other tables. Give each entry a link + # to num_link sources, sources are chosen on a round robin + # basis + + for num, add_func in ((num_persons, self._add_person_with_sources), + (num_families, self._add_family_with_sources), + (num_events, self._add_event_with_sources), + (num_places, self._add_place_with_sources), + (num_media_objects, self._add_media_object_with_sources)): + + source_idx = 1 + for person_idx in xrange(0,num): + + # Get the list of sources to link + lnk_sources = set() + for i in xrange(0,num_links): + lnk_sources.add(sources[source_idx-1]) + source_idx = (source_idx+1) % len(sources) + + add_func(lnk_sources) + + return + + def _add_source(self): # Add a Source tran = self._db.transaction_begin() @@ -36,27 +73,70 @@ class ReferenceMapTest (unittest.TestCase): self._db.commit_source(source,tran) self._db.transaction_commit(tran, "Add Source") - src_ref = RelLib.SourceRef() - src_ref.set_base_handle(source.get_handle()) + return source + + + def _add_object_with_source(self,sources,object_class,add_method,commit_method): + + object = object_class() + + for source in sources: + src_ref = RelLib.SourceRef() + src_ref.set_base_handle(source.get_handle()) + object.add_source_reference(src_ref) - # Add Person with reference to the Source tran = self._db.transaction_begin() - person = RelLib.Person() + add_method(object,tran) + commit_method(object,tran) + self._db.transaction_commit(tran, "Add Object") - person.add_source_reference(src_ref) - self._db.add_person(person,tran) - self._db.commit_person(person,tran) - self._db.transaction_commit(tran, "Add Person") + return object - return (person,source) + def _add_person_with_sources(self,sources): + + return self._add_object_with_source(sources, + RelLib.Person, + self._db.add_person, + self._db.commit_person) + + def _add_family_with_sources(self,sources): + + return self._add_object_with_source(sources, + RelLib.Family, + self._db.add_family, + self._db.commit_family) + + def _add_event_with_sources(self,sources): + + return self._add_object_with_source(sources, + RelLib.Event, + self._db.add_event, + self._db.commit_event) + + def _add_place_with_sources(self,sources): + + return self._add_object_with_source(sources, + RelLib.Place, + self._db.add_place, + self._db.commit_place) + + def _add_media_object_with_sources(self,sources): + + return self._add_object_with_source(sources, + RelLib.MediaObject, + self._db.add_object, + self._db.commit_media_object) + + def test_simple_lookup(self): """insert a record and a reference and check that a lookup for the reference returns the original record.""" - person,source = self._add_person_and_source() + source = self._add_source() + person = self._add_person_with_sources([source]) references = [ ref for ref in self._db.find_backlink_handles(source.get_handle()) ] @@ -67,7 +147,8 @@ class ReferenceMapTest (unittest.TestCase): """check that deleting a primary will remove the backreferences from the reference_map""" - person,source = self._add_person_and_source() + source = self._add_source() + person = self._add_person_with_sources([source]) assert self._db.get_person_from_handle(person.get_handle()) is not None @@ -91,7 +172,8 @@ class ReferenceMapTest (unittest.TestCase): self._db._update_reference_map = lambda x,y: 1 # Insert a person/source pair. - person,source = self._add_person_and_source() + source = self._add_source() + person = self._add_person_with_sources([source]) # Check that the reference map does not contain the reference. references = [ ref for ref in self._db.find_backlink_handles(source.get_handle()) ] @@ -108,8 +190,53 @@ class ReferenceMapTest (unittest.TestCase): assert len(references) == 1, "len(references) == %s " % str(len(references)) - + def _timeit(func,*args,**kwargs): + start = time.time() + + func(*args,**kwargs) + + end = time.time() + return end - start + + def test_performance(self): + + self._populate_database(num_sources = 100, + num_persons = 10, + num_families = 10, + num_events = 10, + num_places = 10, + num_media_objects = 10, + num_links = 10) + + + # time searching for source backrefs with and without reference_map + cur = self._db.get_source_cursor() + handle,data = cur.first() + cur.close() + + start = time.time() + references = [ ref for ref in self._db.find_backlink_handles(handle) ] + end = time.time() + + with_reference_map = end - start + + remember = self._db.__class__.find_backlink_handles + + self._db.__class__.find_backlink_handles = self._db.__class__.__base__.find_backlink_handles + + start = time.time() + references = [ ref for ref in self._db.find_backlink_handles(handle) ] + end = time.time() + + without_reference_map = end - start + + self._db.__class__.find_backlink_handles = remember + + logger.info("with refs %s\n", str(with_reference_map)) + logger.info("without refs %s\n", str(without_reference_map)) + + assert with_reference_map < (without_reference_map / 10), "Reference_map should an order of magnitude faster." def testSuite(): return unittest.makeSuite(ReferenceMapTest,'test') diff --git a/gramps2/test/RunAllTests.py b/gramps2/test/RunAllTests.py index ffd0c3ab7..3ae70a94e 100644 --- a/gramps2/test/RunAllTests.py +++ b/gramps2/test/RunAllTests.py @@ -43,12 +43,19 @@ if __name__ == '__main__': if options.verbose_level == 1: logger.setLevel(logging.INFO) - elif options.verbose_level >= 2: + console.setLevel(logging.INFO) + elif options.verbose_level == 2: logger.setLevel(logging.DEBUG) - os.environ['GRAMPS_SIGNAL'] = "1" - elif options.verbose_level >= 3: + console.setLevel(logging.DEBUG) + elif options.verbose_level == 3: logger.setLevel(logging.NOTSET) + console.setLevel(logging.NOTSET) + elif options.verbose_level >= 4: + logger.setLevel(logging.NOTSET) + console.setLevel(logging.NOTSET) + os.environ['GRAMPS_SIGNAL'] = "1" else: logger.setLevel(logging.ERROR) + console.setLevel(logging.ERROR) unittest.TextTestRunner(verbosity=options.verbose_level).run(allTheTests())