Skip to content

Optimization idea involving a UVWork class when there is no default executor. #111

@Vizonex

Description

@Vizonex

I think I have an idea about other ways the uvloop thread pool can be utilized besides just dns queries but sometimes it can be very inefficient to have 2 different thread pools running at the same time so I had the idea of implementing UVWork into the mix for being a backup when there is no default executor chosen so if something like asyncio.to_thread(...) was called, UVWork can be invoked in handling the blocking function.

Even though I'm still in the middle of brainstorming this idea, I think it's something the uvloop contributors and maintainers might take interest in implementing eventually which is why I bring this up now before I start making a draft Pull Request here and same with over there.

# Based on concurrent.Futures.thread._WorkItem
cdef class UVWork(UVRequest):
    cdef:
        object fut # asyncio.Future
        object fn
        tuple args
        object exc # Bad case scenario

    def __cinit__(self, Loop loop, object fut, object fn, tuple args):
        self.loop = loop
        self.request = <uv.uv_req_t*>PyMem_RawMalloc(sizeof(uv.uv_work_t))
        if self.request == NULL:
            raise MemoryError
        
        self.fut = fut
        self.func = fn
        self.args = args
        self.exc = None
        
        # hook data to UVWork because in this case we are the work.
        (<uv.uv_work_t>self.request).data = <void*>self
        # TODO:
        # uv.uv_queue_work(self.loop.uvloop, self.request, )

    cdef object run(self):
        cdef object result
        try:
            result = self.fn(*self.args)
        # TODO: Optimize using C Functions
        except BaseException as exc:
            self.loop.call_soon_threadsafe(self.fut.set_exception, exc)
        else:
            self.loop.call_soon_threadsafe(self.fut.set_result, result)

    # TODO:...
    # cpdef on_callback(self, fut: Future):
    #     if fut.cancelled():
    #         self.cancel()

    # cdef on_done(self):


cdef void on_work_cb(uv.uv_work_t *req) noexcept with gil:
    cdef UVWork work = <UVWork>req.data
    # run without needing help
    try:
        work.run()
    except BaseException as exc:
        work.loop.call_soon_threadsafe(work.fut.set_exception, exc)

Metadata

Metadata

Assignees

Labels

Programmers WantedAdditional Programmers wanted for writing a fix or helping with the review process.enhancementNew feature or requestuvloop-changesPull request or issue is related to uvloop changes

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions