I think this function in Julia allocates once, 16 bytes, at poptask (can’t easily run it alone):
julia> function wait()
GC.safepoint()
W = Base.workqueue_for(Threads.threadid())
Base.poptask(W)
result = Base.try_yieldto(Base.ensure_rescheduled) # probably not here
Base.process_events() # NOT here
# return when we come out of the queue
return result
end
It’s called from:
julia> s = "Palli"; @time (Base.iolock_begin(); Base.uv_write(stdout, convert(Ptr{UInt8}, pointer(s)), convert(UInt, 7)))
Palli 0.000051 seconds (2 allocations: 32 bytes)
7
There are the 2 remaining allocations I’m trying to eliminate from print (plus one hidden):
# caller must have acquired the iolock
julia> function uv_write(s::Base.LibuvStream, p::Ptr{UInt8}, n::UInt)
uvw = Base.uv_write_async(s, p, n)
ct = current_task()
Base.preserve_handle(ct)
Base.sigatomic_begin()
Base.uv_req_set_data(uvw, ct)
Base.iolock_end()
local status
try
Base.sigatomic_end()
# wait for the last chunk to complete (or error)
# assume that any errors would be sticky,
# (so we don't need to monitor the error status of the intermediate writes)
wait()::Cint # 1 allocation of 16 bytes
Base.sigatomic_begin()
finally
# try-finally unwinds the sigatomic level, so need to repeat sigatomic_end
Base.sigatomic_end()
Base.iolock_begin()
# ct.queue === nothing || list_deletefirst!(ct.queue::IntrusiveLinkedList{Task}, ct)
# if uv_req_data(uvw) != C_NULL
# uvw is still alive,
# so make sure we won't get spurious notifications later
# uv_req_set_data(uvw, C_NULL)
# else
# done with uvw
# Libc.free(uvw)
# end
Base.iolock_end();
Base.unpreserve_handle(ct)
end
if status < 0
throw(_UVError("write", status))
end
return Int(n)
end
Note, I’ve commented out a bit there from what is in Base. And added Base.
in some places so that I can easily substitute.
I believe nothing up to finally
allocates there except wait()
. And then something after. uv_write_async DOES allocated with Libc.malloc, and then freed in that other function… maybe not a good code-pattern, I thought I had found a memory leak. I know about that hidden allocation. Any good idea about how to eliminate that less bad allocation also?