summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorFederico Caselli <cfederico87@gmail.com>2023-04-19 18:39:18 -0400
committermike bayer <mike_mp@zzzcomputing.com>2023-04-26 19:48:00 +0000
commit105f18be353965b064750726597b63334fc0716b (patch)
tree29ee8a339ea86dbb37fc07b2e654d11c5922a419 /test
parentff198e35f0e04b8d38df25df234e72259069b4d1 (diff)
downloadsqlalchemy-105f18be353965b064750726597b63334fc0716b.tar.gz
Performance improvement in Row
Various performance improvements to Row instanciation - avoid passing processors if they are all None - improve processor logic in cython - improve tuplegetter using slices when contiguous indexes are used Some timing follow. In particular [base_]row_new_proc that tests using processors has a 25% improvement compared to before in cython. Looking at the [b]row_new_proc_none that test a list of processors all None, this has 50% improvement in cython when passing the none list, but in this patch it would usually be disabled by passing None, so the performance gain is actually 90%, since it would run the case [base_]row_new. Tuplegetter is a bit faster in the single item get and when getting sequential indexes (like indexes 1,2,3,4) at the cost of a bit longer creation time in python, cython is mostly the same. Current times | python | cython | cy / py | base_row_new | 0.639817400 | 0.118265500 | 0.184842582 | row_new | 0.680355100 | 0.129714600 | 0.190657202 | base_row_new_proc | 3.076538900 | 1.488428600 | 0.483799701 | row_new_proc | 3.119700100 | 1.532197500 | 0.491136151 | brow_new_proc_none | 1.917702300 | 0.475511500 | 0.247958977 | row_new_proc_none | 1.956253300 | 0.497803100 | 0.254467609 | tuplegetter_one | 0.152512600 | 0.148523900 | 0.973846751 | tuplegetter_many | 0.184394100 | 0.184511500 | 1.000636680 | tuplegetter_seq | 0.154832800 | 0.156270100 | 1.009282917 | tuplegetter_new_one | 0.523730000 | 0.343402200 | 0.655685563 | tuplegetter_new_many| 0.738924400 | 0.420961400 | 0.569694816 | tuplegetter_new_seq | 1.062036900 | 0.495462000 | 0.466520514 | Parent commit times | python | cython | cy / py | base_row_new | 0.643890800 | 0.113548300 | 0.176347138 | row_new | 0.674885900 | 0.124391800 | 0.184315304 | base_row_new_proc | 3.072020400 | 2.017367000 | 0.656690626 | row_new_proc | 3.109943400 | 2.048359400 | 0.658648450 | brow_new_proc_none | 1.967133700 | 1.006326000 | 0.511569702 | row_new_proc_none | 1.960814900 | 1.025217800 | 0.522852922 | tuplegetter_one | 0.197359900 | 0.205999000 | 1.043773330 | tuplegetter_many | 0.196575900 | 0.194888500 | 0.991416038 | tuplegetter_seq | 0.192723900 | 0.205635000 | 1.066992729 | tuplegetter_new_one | 0.534644500 | 0.414311700 | 0.774929322 | tuplegetter_new_many| 0.479376500 | 0.417448100 | 0.870814694 | tuplegetter_new_seq | 0.481580200 | 0.412697900 | 0.856966088 | Change-Id: I2ca1f49dca2beff625c283f1363c29c8ccc0c3f7
Diffstat (limited to 'test')
-rw-r--r--test/base/test_result.py24
-rw-r--r--test/perf/compiled_extensions.py65
-rw-r--r--test/profiles.txt16
3 files changed, 83 insertions, 22 deletions
diff --git a/test/base/test_result.py b/test/base/test_result.py
index 05f922d67..83017c165 100644
--- a/test/base/test_result.py
+++ b/test/base/test_result.py
@@ -236,6 +236,30 @@ class ResultTupleTest(fixtures.TestBase):
row3 = loads(state2)
is_true(isinstance(row3, dump_cls))
+ def test_processors(self):
+ parent = result.SimpleResultMetaData(["a", "b", "c", "d"])
+ data = (1, 99, "42", "foo")
+ row_none = result.Row(parent, None, parent._key_to_index, data)
+ eq_(row_none._to_tuple_instance(), data)
+ row_all_p = result.Row(
+ parent, [str, float, int, str.upper], parent._key_to_index, data
+ )
+ eq_(row_all_p._to_tuple_instance(), ("1", 99.0, 42, "FOO"))
+ row_some_p = result.Row(
+ parent, [None, str, None, str.upper], parent._key_to_index, data
+ )
+ eq_(row_some_p._to_tuple_instance(), (1, "99", "42", "FOO"))
+ row_shorter = result.Row(
+ parent, [None, str], parent._key_to_index, data
+ )
+ eq_(row_shorter._to_tuple_instance(), (1, "99"))
+
+ def test_tuplegetter(self):
+ data = list(range(10, 20))
+ eq_(result.tuplegetter(1)(data), [11])
+ eq_(result.tuplegetter(1, 9, 3)(data), (11, 19, 13))
+ eq_(result.tuplegetter(2, 3, 4)(data), [12, 13, 14])
+
class ResultTest(fixtures.TestBase):
def _fixture(
diff --git a/test/perf/compiled_extensions.py b/test/perf/compiled_extensions.py
index 14bb4e4ab..872165d07 100644
--- a/test/perf/compiled_extensions.py
+++ b/test/perf/compiled_extensions.py
@@ -787,6 +787,8 @@ class OrderedSet(IdentitySet):
class TupleGetter(Case):
+ NUMBER = 2_000_000
+
@staticmethod
def python():
from sqlalchemy.engine._py_row import tuplegetter
@@ -817,20 +819,7 @@ class TupleGetter(Case):
self.tuple = tuple(range(1000))
self.tg_inst = self.impl_tg(42)
self.tg_inst_m = self.impl_tg(42, 420, 99, 9, 1)
-
- class MockRow:
- def __init__(self, data):
- self.data = data
-
- def __getitem__(self, index):
- # called by python
- return self.data[index]
-
- def _get_by_key_impl_mapping(self, index):
- # called by c
- return self.data[index]
-
- self.row = MockRow(self.tuple)
+ self.tg_inst_seq = self.impl_tg(*range(70, 75))
@classmethod
def update_results(cls, results):
@@ -847,6 +836,10 @@ class TupleGetter(Case):
self.tg_inst_m(self.tuple)
@test_case
+ def tuplegetter_seq(self):
+ self.tg_inst_seq(self.tuple)
+
+ @test_case
def tuplegetter_new_one(self):
self.impl_tg(42)(self.tuple)
@@ -854,6 +847,10 @@ class TupleGetter(Case):
def tuplegetter_new_many(self):
self.impl_tg(42, 420, 99, 9, 1)(self.tuple)
+ @test_case
+ def tuplegetter_new_seq(self):
+ self.impl_tg(40, 41, 42, 43, 44)(self.tuple)
+
class BaseRow(Case):
@staticmethod
@@ -911,6 +908,30 @@ class BaseRow(Case):
self.row_state = self.row.__getstate__()
self.row_long_state = self.row_long.__getstate__()
+ assert len(ascii_letters) == 52
+ self.parent_proc = SimpleResultMetaData(
+ tuple(ascii_letters),
+ _processors=[None, int, float, None, str] * 10, # cut the last 2
+ )
+ self.row_proc_args = (
+ self.parent_proc,
+ self.parent_proc._processors,
+ self.parent_proc._key_to_index,
+ tuple(range(len(ascii_letters))),
+ )
+
+ self.parent_proc_none = SimpleResultMetaData(
+ tuple(ascii_letters), _processors=[None] * 52
+ )
+ self.row_proc_none_args = (
+ self.parent_proc_none,
+ # NOTE: usually the code calls _effective_processors that returns
+ # None for this case of all None.
+ self.parent_proc_none._processors,
+ self.parent_proc_none._key_to_index,
+ tuple(range(len(ascii_letters))),
+ )
+
@classmethod
def update_results(cls, results):
cls._divide_results(results, "c", "python", "c / py")
@@ -928,6 +949,22 @@ class BaseRow(Case):
self.Row(*self.row_long_args)
@test_case
+ def base_row_new_proc(self):
+ self.impl(*self.row_proc_args)
+
+ @test_case
+ def row_new_proc(self):
+ self.Row(*self.row_proc_args)
+
+ @test_case
+ def brow_new_proc_none(self):
+ self.impl(*self.row_proc_none_args)
+
+ @test_case
+ def row_new_proc_none(self):
+ self.Row(*self.row_proc_none_args)
+
+ @test_case
def row_dumps(self):
self.row.__getstate__()
self.row_long.__getstate__()
diff --git a/test/profiles.txt b/test/profiles.txt
index 7379f5f3c..fd229ed03 100644
--- a/test/profiles.txt
+++ b/test/profiles.txt
@@ -376,7 +376,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_6
test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 2592
test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 25595
test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 2539
-test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 15600
+test.aaa_profiling.test_resultset.ResultSetTest.test_fetch_by_key_mappings x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 14614
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-0]
@@ -406,7 +406,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 16
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 14
-test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 16
+test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 15
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2]
@@ -421,7 +421,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 14
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 16
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 14
-test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 16
+test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[False-2] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 15
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1]
@@ -436,7 +436,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 17
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 19
test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 17
-test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 19
+test.aaa_profiling.test_resultset.ResultSetTest.test_one_or_none[True-1] x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 18
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string
@@ -451,7 +451,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpy
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 291
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 6291
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 257
-test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 6257
+test.aaa_profiling.test_resultset.ResultSetTest.test_raw_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 5277
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode
@@ -466,7 +466,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cp
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 291
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 6291
test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 257
-test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 6257
+test.aaa_profiling.test_resultset.ResultSetTest.test_raw_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 5277
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_string
@@ -481,7 +481,7 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython
test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 585
test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 6589
test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 532
-test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 6536
+test.aaa_profiling.test_resultset.ResultSetTest.test_string x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 5605
# TEST: test.aaa_profiling.test_resultset.ResultSetTest.test_unicode
@@ -496,4 +496,4 @@ test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpytho
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_cextensions 585
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpython_3.10_postgresql_psycopg2_dbapiunicode_nocextensions 6589
test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 532
-test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 6536
+test.aaa_profiling.test_resultset.ResultSetTest.test_unicode x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 5605