Skip to content

Commit 16c04e2

Browse files
authored
PERF: drop GIL during long-running proj database calls (#1354)
These calls can take hundreds of milliseconds to access the PROJ databases, during which time no other Python code in any other thread can run. Use `nogil` to avoid this effect. This should be safe for these calls as they all take a separate PROJ threading context.
1 parent 3cea713 commit 16c04e2

File tree

2 files changed

+38
-27
lines changed

2 files changed

+38
-27
lines changed

pyproj/_transformer.pyx

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -330,14 +330,15 @@ cdef PJ* proj_create_crs_to_crs(
330330
ELSE:
331331
raise NotImplementedError("only_best requires PROJ 9.2+.")
332332

333-
334-
cdef PJ* transform = proj_create_crs_to_crs_from_pj(
335-
ctx,
336-
source_crs,
337-
target_crs,
338-
area,
339-
options,
340-
)
333+
cdef PJ* transform = NULL
334+
with nogil:
335+
transform = proj_create_crs_to_crs_from_pj(
336+
ctx,
337+
source_crs,
338+
target_crs,
339+
area,
340+
options,
341+
)
341342
proj_destroy(source_crs)
342343
proj_destroy(target_crs)
343344
if transform == NULL:

pyproj/database.pyx

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ def get_authorities():
6969
Authorities in PROJ database.
7070
"""
7171
cdef PJ_CONTEXT* context = pyproj_context_create()
72-
cdef PROJ_STRING_LIST proj_auth_list = proj_get_authorities_from_database(context)
72+
cdef PROJ_STRING_LIST proj_auth_list = NULL
73+
with nogil:
74+
proj_auth_list = proj_get_authorities_from_database(context)
7375
if proj_auth_list == NULL:
7476
pyproj_context_destroy(context)
7577
return []
@@ -108,14 +110,19 @@ def get_codes(str auth_name not None, pj_type not None, bint allow_deprecated=Fa
108110
cdef PJ_CONTEXT* context = NULL
109111
cdef PJ_TYPE cpj_type = get_pj_type(pj_type)
110112
cdef PROJ_STRING_LIST proj_code_list = NULL
113+
cdef const char* c_auth_name = NULL
114+
cdef bytes b_auth_name
111115
try:
112116
context = pyproj_context_create()
113-
proj_code_list = proj_get_codes_from_database(
114-
context,
115-
cstrencode(auth_name),
116-
cpj_type,
117-
allow_deprecated,
118-
)
117+
b_auth_name = cstrencode(auth_name)
118+
c_auth_name = b_auth_name
119+
with nogil:
120+
proj_code_list = proj_get_codes_from_database(
121+
context,
122+
c_auth_name,
123+
cpj_type,
124+
allow_deprecated,
125+
)
119126
finally:
120127
pyproj_context_destroy(context)
121128
if proj_code_list == NULL:
@@ -239,11 +246,12 @@ def query_crs_info(
239246
query_params.east_lon_degree = area_of_interest.east_lon_degree
240247
query_params.north_lat_degree = area_of_interest.north_lat_degree
241248

242-
crs_info_list = proj_get_crs_info_list_from_database(
243-
context,
244-
c_auth_name,
245-
query_params,
246-
&result_count)
249+
with nogil:
250+
crs_info_list = proj_get_crs_info_list_from_database(
251+
context,
252+
c_auth_name,
253+
query_params,
254+
&result_count)
247255
finally:
248256
if query_params != NULL:
249257
proj_get_crs_list_parameters_destroy(query_params)
@@ -400,13 +408,15 @@ def get_units_map(str auth_name=None, str category=None, bint allow_deprecated=F
400408

401409
cdef int num_units = 0
402410
cdef PJ_CONTEXT* context = pyproj_context_create()
403-
cdef PROJ_UNIT_INFO** db_unit_list = proj_get_units_from_database(
404-
context,
405-
c_auth_name,
406-
c_category,
407-
bool(allow_deprecated),
408-
&num_units,
409-
)
411+
cdef PROJ_UNIT_INFO** db_unit_list = NULL
412+
with nogil:
413+
db_unit_list = proj_get_units_from_database(
414+
context,
415+
c_auth_name,
416+
c_category,
417+
bool(allow_deprecated),
418+
&num_units,
419+
)
410420
units_map = {}
411421
try:
412422
for iii in range(num_units):

0 commit comments

Comments
 (0)