]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
perf(c): take more care about the GIL around potentially blocking functions
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Wed, 2 Nov 2022 11:01:42 +0000 (12:01 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Fri, 4 Nov 2022 16:29:04 +0000 (17:29 +0100)
psycopg_c/psycopg_c/_psycopg/generators.pyx
psycopg_c/psycopg_c/pq/libpq.pxd

index 67bdd13f4c329cacf64e5435a1635107a59accd0..e389ef7a03a2b1c16dfb11f104d76544c171e191 100644 (file)
@@ -39,7 +39,9 @@ def connect(conninfo: str) -> PQGenConn[abc.PGconn]:
                 pgconn=conn
             )
 
-        poll_status = libpq.PQconnectPoll(pgconn_ptr)
+        with nogil:
+            poll_status = libpq.PQconnectPoll(pgconn_ptr)
+
         if poll_status == libpq.PGRES_POLLING_OK:
             break
         elif poll_status == libpq.PGRES_POLLING_READING:
@@ -142,7 +144,6 @@ def fetch_many(pq.PGconn pgconn) -> PQGen[List[PGresult]]:
         if status == libpq.PGRES_PIPELINE_SYNC:
             # PIPELINE_SYNC is not followed by a NULL, but we return it alone
             # similarly to other result sets.
-            assert len(results) == 1, results
             break
 
     return results
@@ -158,10 +159,12 @@ def fetch(pq.PGconn pgconn) -> PQGen[Optional[PGresult]]:
     Return a result from the database (whether success or error).
     """
     cdef libpq.PGconn *pgconn_ptr = pgconn._pgconn_ptr
-    cdef int cires, ibres = 0
+    cdef int cires, ibres
     cdef libpq.PGresult *pgres
 
-    if libpq.PQisBusy(pgconn_ptr):
+    with nogil:
+        ibres = libpq.PQisBusy(pgconn_ptr)
+    if ibres:
         yield WAIT_R
         while True:
             with nogil:
@@ -178,7 +181,8 @@ def fetch(pq.PGconn pgconn) -> PQGen[Optional[PGresult]]:
 
     _consume_notifies(pgconn)
 
-    pgres = libpq.PQgetResult(pgconn_ptr)
+    with nogil:
+        pgres = libpq.PQgetResult(pgconn_ptr)
     if pgres is NULL:
         return None
     return pq.PGresult._from_ptr(pgres)
@@ -214,8 +218,13 @@ def pipeline_communicate(
             _consume_notifies(pgconn)
 
             res: List[PGresult] = []
-            while not libpq.PQisBusy(pgconn_ptr):
-                pgres = libpq.PQgetResult(pgconn_ptr)
+            while True:
+                with nogil:
+                    ibres = libpq.PQisBusy(pgconn_ptr)
+                    if ibres:
+                        break
+                    pgres = libpq.PQgetResult(pgconn_ptr)
+
                 if pgres is NULL:
                     if not res:
                         break
@@ -225,13 +234,11 @@ def pipeline_communicate(
                     status = libpq.PQresultStatus(pgres)
                     r = pq.PGresult._from_ptr(pgres)
                     if status == libpq.PGRES_PIPELINE_SYNC:
-                        assert not res
                         results.append([r])
                         break
                     else:
                         res.append(r)
 
-
         if ready & READY_W:
             pgconn.flush()
             if not commands:
index 2f69e2fd1a240df26761e3f4b0616796a6a3c51c..5e05e40a89ad183f2bf261711abec7aa87aeaee7 100644 (file)
@@ -106,7 +106,7 @@ cdef extern from "libpq-fe.h":
     # 33.1. Database Connection Control Functions
     PGconn *PQconnectdb(const char *conninfo)
     PGconn *PQconnectStart(const char *conninfo)
-    PostgresPollingStatusType PQconnectPoll(PGconn *conn)
+    PostgresPollingStatusType PQconnectPoll(PGconn *conn) nogil
     PQconninfoOption *PQconndefaults()
     PQconninfoOption *PQconninfo(PGconn *conn)
     PQconninfoOption *PQconninfoParse(const char *conninfo, char **errmsg)
@@ -131,7 +131,7 @@ cdef extern from "libpq-fe.h":
     int PQprotocolVersion(const PGconn *conn)
     int PQserverVersion(const PGconn *conn)
     char *PQerrorMessage(const PGconn *conn)
-    int PQsocket(const PGconn *conn)
+    int PQsocket(const PGconn *conn) nogil
     int PQbackendPID(const PGconn *conn)
     int PQconnectionNeedsPassword(const PGconn *conn)
     int PQconnectionUsedPassword(const PGconn *conn)
@@ -160,14 +160,14 @@ cdef extern from "libpq-fe.h":
                              const int *paramLengths,
                              const int *paramFormats,
                              int resultFormat) nogil
-    PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName)
-    PGresult *PQdescribePortal(PGconn *conn, const char *portalName)
-    ExecStatusType PQresultStatus(const PGresult *res)
+    PGresult *PQdescribePrepared(PGconn *conn, const char *stmtName) nogil
+    PGresult *PQdescribePortal(PGconn *conn, const char *portalName) nogil
+    ExecStatusType PQresultStatus(const PGresult *res) nogil
     # PQresStatus: not needed, we have pretty enums
-    char *PQresultErrorMessage(const PGresult *res)
+    char *PQresultErrorMessage(const PGresult *res) nogil
     # TODO: PQresultVerboseErrorMessage
-    char *PQresultErrorField(const PGresult *res, int fieldcode)
-    void PQclear(PGresult *res)
+    char *PQresultErrorField(const PGresult *res, int fieldcode) nogil
+    void PQclear(PGresult *res) nogil
 
     # 33.3.2. Retrieving Query Result Information
     int PQntuples(const PGresult *res)
@@ -232,14 +232,14 @@ cdef extern from "libpq-fe.h":
                             const int *paramLengths,
                             const int *paramFormats,
                             int resultFormat) nogil
-    int PQsendDescribePrepared(PGconn *conn, const char *stmtName)
-    int PQsendDescribePortal(PGconn *conn, const char *portalName)
-    PGresult *PQgetResult(PGconn *conn)
+    int PQsendDescribePrepared(PGconn *conn, const char *stmtName) nogil
+    int PQsendDescribePortal(PGconn *conn, const char *portalName) nogil
+    PGresult *PQgetResult(PGconn *conn) nogil
     int PQconsumeInput(PGconn *conn) nogil
     int PQisBusy(PGconn *conn) nogil
-    int PQsetnonblocking(PGconn *conn, int arg)
+    int PQsetnonblocking(PGconn *conn, int arg) nogil
     int PQisnonblocking(const PGconn *conn)
-    int PQflush(PGconn *conn)
+    int PQflush(PGconn *conn) nogil
 
     # 33.5. Retrieving Query Results Row-by-Row
     int PQsetSingleRowMode(PGconn *conn)