• Does Python Need Virtual Threads? (Posting On Python-List Prohibited)

    From Lawrence D'Oliveiro@21:1/5 to All on Sat Jun 14 04:11:55 2025
    Short answer: no.

    <https://discuss.python.org/t/add-virtual-threads-to-python/91403>

    Firstly, anybody appealing to Java as an example of how to design a
    programming language should immediately be sending your bullshit detector
    into the yellow zone.

    Secondly, the link to a critique of JavaScript that dates from 2015, from before the language acquired its async/await constructs, should be another warning sign.

    Looking at that Java spec, a “virtual thread” is just another name for “stackful coroutine”. Because that’s what you get when you take away implicit thread preemption and substitute explicit preemption instead.

    The continuation concept is useful in its own right. Why not concentrate
    on implementing that as a new primitive instead?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lawrence D'Oliveiro on Sat Jun 14 04:29:07 2025
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    Looking at that Java spec, a “virtual thread” is just another name for “stackful coroutine”. Because that’s what you get when you take away implicit thread preemption and substitute explicit preemption instead.

    Try using Erlang a little, It has preemptive lightweight processes and
    it is great. Much better than async/await imho.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to Lawrence D'Oliveiro on Sat Jun 14 23:23:23 2025
    Concerning virtual threads the only problem
    with Java I have is, that JDK 17 doesn't have them.
    And some linux distributions are stuck with JDK 17.

    Otherwise its not an idea that belongs solely
    to Java, I think golang pioniered them with their
    goroutines. I am planning to use them more heavily

    when they become more widely available, and I don't
    see any principle objection that Python wouldn't
    have them as well. It would make async I/O based

    on async waithing for a thread maybe more lightweight.
    But this would be only important if you have a high
    number of tasks.

    Lawrence D'Oliveiro schrieb:
    Short answer: no.

    <https://discuss.python.org/t/add-virtual-threads-to-python/91403>

    Firstly, anybody appealing to Java as an example of how to design a programming language should immediately be sending your bullshit detector into the yellow zone.

    Secondly, the link to a critique of JavaScript that dates from 2015, from before the language acquired its async/await constructs, should be another warning sign.

    Looking at that Java spec, a “virtual thread” is just another name for “stackful coroutine”. Because that’s what you get when you take away implicit thread preemption and substitute explicit preemption instead.

    The continuation concept is useful in its own right. Why not concentrate
    on implementing that as a new primitive instead?


    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paul Rubin on Sat Jun 14 23:10:55 2025
    On Sat, 14 Jun 2025 04:29:07 -0700, Paul Rubin wrote:

    Try using Erlang a little, It has preemptive lightweight processes and
    it is great. Much better than async/await imho.

    Those are called “threads”. Python already has those, and the ongoing “noGIL” project will make them even more useful.

    There’s a reason why the old coroutine concept was brought back (albeit in this new “stackless” guise): because threads are not the best answer to everything.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lawrence D'Oliveiro on Sat Jun 14 18:25:26 2025
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    Try using Erlang a little, It has preemptive lightweight processes and
    it is great. Much better than async/await imho.

    Those are called “threads”. Python already has those, and the ongoing “noGIL” project will make them even more useful.

    Erlang's lightweight processes are called "processes" rather than
    "threads" since they don't give the appearance of having shared memory.
    They communicate by passing data through channels. From the
    application's perspective, that is always done by copying the data,
    although the VM sometimes optimizes away the copying behind the scenes.

    Python has OS threads but they are way more expensive than Erlang
    processes. Programming with them in an Erlang-like style still can work
    pretty well.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paul Rubin on Sun Jun 15 02:13:33 2025
    On Sat, 14 Jun 2025 18:25:26 -0700, Paul Rubin wrote:

    Erlang's lightweight processes are called "processes" rather than
    "threads" since they don't give the appearance of having shared memory.
    They communicate by passing data through channels. From the
    application's perspective, that is always done by copying the data,
    although the VM sometimes optimizes away the copying behind the scenes.

    Python has OS threads but they are way more expensive than Erlang
    processes.

    Sharing process context is cheaper than having to keep copying data back
    and forth. Clever tricks with the paging hardware can often be more
    trouble than they’re worth.

    Remember, Python’s threads are OS threads. If you’re thinking “expensive”,
    you must be assuming “Microsoft Windows”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lawrence D'Oliveiro on Sun Jun 15 13:24:56 2025
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    Remember, Python’s threads are OS threads. If you’re thinking “expensive”,
    you must be assuming “Microsoft Windows”.

    Let's see how CPython holds up with a million OS threads running. Even
    being able to disable the GIL and use more than one core is very recent.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paul Rubin on Sun Jun 15 20:59:43 2025
    On Sun, 15 Jun 2025 13:24:56 -0700, Paul Rubin wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    Remember, Python’s threads are OS threads. If you’re thinking
    “expensive”, you must be assuming “Microsoft Windows”.

    Let's see how CPython holds up with a million OS threads running.

    Linux can already run hundreds of thousands of processes/threads (there’s
    not a lot of difference between the two on Linux). Remember why pid_t is
    32 bits, not 16 bits.

    See the definition of /proc/sys/kernel/threads-max <https://manpages.debian.org/proc_sys_kernel(5)>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lawrence D'Oliveiro on Sun Jun 15 14:33:28 2025
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    Let's see how CPython holds up with a million OS threads running.
    Linux can already run hundreds of thousands of processes/threads

    To misquote Austin Powers, "one MILLLLLION threads". Here Erlang
    does it in less than 1GB of memory:

    https://hauleth.dev/post/beam-process-memory-usage/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paul Rubin on Mon Jun 16 01:14:34 2025
    On Sun, 15 Jun 2025 14:33:28 -0700, Paul Rubin wrote:

    Lawrence D'Oliveiro <ldo@nz.invalid> writes:

    Let's see how CPython holds up with a million OS threads running.

    Linux can already run hundreds of thousands of processes/threads

    To misquote Austin Powers, "one MILLLLLION threads". Here Erlang does
    it in less than 1GB of memory:

    https://hauleth.dev/post/beam-process-memory-usage/

    Just a note that Erlang dates from before the current state of CPU architectures, where you have a 100:1 disparity between RAM-access speeds
    and CPU register-access speeds.

    In other words, you do not want to copy stuff between processes if you can
    help it. With threads sharing common memory, that data can reside in
    caches that multiple threads in the same process context can share without copying.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Paul Rubin@21:1/5 to Lawrence D'Oliveiro on Sun Jun 15 21:02:46 2025
    Lawrence D'Oliveiro <ldo@nz.invalid> writes:
    In other words, you do not want to copy stuff between processes if you can help it.

    I'd be interested in seeing some benchmarks of multi-threaded Python
    beating Erlang, if you have any to show. Otherwise, you are guessing.
    Stuff copied between Erlang processes tends to be pretty small, fwiw.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Paul Rubin on Tue Jun 17 02:12:03 2025
    On Sun, 15 Jun 2025 21:02:46 -0700, Paul Rubin wrote:

    I'd be interested in seeing some benchmarks of multi-threaded Python
    beating Erlang, if you have any to show.

    Since you ask, I tried running up a simple program that creates lots of
    dummy threads that do nothing but sleep for a few seconds, and reports on
    its RAM usage by reading /proc/self/statm.

    I am currently up to a bit over 25,000 threads (the default limit is
    somewhere just under 26,000). The program reports its VM usage as over
    200GB, which is way more than my total RAM + swap space, but in fact the free(1) command reports that RAM and swap usage are nowhere that high. The resident RAM usage while all the threads are running is reported at about 430MB.

    In other words, multiply that by 40, and a million threads should get the program’s RAM usage up to maybe 18GB.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to Mild Shock on Mon Jun 23 13:29:09 2025
    Hi,

    async I/O in Python is extremly disappointing
    and an annoying bottleneck.

    The problem is async I/O via threads is currently
    extremly slow. I use a custom async I/O file property
    predicate. It doesn't need to be async for file

    system access. But by some historical circumstances
    I made it async since the same file property routine
    might also do a http HEAD request. But what I was

    testing and comparing was a simple file system access
    inside a wrapped thread, that is async awaited.
    Such a thread is called for a couple of directory

    entries to check a directory tree whether updates
    are need. Here some measurement doing this simple
    involving some little async I/O:

    node.js: 10 ms (usual Promises and stuff)
    JDK 24: 50 ms (using Threads, not yet VirtualThreads)
    pypy: 2000 ms

    So currently PyPy is 200x times slower than node.js
    when it comes to async I/O. No files were read or
    written in the test case, only "mtime" was read,

    via this Python line:

    stats = await asyncio.to_thread(os.stat, url)

    Bye

    Mild Shock schrieb:

    Concerning virtual threads the only problem
    with Java I have is, that JDK 17 doesn't have them.
    And some linux distributions are stuck with JDK 17.

    Otherwise its not an idea that belongs solely
    to Java, I think golang pioniered them with their
    goroutines. I am planning to use them more heavily

    when they become more widely available, and I don't
    see any principle objection that Python wouldn't
    have them as well. It would make async I/O based

    on async waithing for a thread maybe more lightweight.
    But this would be only important if you have a high
    number of tasks.

    Lawrence D'Oliveiro schrieb:
    Short answer: no.

    <https://discuss.python.org/t/add-virtual-threads-to-python/91403>

    Firstly, anybody appealing to Java as an example of how to design a
    programming language should immediately be sending your bullshit detector
    into the yellow zone.

    Secondly, the link to a critique of JavaScript that dates from 2015, from
    before the language acquired its async/await constructs, should be
    another
    warning sign.

    Looking at that Java spec, a “virtual thread” is just another name for >> “stackful coroutine”. Because that’s what you get when you take away >> implicit thread preemption and substitute explicit preemption instead.

    The continuation concept is useful in its own right. Why not concentrate
    on implementing that as a new primitive instead?



    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mild Shock@21:1/5 to Mild Shock on Tue Jun 24 00:32:26 2025
    So what does:

    stats = await asyncio.to_thread(os.stat, url)

    Whell it calls in a sparate new secondary thread:

    os.stat(url)

    It happends that url is only a file path, and
    the file path points to an existing file. So the
    secondary thread computs the stats, and terminates,

    and the async framework hands the stats back to
    the main thread that did the await, and the main
    thread stops his waiting and continues to run

    cooperatively with the other tasks in the current
    event loop. The test case measures the wall time.
    The results are:

    node.js: 10 ms (usual Promises and stuff)
    JDK 24: 50 ms (using Threads, not yet VirtualThreads)
    pypy: 2000 ms

    I am only using one main task, sequentially on
    such await calles, with a couple of file, not
    more than 50 files.

    I could compare with removing the async detour,
    to qualify the async I/O detour overhead.

    Mild Shock schrieb:
    Hi,

    async I/O in Python is extremly disappointing
    and an annoying bottleneck.

    The problem is async I/O via threads is currently
    extremly slow. I use a custom async I/O file property
    predicate. It doesn't need to be async for file

    system access. But by some historical circumstances
    I made it async since the same file property routine
    might also do a http HEAD request. But what I was

    testing and comparing was a simple file system access
    inside a wrapped thread, that is async awaited.
    Such a thread is called for a couple of directory

    entries to check a directory tree whether updates
    are need. Here some measurement doing this simple
    involving some little async I/O:

    node.js: 10 ms (usual Promises and stuff)
    JDK 24: 50 ms (using Threads, not yet VirtualThreads)
    pypy: 2000 ms

    So currently PyPy is 200x times slower than node.js
    when it comes to async I/O. No files were read or
    written in the test case, only "mtime" was read,

    via this Python line:

    stats = await asyncio.to_thread(os.stat, url)

    Bye

    Mild Shock schrieb:

    Concerning virtual threads the only problem
    with Java I have is, that JDK 17 doesn't have them.
    And some linux distributions are stuck with JDK 17.

    Otherwise its not an idea that belongs solely
    to Java, I think golang pioniered them with their
    goroutines. I am planning to use them more heavily

    when they become more widely available, and I don't
    see any principle objection that Python wouldn't
    have them as well. It would make async I/O based

    on async waithing for a thread maybe more lightweight.
    But this would be only important if you have a high
    number of tasks.

    Lawrence D'Oliveiro schrieb:
    Short answer: no.

    <https://discuss.python.org/t/add-virtual-threads-to-python/91403>

    Firstly, anybody appealing to Java as an example of how to design a
    programming language should immediately be sending your bullshit
    detector
    into the yellow zone.

    Secondly, the link to a critique of JavaScript that dates from 2015,
    from
    before the language acquired its async/await constructs, should be
    another
    warning sign.

    Looking at that Java spec, a “virtual thread” is just another name for >>> “stackful coroutine”. Because that’s what you get when you take away >>> implicit thread preemption and substitute explicit preemption instead.

    The continuation concept is useful in its own right. Why not concentrate >>> on implementing that as a new primitive instead?




    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)