Skip to content

Commit fcb5502

Browse files
authored
remove PYNULL_CACHE (#767)
* remove PYNULL_CACHE * restore PYNULL_CACHE but with a lock now * back to removing PYNULL_CACHE but now skip the finalizer * revert to some default settings in benchmark ci * docstring clarification --------- Co-authored-by: Christopher Rowley <github.com/cjdoris>
1 parent 2381ce1 commit fcb5502

3 files changed

Lines changed: 6 additions & 20 deletions

File tree

.github/workflows/benchmark_pr.yml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,5 @@ jobs:
88
steps:
99
- uses: MilesCranmer/AirspeedVelocity.jl@action-v1
1010
with:
11-
julia-version: "1"
1211
tune: "true"
13-
# Post to "summary" tab of workflow run:
14-
job-summary: "true"
15-
# Run benchmark using PR's version of the script:
1612
bench-on: ${{ github.event.pull_request.head.sha }}

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Changelog
22

33
## Unreleased
4-
54
* Add configuration via Preferences in addition to environment variables (e.g. `exe`
65
rather than `JULIA_PYTHONCALL_EXE`.)
6+
* Internals: removed the cache of unused Python objects. This makes `pydel!` faster and
7+
removes a race condition in free-threaded python.
78

89
## 0.9.32 (2026-05-14)
910
* Added `juliacall.TypeValue.__numpy_dtype__` attribute to allow converting Julia types

src/Core/Py.jl

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,6 @@ decref(x::Py) = Base.GC.@preserve x (decref(getptr(x)); x)
3737

3838
Base.unsafe_convert(::Type{C.PyPtr}, x::Py) = getptr(x)
3939

40-
const PYNULL_CACHE = Py[]
41-
4240
"""
4341
pynew([ptr])
4442
@@ -50,12 +48,7 @@ points at, i.e. the new `Py` object owns a reference.
5048
Note that NULL Python objects are not safe in the sense that most API functions will probably
5149
crash your Julia session if you pass a NULL argument.
5250
"""
53-
pynew() =
54-
if isempty(PYNULL_CACHE)
55-
Py(Val(:new), C.PyNULL)
56-
else
57-
pop!(PYNULL_CACHE)
58-
end
51+
pynew() = Py(Val(:new), C.PyNULL)
5952

6053
const PyNULL = pynew()
6154

@@ -86,21 +79,17 @@ DANGER! Use this function ONLY IF the Julia object `x` could have been garbage-c
8679
anyway, i.e. was about to become unreachable. This means you MUST KNOW that no other part of
8780
the program has the Julia object `x`.
8881
89-
This decrements the reference count, sets the pointer to NULL and appends `x` to a cache
90-
of unused objects (`PYNULL_CACHE`).
82+
This decrements the reference count and sets the pointer to NULL.
9183
92-
This is an optimization to avoid excessive allocation and deallocation in Julia, which can
93-
be a significant source of slow-down in code which uses a lot of Python objects. It allows
94-
`pynew()` to pop an item from `PYNULL_CACHE` instead of allocating one, and avoids calling
95-
the relatively slow finalizer on `x`.
84+
Use this to eagerly free a Python object, rather than waiting for Julia's GC to finalize
85+
it at some indeterminate point in the future.
9686
"""
9787
function pydel!(x::Py)
9888
ptr = getptr(x)
9989
if ptr != C.PyNULL
10090
C.Py_DecRef(ptr)
10191
setptr!(x, C.PyNULL)
10292
end
103-
push!(PYNULL_CACHE, x)
10493
return
10594
end
10695

0 commit comments

Comments
 (0)