Skip to content

Proposal for using sublime.set_timeout_async as the loop's default executor #6

@rwols

Description

@rwols

You can run blocking, compute-intensive functions using run_in_executor:

def compute_intensive_function() -> int:
    time.sleep(1)
    return 42

async def f() -> int:
    result = await asyncio.get_running_loop().run_in_executor(None, compute_intensive_function)
    return result

The first argument is a concurrent.futures.Executor. When None is passed, the default executor is lazily instantiated, which by default is a concurrent.futures.ThreadPoolExecutor.

.

The documentation for ThreadPoolExecutor mentions that it will by default spawn

min(32, (os.process_cpu_count() or 1) + 4)

threads. Now here's the point where I'm going to be opinionated. I consider this too many threads for text editor plugins. For a server? Sure. Not for a text editor.

Because we already have a thread available to us for compute-intensive work, we should utilize that thread. This issue proposes we do that.

In my exploratory library I wrote such an executor here: https://github.com/sublimelsp/sublime_asyncio/blob/master/executor.py

It is hooked up to the loop here: https://github.com/sublimelsp/sublime_asyncio/blob/6a8eb2dbd36c72b34eb0078bc1b3cb96f1692acb/globalstate.py#L71

This will cause calls like this:

async def f() -> int:
    result = await asyncio.get_running_loop().run_in_executor(None, compute_intensive_function)
    return result

to use ST's async thread. Yes, you can still pass a custom executor that spawns too many threads for a text editor. Like bringing a leaf blower to move a single leaf. But that's every plugin author's deliberate choice then.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions