PythonCall.jl icon indicating copy to clipboard operation
PythonCall.jl copied to clipboard

reducing allocations when checking python coroutines

Open untoreh opened this issue 1 year ago • 6 comments

If I do:

while !Bool(fut.done())
    sleep(0.01)
end

where fut is a future created like:

aio = pyimport("asyncio")
coro = aio.sleep(1)
loop = aio.Runner().get_loop()
aio.run_coroutine_threadsafe(coro, loop)

It allocates linearly the more you sleep. I tried using a global julia vector [true] and updating it in place when the future is done, but it doesn't reduce allocations that much, is there a better way?

untoreh avatar Mar 18 '23 13:03 untoreh

Is this actually causing issues? The Julia garbage collector only kicks in when you are running out of memory, so it may just be that you haven't run it for long enough for the GC to kick in.

cjdoris avatar Mar 19 '23 15:03 cjdoris

If that were the case only @allocated would increase, while @allocations would be somewhat stable? @allocations still increases linearly the more I sleep, moreover, the number of allocations returned is always the same given the same amount of sleep. Increasing the sleep time, to reduce the number of iterations also allocates (still linearly) less

untoreh avatar Mar 19 '23 17:03 untoreh

Can you give me some code and output that demonstrates the issue please?

cjdoris avatar Mar 22 '23 14:03 cjdoris

using PythonCall
using PythonCall: pynew, pycopy!, pyisnull
using PythonCall.C.CondaPkg

const pyaio = pynew()
const pyuv = pynew()
const pythreads = pynew()
const pyrunner = pynew()
const pyrunner_thread = pynew()
const pyloop = pynew()

start_loop() = begin
    pycopy!(pyaio, pyimport("asyncio"))
    pycopy!(pyuv, pyimport("uvloop"))
    pycopy!(pythreads, pyimport("threading"))

    @assert !pyisnull(pyaio)
    @assert !pyisnull(pythreads)
    @assert pyisnull(pyloop) || !Bool(pyloop.is_running())
    @assert pyisnull(pyrunner_thread) || !Bool(pyrunner_thread.is_alive())

    pycopy!(pyrunner, pyaio.Runner(; loop_factory=pyuv.new_event_loop))
    pycopy!(
        pyrunner_thread, pythreads.Thread(; target=pyrunner.run, args=[async_main_func()()])
    )

    pyrunner_thread.daemon = pybuiltins.True
    pyrunner_thread.start()
    pycopy!(pyloop, pyrunner.get_loop())
end

function async_main_func()
    @pyexec () => """
    global asyncio, inf
    import asyncio
    from math import inf
    async def main():
        try:
            await asyncio.sleep(inf)
        finally:
            asyncio.get_running_loop().stop()
    """ => main
end

function pyschedule(coro::Py)
    pyaio.run_coroutine_threadsafe(coro, pyloop)
end
pywait_fut(fut::Py) = begin
    while !Bool(fut.done())
        sleep(0.01)
    end
end
pytask(coro::Py, ::Val{:coro}) = begin
    @async let fut = pyschedule(coro)
        pywait_fut(fut)
        fut.result()
    end
end
pytask(f::Py, args...; kwargs...) = pytask(f(args...; kwargs...), Val(:coro))
pyfetch(f::Py, args...; kwargs...) = fetch(pytask(f, args...; kwargs...))

test() = begin
    CondaPkg.add_pip("uvloop")
    start_loop()
    # compile
    pyfetch(pyaio.sleep, 0.)
    println("@allocated:")
    println("Sleeping for 1s")
    display(@allocated pyfetch(pyaio.sleep, 1.0))
    println("Sleeping for 3s")
    display(@allocated pyfetch(pyaio.sleep, 3.0))
    println("Sleeping for 9s")
    display(@allocated pyfetch(pyaio.sleep, 9.0))
    println("\n@allocations")
    println("Sleeping for 1s")
    display(@allocations pyfetch(pyaio.sleep, 1.0))
    println("Sleeping for 3s")
    display(@allocations pyfetch(pyaio.sleep, 3.0))
    println("Sleeping for 9s")
    display(@allocations pyfetch(pyaio.sleep, 9.0))
end

test()

untoreh avatar Apr 08 '23 08:04 untoreh

This issue has been marked as stale because it has been open for 30 days with no activity. If the issue is still relevant then please leave a comment, or else it will be closed in 7 days.

github-actions[bot] avatar Aug 29 '23 01:08 github-actions[bot]

This issue has been closed because it has been stale for 7 days. You can re-open it if it is still relevant.

github-actions[bot] avatar Sep 06 '23 01:09 github-actions[bot]