]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
Some refcount care in tight loops
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 8 Jan 2021 02:54:36 +0000 (03:54 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 8 Jan 2021 02:54:36 +0000 (03:54 +0100)
psycopg3_c/psycopg3_c/_psycopg3/copy.pyx
psycopg3_c/psycopg3_c/_psycopg3/transform.pyx

index 059569f91ff8428a556533f20778d913f5d1736e..009e6ea298e865a47381d63b6cf8e67e7e4ee95e 100644 (file)
@@ -42,11 +42,12 @@ def format_row_binary(
     cdef uint32_t besize
     cdef char *buf
     cdef int i
+    fmt = FORMAT_BINARY
 
     for i in range(rowlen):
         item = row[i]
         if item is not None:
-            dumper = tx.get_dumper(item, FORMAT_BINARY)
+            dumper = tx.get_dumper(item, fmt)
             if isinstance(dumper, CDumper):
                 # A cdumper can resize if necessary and copy in place
                 size = (<CDumper>dumper).cdump(item, out, pos + sizeof(besize))
@@ -56,7 +57,7 @@ def format_row_binary(
                 memcpy(target + pos, <void *>&besize, sizeof(besize))
             else:
                 # A Python dumper, gotta call it and extract its juices
-                b = dumper.dump(item)
+                b = PyObject_CallFunctionObjArgs(dumper.dump, <PyObject *>item, NULL)
                 _buffer_as_string_and_size(b, &buf, &size)
                 target = CDumper.ensure_size(out, pos, size + sizeof(besize))
                 besize = htobe32(size)
@@ -98,6 +99,7 @@ def format_row_text(
     cdef unsigned char *target
     cdef int nesc = 0
     cdef int with_tab
+    fmt = FORMAT_TEXT
 
     for i in range(rowlen):
         # Include the tab before the data, so it gets included in the resizes
@@ -115,14 +117,14 @@ def format_row_text(
                 pos += 2
             continue
 
-        dumper = tx.get_dumper(item, FORMAT_TEXT)
+        dumper = tx.get_dumper(item, fmt)
         if isinstance(dumper, CDumper):
             # A cdumper can resize if necessary and copy in place
             size = (<CDumper>dumper).cdump(item, out, pos + with_tab)
             target = <unsigned char *>PyByteArray_AS_STRING(out) + pos
         else:
             # A Python dumper, gotta call it and extract its juices
-            b = dumper.dump(item)
+            b = PyObject_CallFunctionObjArgs(dumper.dump, <PyObject *>item, NULL)
             _buffer_as_string_and_size(b, &buf, &size)
             target = <unsigned char *>CDumper.ensure_size(out, pos, size + with_tab)
             memcpy(target + with_tab, buf, size)
index 8d9ea6ff3a177d2580d9e335f3ebb7aed7a7070c..1d5c21e32cbc70aedcf9804c692db08f14c4f066 100644 (file)
@@ -247,18 +247,13 @@ cdef class Transformer:
             Py_INCREF(record)
             PyList_SET_ITEM(records, row - row0, record)
 
-        cdef RowLoader loader
-        cdef CLoader cloader
-        cdef object pyloader
+        cdef PyObject *loader  # borrowed RowLoader
         cdef PyObject *brecord  # borrowed
-        for col in range(self._nfields):
-            # TODO: the is some visible python churn around this lookup.
-            # replace with a C array of borrowed references pointing to
-            # the cloader.cload function pointer
-            loader = self._row_loaders[col]
-            if loader.cloader is not None:
-                cloader = loader.cloader
+        row_loaders = self._row_loaders  # avoid an incref/decref per item
 
+        for col in range(self._nfields):
+            loader = PyList_GET_ITEM(row_loaders, col)
+            if (<RowLoader>loader).cloader is not None:
                 for row in range(row0, row1):
                     brecord = PyList_GET_ITEM(records, row - row0)
                     attval = &(ires.tuples[row][col])
@@ -267,13 +262,12 @@ cdef class Transformer:
                         PyTuple_SET_ITEM(<object>brecord, col, None)
                         continue
 
-                    pyval = loader.cloader.cload(attval.value, attval.len)
+                    pyval = (<RowLoader>loader).cloader.cload(
+                        attval.value, attval.len)
                     Py_INCREF(pyval)
                     PyTuple_SET_ITEM(<object>brecord, col, pyval)
 
             else:
-                pyloader = loader.pyloader
-
                 for row in range(row0, row1):
                     brecord = PyList_GET_ITEM(records, row - row0)
                     attval = &(ires.tuples[row][col])
@@ -285,7 +279,7 @@ cdef class Transformer:
                     # TODO: no copy
                     b = attval.value[:attval.len]
                     pyval = PyObject_CallFunctionObjArgs(
-                        pyloader, <PyObject *>b, NULL)
+                        (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
                     Py_INCREF(pyval)
                     PyTuple_SET_ITEM(<object>brecord, col, pyval)
 
@@ -302,13 +296,15 @@ cdef class Transformer:
         # cheeky access to the internal PGresult structure
         cdef pg_result_int *ires = <pg_result_int*>res
 
-        cdef RowLoader loader
+        cdef PyObject *loader  # borrowed RowLoader
         cdef int col
         cdef PGresAttValue *attval
         cdef const char *val
         cdef object record  # not 'tuple' as it would check on assignment
 
         record = PyTuple_New(self._nfields)
+        row_loaders = self._row_loaders  # avoid an incref/decref per item
+
         for col in range(self._nfields):
             attval = &(ires.tuples[row][col])
             if attval.len == -1:  # NULL_LEN
@@ -316,18 +312,15 @@ cdef class Transformer:
                 PyTuple_SET_ITEM(record, col, None)
                 continue
 
-            # TODO: the is some visible python churn around this lookup.
-            # replace with a C array of borrowed references pointing to
-            # the cloader.cload function pointer
-            loader = self._row_loaders[col]
             val = attval.value
-            if loader.cloader is not None:
-                pyval = loader.cloader.cload(val, attval.len)
+            loader = PyList_GET_ITEM(row_loaders, col)
+            if (<RowLoader>loader).cloader is not None:
+                pyval = (<RowLoader>loader).cloader.cload(val, attval.len)
             else:
                 # TODO: no copy
                 b = val[:attval.len]
                 pyval = PyObject_CallFunctionObjArgs(
-                    loader.pyloader, <PyObject *>b, NULL)
+                    (<RowLoader>loader).pyloader, <PyObject *>b, NULL)
 
             Py_INCREF(pyval)
             PyTuple_SET_ITEM(record, col, pyval)