]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
added ORM version of zoomark, python 2.5 only for starters
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 18 May 2008 16:19:21 +0000 (16:19 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 18 May 2008 16:19:21 +0000 (16:19 +0000)
test/profiling/alltests.py
test/profiling/zoomark_orm.py [new file with mode: 0644]

index 61e8a4a14cd98ee161af039bc41afcdd2377bda1..aa7dd434a8fef9d7d009eeca4753d7080980d05e 100644 (file)
@@ -7,6 +7,7 @@ def suite():
         'profiling.compiler',
         'profiling.pool',
         'profiling.zoomark',
+        'profiling.zoomark_orm',
         )
     alltests = unittest.TestSuite()
     for name in modules_to_test:
diff --git a/test/profiling/zoomark_orm.py b/test/profiling/zoomark_orm.py
new file mode 100644 (file)
index 0000000..3d69e6f
--- /dev/null
@@ -0,0 +1,321 @@
+"""Benchmark for SQLAlchemy.
+
+An adaptation of Robert Brewers' ZooMark speed tests.
+"""
+
+import datetime
+import sys
+import time
+import testenv; testenv.configure_for_tests()
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from testlib import *
+
+ITERATIONS = 1
+
+dbapi_session = engines.ReplayableSession()
+metadata = None
+
+class ZooMarkTest(TestBase):
+    """Runs the ZooMark and squawks if method counts vary from the norm.
+
+    Each test has an associated `call_range`, the total number of accepted
+    function calls made during the test.  The count can vary between Python
+    2.4 and 2.5.
+
+    Unlike a unit test, this is a ordered collection of steps.  Running
+    components individually will fail.
+
+    """
+
+    __only_on__ = 'postgres'
+    __skip_if__ = ((lambda: sys.version_info < (2, 5)), )  # TODO: get 2.4 support
+
+    def test_baseline_0_setup(self):
+        global metadata, session
+
+        creator = testing.db.pool._creator
+        recorder = lambda: dbapi_session.recorder(creator())
+        engine = engines.testing_engine(options={'creator':recorder})
+        metadata = MetaData(engine)
+        session = sessionmaker()()
+
+    def test_baseline_1_create_tables(self):
+        zoo = Table('Zoo', metadata,
+                    Column('ID', Integer, Sequence('zoo_id_seq'),
+                           primary_key=True, index=True),
+                    Column('Name', Unicode(255)),
+                    Column('Founded', Date),
+                    Column('Opens', Time),
+                    Column('LastEscape', DateTime),
+                    Column('Admission', Float),
+                    )
+
+        animal = Table('Animal', metadata,
+                       Column('ID', Integer, Sequence('animal_id_seq'),
+                              primary_key=True),
+                       Column('ZooID', Integer, ForeignKey('Zoo.ID'),
+                              index=True),
+                       Column('Name', Unicode(100)),
+                       Column('Species', Unicode(100)),
+                       Column('Legs', Integer, default=4),
+                       Column('LastEscape', DateTime),
+                       Column('Lifespan', Float(4)),
+                       Column('MotherID', Integer, ForeignKey('Animal.ID')),
+                       Column('PreferredFoodID', Integer),
+                       Column('AlternateFoodID', Integer),
+                       )
+        metadata.create_all()
+        
+        global Zoo, Animal
+        class Zoo(object):
+            def __init__(self, **kwargs):
+                for k, v in kwargs.iteritems():
+                    setattr(self, k, v)
+        class Animal(object):
+            def __init__(self, **kwargs):
+                for k, v in kwargs.iteritems():
+                    setattr(self, k, v)
+        mapper(Zoo, zoo)
+        mapper(Animal, animal)
+        
+    def test_baseline_1a_populate(self):
+        wap = Zoo(Name=u'Wild Animal Park',
+                           Founded=datetime.date(2000, 1, 1),
+                           # 59 can give rounding errors with divmod, which
+                           # AdapterFromADO needs to correct.
+                           Opens=datetime.time(8, 15, 59),
+                           LastEscape=datetime.datetime(2004, 7, 29, 5, 6, 7),
+                           Admission=4.95,
+                           )
+        session.save(wap)
+        sdz = Zoo(Name =u'San Diego Zoo',
+                           # This early date should play havoc with a number
+                           # of implementations.
+                           Founded = datetime.date(1835, 9, 13),
+                           Opens = datetime.time(9, 0, 0),
+                           Admission = 0,
+                           )
+        session.save(sdz)
+        
+        bio = Zoo(
+                  Name = u'Montr\xe9al Biod\xf4me',
+                  Founded = datetime.date(1992, 6, 19),
+                  Opens = datetime.time(9, 0, 0),
+                  Admission = 11.75,
+                  )
+        session.save(bio)
+        
+        seaworld = Zoo(
+                Name =u'Sea_World', Admission = 60)
+        session.save(seaworld)
+        
+        # Let's add a crazy futuristic Zoo to test large date values.
+        lp = Zoo(Name =u'Luna Park',
+                                  Founded = datetime.date(2072, 7, 17),
+                                  Opens = datetime.time(0, 0, 0),
+                                  Admission = 134.95,
+                                  )
+        session.save(lp)
+        session.flush()
+        
+        # Animals
+        leopard = Animal(Species=u'Leopard', Lifespan=73.5,)
+        session.save(leopard)
+        leopard.ZooID = wap.ID
+        leopard.LastEscape = datetime.datetime(2004, 12, 21, 8, 15, 0, 999907)
+        
+        session.save(Animal(Species=u'Lion', ZooID=wap.ID))
+        session.save(Animal(Species=u'Slug', Legs=1, Lifespan=.75))
+        session.save(Animal(Species=u'Tiger', ZooID=sdz.ID))
+        
+        # Override Legs.default with itself just to make sure it works.
+        session.save(Animal(Species=u'Bear', Legs=4))
+        session.save(Animal(Species=u'Ostrich', Legs=2, Lifespan=103.2))
+        session.save(Animal(Species=u'Centipede', Legs=100))
+        
+        session.save(Animal(Species=u'Emperor Penguin', Legs=2, ZooID=seaworld.ID))
+        session.save(Animal(Species=u'Adelie Penguin', Legs=2, ZooID=seaworld.ID))
+        
+        session.save(Animal(Species=u'Millipede', Legs=1000000, ZooID=sdz.ID))
+        
+        # Add a mother and child to test relationships
+        bai_yun = Animal(Species=u'Ape', Nameu=u'Bai Yun', Legs=2)
+        session.save(bai_yun)
+        session.save(Animal(Species=u'Ape', Name=u'Hua Mei', Legs=2,
+                         MotherID=bai_yun.ID))
+        session.flush()
+        session.commit()
+
+    def test_baseline_2_insert(self):
+        for x in xrange(ITERATIONS):
+            session.save(Animal(Species=u'Tick', Name=u'Tick %d' % x, Legs=8))
+        session.flush()
+
+    def test_baseline_3_properties(self):
+        for x in xrange(ITERATIONS):
+            # Zoos
+            WAP = list(session.query(Zoo).filter(Zoo.Name==u'Wild Animal Park'))
+            SDZ = list(session.query(Zoo).filter(Zoo.Founded==datetime.date(1835, 9, 13)))
+            Biodome = list(session.query(Zoo).filter(Zoo.Name==u'Montr\xe9al Biod\xf4me'))
+            seaworld = list(session.query(Zoo).filter(Zoo.Admission == float(60)))
+            
+            # Animals
+            leopard = list(session.query(Animal).filter(Animal.Species == u'Leopard'))
+            ostrich = list(session.query(Animal).filter(Animal.Species==u'Ostrich'))
+            millipede = list(session.query(Animal).filter(Animal.Legs==1000000))
+            ticks = list(session.query(Animal).filter(Animal.Species==u'Tick'))
+
+    def test_baseline_4_expressions(self):
+        for x in xrange(ITERATIONS):
+            assert len(list(session.query(Zoo))) == 5
+            assert len(list(session.query(Animal))) == ITERATIONS + 12
+            assert len(list(session.query(Animal).filter(Animal.Legs==4))) == 4
+            assert len(list(session.query(Animal).filter(Animal.Legs == 2))) == 5
+            assert len(list(session.query(Animal).filter(and_(Animal.Legs >= 2, Animal.Legs < 20)))) == ITERATIONS + 9
+            assert len(list(session.query(Animal).filter(Animal.Legs > 10))) == 2
+            assert len(list(session.query(Animal).filter(Animal.Lifespan > 70))) == 2
+            assert len(list(session.query(Animal).filter(Animal.Species.like(u'L%')))) == 2
+            assert len(list(session.query(Animal).filter(Animal.Species.like(u'%pede')))) == 2
+
+            assert len(list(session.query(Animal).filter(Animal.LastEscape != None))) == 1
+            assert len(list(session.query(Animal).filter(Animal.LastEscape == None))) == ITERATIONS + 11
+
+            # In operator (containedby)
+            assert len(list(session.query(Animal).filter(Animal.Species.like(u'%pede%')))) == 2
+            assert len(list(session.query(Animal).filter(
+                    Animal.Species.in_((u'Lion', u'Tiger', u'Bear'))))) == 3
+
+            # Try In with cell references
+            class thing(object): pass
+            pet, pet2 = thing(), thing()
+            pet.Name, pet2.Name = u'Slug', u'Ostrich'
+            assert len(list(session.query(Animal).filter(Animal.Species.in_((pet.Name, pet2.Name))))) == 2
+
+            # logic and other functions
+            name =u'Lion'
+            assert len(list(session.query(Animal).filter(func.length(Animal.Species) == len(name)))) == ITERATIONS + 3
+
+            assert len(list(session.query(Animal).filter(Animal.Species.like(u'%i%')))) == ITERATIONS + 7
+
+            # Test now(), today(), year(), month(), day()
+            assert len(list(session.query(Zoo).filter(and_(Zoo.Founded != None, Zoo.Founded < func.now())))) == 3
+            assert len(list(session.query(Animal).filter(Animal.LastEscape == func.now()))) == 0
+            assert len(list(session.query(Animal).filter(func.date_part('year', Animal.LastEscape) == 2004))) == 1
+            assert len(list(session.query(Animal).filter(func.date_part('month', Animal.LastEscape) == 12))) == 1
+            assert len(list(session.query(Animal).filter(func.date_part('day', Animal.LastEscape) == 21))) == 1
+
+    def test_baseline_5_aggregates(self):
+        Animal = metadata.tables['Animal']
+        Zoo = metadata.tables['Zoo']
+        
+        # TODO: convert to ORM
+        for x in xrange(ITERATIONS):
+            # views
+            view = select([Animal.c.Legs]).execute().fetchall()
+            legs = [x[0] for x in view]
+            legs.sort()
+
+            expected = {'Leopard': 73.5,
+                        'Slug': .75,
+                        'Tiger': None,
+                        'Lion': None,
+                        'Bear': None,
+                        'Ostrich': 103.2,
+                        'Centipede': None,
+                        'Emperor Penguin': None,
+                        'Adelie Penguin': None,
+                        'Millipede': None,
+                        'Ape': None,
+                        'Tick': None,
+                        }
+            for species, lifespan in select([Animal.c.Species, Animal.c.Lifespan]
+                                            ).execute().fetchall():
+                assert lifespan == expected[species]
+
+            expected = [u'Montr\xe9al Biod\xf4me', 'Wild Animal Park']
+            e = select([Zoo.c.Name],
+                       and_(Zoo.c.Founded != None,
+                            Zoo.c.Founded <= func.current_timestamp(),
+                            Zoo.c.Founded >= datetime.date(1990, 1, 1)))
+            values = [val[0] for val in e.execute().fetchall()]
+            assert set(values) == set(expected)
+
+            # distinct
+            legs = [x[0] for x in
+                    select([Animal.c.Legs], distinct=True).execute().fetchall()]
+            legs.sort()
+
+    def test_baseline_6_editing(self):
+        for x in xrange(ITERATIONS):
+            # Edit
+            SDZ = session.query(Zoo).filter(Zoo.Name==u'San Diego Zoo').one()
+            SDZ.Name = u'The San Diego Zoo'
+            SDZ.Founded = datetime.date(1900, 1, 1)
+            SDZ.Opens = datetime.time(7, 30, 0)
+            SDZ.Admission = 35.00
+            
+            # Test edits
+            SDZ = session.query(Zoo).filter(Zoo.Name==u'The San Diego Zoo').one()
+            assert SDZ.Founded == datetime.date(1900, 1, 1), SDZ.Founded
+            
+            # Change it back
+            SDZ.Name = u'San Diego Zoo'
+            SDZ.Founded = datetime.date(1835, 9, 13)
+            SDZ.Opens = datetime.time(9, 0, 0)
+            SDZ.Admission = 0
+            
+            # Test re-edits
+            SDZ = session.query(Zoo).filter(Zoo.Name==u'San Diego Zoo').one()
+            assert SDZ.Founded == datetime.date(1835, 9, 13), SDZ.Founded
+
+    def test_baseline_7_drop(self):
+        metadata.drop_all()
+
+    # Now, run all of these tests again with the DB-API driver factored out:
+    # the ReplayableSession playback stands in for the database.
+
+    # How awkward is this in a unittest framework?  Very.
+
+    def test_profile_0(self):
+        global metadata, session
+
+        player = lambda: dbapi_session.player()
+        engine = create_engine('postgres:///', creator=player)
+        metadata = MetaData(engine)
+        session = sessionmaker()()
+
+    @profiling.function_call_count(4659)
+    def test_profile_1_create_tables(self):
+        self.test_baseline_1_create_tables()
+
+    @profiling.function_call_count(12478)
+    def test_profile_1a_populate(self):
+        self.test_baseline_1a_populate()
+
+    @profiling.function_call_count(1184)
+    def test_profile_2_insert(self):
+        self.test_baseline_2_insert()
+
+    @profiling.function_call_count(8323)
+    def test_profile_3_properties(self):
+        self.test_baseline_3_properties()
+
+    @profiling.function_call_count(29494)
+    def test_profile_4_expressions(self):
+        self.test_baseline_4_expressions()
+
+    @profiling.function_call_count(1327)
+    def test_profile_5_aggregates(self):
+        self.test_baseline_5_aggregates()
+
+    @profiling.function_call_count(3985)
+    def test_profile_6_editing(self):
+        self.test_baseline_6_editing()
+
+    def test_profile_7_drop(self):
+        self.test_baseline_7_drop()
+
+
+if __name__ == '__main__':
+    testenv.main()