omnilib/aiosqlite

Performance enhancements

m-schubert opened this issue · 1 comments

I ran into similar problems as found in 48e3021 regarding performance issues. I noticed it especially with processes that ran many, small queries.

I wasn't particularly happy with the _execute() method blocking the event loop at all, and just polling by adding asyncio.sleep calls means spending a heap of time sleeping.

I rewrote the run() and _execute(). The result is a simpler thread loop, commands to be executed can be queued (I removed the asyncio.Lock), and awaiting a result no longer relies on polling, so results become available almost instantly after being processed in the SQLite thread.

My code:

class FasterConnection(aiosqlite.Connection):
    def run(self):
        while self._running:
            try:
                future, function = self._tx.get(timeout=0.1)
            except queue.Empty:
                continue

            try:
                self._loop.call_soon_threadsafe(future.set_result, function())
            except BaseException as e:
                self._loop.call_soon_threadsafe(future.set_exception(e))

    async def _execute(self, fn, *args, **kwargs):
        function = functools.partial(fn, *args, **kwargs)
        future = self._loop.create_future()

        self._tx.put_nowait((future, function))

        return await future

I know this isn't the traditional way of submitting code to a project, I apologise. Hopefully it's useful, however.

Interesting idea. Would you, or someone else, be willing to submit this as a pull request?