• Re: Request for comments, async ISO core standard I/O

    From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Feb 22 11:18:20 2024
    From Newsgroup: comp.lang.prolog

    Now asyncifying I/O of Dogelog Player for Python.
    I guess we got our head around the equivalents
    of our Java Surrogate async/await constructs

    "Promise" and "Coroutine". The key utilities among
    asyncio are asyncio.to_thread an asyncio.run_coroutine_threadsafe,
    which seem toe especially made for the two use cases.

    Namely what was our Java Surrogate "Promise" wrapper,
    now looks like here, what a wonderful code gem:


    async def console_promise(buf, stream):
    try:
    res = await asyncio.to_thread(blocking_readline, stream.data)
    stream.buf = res
    stream.pos = 0
    except IOError as err:
    register_signal(buf, map_stream_error(err))


    def blocking_readline(data):
    return data.readline()


    And what was our Java Surrogate "Coroutine" wrapper,
    now looks like here, what a wonderful code gem again:

    def test_sys_http_server_on(args):
    [...]
    obj.func = lambda req, res: baby_come_back(
    launch_async(clause, buf, [req, res]), loop)


    def baby_come_back(coro, loop):
    future = asyncio.run_coroutine_threadsafe(coro, loop)
    return future.result()

    LoL
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Thu Feb 22 11:26:34 2024
    From Newsgroup: comp.lang.prolog

    But its much more complicated than what we did
    for JDK 21. Also starting the HTTP server in a separate
    thread is extremly frightening:


    def test_http_server_listen(args):
    [...]
    thread = threading.Thread(target=blocking_forever, args=(obj,))
    thread.start()


    def blocking_forever(obj):
    obj.serve_forever()


    Its extremly frightening since the Thread docu warns us:

    Thread-based parallelism
    In CPython, due to the Global Interpreter Lock,
    only one thread can execute Python code at once https://docs.python.org/3/library/threading.html

    global interpreter lock
    Also, the GIL is always released when doing I/O.
    Past efforts to create a “free-threaded” interpreter
    have not been successful https://docs.python.org/3/glossary.html#term-global-interpreter-lock

    But still, our use of asyncio.to_thread and
    asyncio.run_coroutine_threadsafe capitalizes on
    that the GIL is nevertheless released during I/O,

    and we don't see much issue here.

    Mild Shock schrieb:
    Now asyncifying I/O of Dogelog Player for Python.
    I guess we got our head around the equivalents
    of our Java Surrogate async/await constructs

    "Promise" and "Coroutine". The key utilities among
    asyncio are asyncio.to_thread an asyncio.run_coroutine_threadsafe,
    which seem toe especially made for the two use cases.

    Namely what was our Java Surrogate "Promise" wrapper,
    now looks like here, what a wonderful code gem:


    async def console_promise(buf, stream):
        try:
            res = await asyncio.to_thread(blocking_readline, stream.data)
            stream.buf = res
            stream.pos = 0
        except IOError as err:
            register_signal(buf, map_stream_error(err))


    def blocking_readline(data):
        return data.readline()


    And what was our Java Surrogate "Coroutine" wrapper,
    now looks like here, what a wonderful code gem again:

    def test_sys_http_server_on(args):
       [...]
        obj.func = lambda req, res: baby_come_back(
                launch_async(clause, buf, [req, res]), loop)


    def baby_come_back(coro, loop):
        future = asyncio.run_coroutine_threadsafe(coro, loop)
        return future.result()

    LoL

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@bursejan@gmail.com to comp.lang.prolog on Thu Feb 22 03:49:59 2024
    From Newsgroup: comp.lang.prolog

    Conclusions so far:
    Super fast Phyton makes you bald, loose your protein
    filaments that grow from follicles found in your head dermis. https://www.linkedin.com/in/jasonbrownlee/
    Why? Because there is no super fast Python. By default
    the Python byte code cannot use multiple cores!
    Mild Shock schrieb am Donnerstag, 22. Februar 2024 um 11:26:37 UTC+1:
    But its much more complicated than what we did
    for JDK 21. Also starting the HTTP server in a separate
    thread is extremly frightening:


    def test_http_server_listen(args):
    [...]
    thread = threading.Thread(target=blocking_forever, args=(obj,)) thread.start()


    def blocking_forever(obj):
    obj.serve_forever()


    Its extremly frightening since the Thread docu warns us:

    Thread-based parallelism
    In CPython, due to the Global Interpreter Lock,
    only one thread can execute Python code at once https://docs.python.org/3/library/threading.html

    global interpreter lock
    Also, the GIL is always released when doing I/O.
    Past efforts to create a “free-threaded” interpreter
    have not been successful https://docs.python.org/3/glossary.html#term-global-interpreter-lock

    But still, our use of asyncio.to_thread and
    asyncio.run_coroutine_threadsafe capitalizes on
    that the GIL is nevertheless released during I/O,

    and we don't see much issue here.

    Mild Shock schrieb:
    Now asyncifying I/O of Dogelog Player for Python.
    I guess we got our head around the equivalents
    of our Java Surrogate async/await constructs

    "Promise" and "Coroutine". The key utilities among
    asyncio are asyncio.to_thread an asyncio.run_coroutine_threadsafe,
    which seem toe especially made for the two use cases.

    Namely what was our Java Surrogate "Promise" wrapper,
    now looks like here, what a wonderful code gem:


    async def console_promise(buf, stream):
    try:
    res = await asyncio.to_thread(blocking_readline, stream.data)
    stream.buf = res
    stream.pos = 0
    except IOError as err:
    register_signal(buf, map_stream_error(err))


    def blocking_readline(data):
    return data.readline()


    And what was our Java Surrogate "Coroutine" wrapper,
    now looks like here, what a wonderful code gem again:

    def test_sys_http_server_on(args):
    [...]
    obj.func = lambda req, res: baby_come_back(
    launch_async(clause, buf, [req, res]), loop)


    def baby_come_back(coro, loop):
    future = asyncio.run_coroutine_threadsafe(coro, loop)
    return future.result()

    LoL
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Tue Mar 5 15:08:31 2024
    From Newsgroup: comp.lang.prolog

    Ha Ha, now Scyer Prolog wants also
    byte friendly compact strings:

    2. introduce a compact internal representation for lists of bytes,
    which appear to Prolog programs as lists of characters. https://github.com/mthom/scryer-prolog/blob/master/src/lib/crypto.pl#L867C2-L868C63

    But they motivated it by security concerns,
    whereas my concern was to get rid of ISO-ism
    making a distinction between text and byte streams,

    on the Prolog API levels. It would be all codes.

    Mostowski Collapse schrieb:
    - UTF-16 native strings: Does work well with the envisioned
    "latin1" payload, the range 0..255 is encoded in one 16-bit word,
    which is two bytes, but most programming language already
    implement clever strings:

    JEP 254: Compact Strings
    We propose to change the internal representation of the String class
    from a UTF-16 char array to a byte array plus an encoding-flag field.
    The new String class will store characters encoded either as ISO-8859-1/ Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate
    which encoding is used.
    https://openjdk.org/jeps/254

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Mar 16 01:29:02 2024
    From Newsgroup: comp.lang.prolog

    Now I have rewritten the Tic-Tac-Toe example
    to be 100% Prolog. Originally the Tic-Tac-Toe example
    was conceived as a first stab in exploring the

    foreign function interface (FFI) of Dogelog Player
    inside the browser to register JavaScript functions
    that do all kind of stuff with the DOM and events.

    But now I have library(markup) for DOM generation
    and library(react) for events. So I rewrote Tic-Tac-Toe
    using these utilities, reducing the amount of

    JavaScript logic to zero. Tic-Tac-Toe is now 100% Prolog.
    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Mar 16 01:39:50 2024
    From Newsgroup: comp.lang.prolog


    What also went down the drain abusing consult_async()
    to do the game intialization, instead I am now using
    perform_async(). So the code went from dangerous.

    await consult_async(":- ensure_loaded('browser.p').");

    dangerous because of possible file name quoting issues.
    To this where the file name is a string object and doesn't
    need to be Prolog encoded, because we don't invoke a Prolog

    text encoded query but a Prolog term:

    await perform_async(new Compound("ensure_loaded", ["browser.p"]));

    In has far we should make some Hydration experiment.
    What is Hydration. Its a new buzzword around the partially
    obsolete design, to have first the HTML body in a broswer

    doument and then at the end of the HTML body some scripts:

    r/webdev - What is Hydration? https://www.reddit.com/r/webdev/comments/xqd4i8/what_is_hydration/

    The bundle end of HTML body design has usually takes
    time time(html)+time(bundle). A better deisgn is unsing
    async loading and the quasi-parallelism of the browser,

    and load the bundle in the head if possible. The load time
    is then around max(time(bundle), time(html))). which might
    give better user experience. We should try the same

    for our examples, load Dogelog Player in the head. But
    the Prolog text loader is not yet task safe. So this might
    involve some more work until we can try it.

    Also we might nevertheless want to do a little hydration
    when the HTML body is read, like wiring event handlers.

    Mild Shock schrieb:
    Now I have rewritten the Tic-Tac-Toe example
    to be 100% Prolog. Originally the Tic-Tac-Toe example
    was conceived as a first stab in exploring the

    foreign function interface (FFI) of Dogelog Player
    inside the browser to register JavaScript functions
    that do all kind of stuff with the DOM and events.

    But now I have library(markup) for DOM generation
    and library(react) for events. So I rewrote Tic-Tac-Toe
    using these utilities, reducing the amount of

    JavaScript logic to zero. Tic-Tac-Toe is now 100% Prolog.

    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Mar 16 01:48:44 2024
    From Newsgroup: comp.lang.prolog


    Note because of the await in front of the
    perform_async() our loading doesn't create a task yet.
    It will change the current load sequence. It will

    only allow that tasks create before the await get
    their share of work. We would need to add one of our
    create_task utilities, or use the async option of a

    script tag, as recommened here for MathJax v3:

    /* put this in the head */
    <script type="text/javascript" id="MathJax-script" async
    src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
    </script>

    The async option of a script tag is described as:

    "For module scripts, if the async attribute is
    present then the scripts and all their dependencies
    will be fetched in parallel to parsing and evaluated
    as soon as they are available." https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async

    Mild Shock schrieb:

    What also went down the drain abusing consult_async()
    to do the game intialization, instead I am now using
    perform_async(). So the code went from dangerous.

        await consult_async(":- ensure_loaded('browser.p').");

    dangerous because of possible file name quoting issues.
    To this where the file name is a string object and doesn't
    need to be Prolog encoded, because we don't invoke a Prolog

    text encoded query but a Prolog term:

        await perform_async(new Compound("ensure_loaded", ["browser.p"]));

    In has far we should make some Hydration experiment.
    What is Hydration. Its a new buzzword around the partially
    obsolete design, to have first the HTML body in a broswer

    doument and then at the end of the HTML body some scripts:

    r/webdev - What is Hydration? https://www.reddit.com/r/webdev/comments/xqd4i8/what_is_hydration/

    The bundle end of HTML body design has usually takes
    time time(html)+time(bundle). A better deisgn is unsing
    async loading and the quasi-parallelism of the browser,

    and load the bundle in the head if possible. The load time
    is then around max(time(bundle), time(html))). which might
    give better user experience. We should try the same

    for our examples, load Dogelog Player in the head. But
    the Prolog text loader is not yet task safe. So this might
    involve some more work until we can try it.

    Also we might nevertheless want to do a little hydration
    when the HTML body is read, like wiring event handlers.

    Mild Shock schrieb:
    Now I have rewritten the Tic-Tac-Toe example
    to be 100% Prolog. Originally the Tic-Tac-Toe example
    was conceived as a first stab in exploring the

    foreign function interface (FFI) of Dogelog Player
    inside the browser to register JavaScript functions
    that do all kind of stuff with the DOM and events.

    But now I have library(markup) for DOM generation
    and library(react) for events. So I rewrote Tic-Tac-Toe
    using these utilities, reducing the amount of

    JavaScript logic to zero. Tic-Tac-Toe is now 100% Prolog.


    --- Synchronet 3.20a-Linux NewsLink 1.114
  • From Mild Shock@janburse@fastmail.fm to comp.lang.prolog on Sat Mar 16 01:53:08 2024
    From Newsgroup: comp.lang.prolog

    Corr. Typo

    It will NOT change the current load sequence.

    Mild Shock schrieb:

    Note because of the await in front of the
    perform_async() our loading doesn't create a task yet.
    It will change the current load sequence. It will

    only allow that tasks create before the await get
    their share of work. We would need to add one of our
    create_task utilities, or use the async option of a

    script tag, as recommened here for MathJax v3:

    /* put this in the head */
    <script type="text/javascript" id="MathJax-script" async
      src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js">
    </script>

    The async option of a script tag is described as:

    "For module scripts, if the async attribute is
    present then the scripts and all their dependencies
    will be fetched in parallel to parsing and evaluated
    as soon as they are available." https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script#async

    Mild Shock schrieb:

    What also went down the drain abusing consult_async()
    to do the game intialization, instead I am now using
    perform_async(). So the code went from dangerous.

         await consult_async(":- ensure_loaded('browser.p').");

    dangerous because of possible file name quoting issues.
    To this where the file name is a string object and doesn't
    need to be Prolog encoded, because we don't invoke a Prolog

    text encoded query but a Prolog term:

         await perform_async(new Compound("ensure_loaded", ["browser.p"])); >>
    In has far we should make some Hydration experiment.
    What is Hydration. Its a new buzzword around the partially
    obsolete design, to have first the HTML body in a broswer

    doument and then at the end of the HTML body some scripts:

    r/webdev - What is Hydration?
    https://www.reddit.com/r/webdev/comments/xqd4i8/what_is_hydration/

    The bundle end of HTML body design has usually takes
    time time(html)+time(bundle). A better deisgn is unsing
    async loading and the quasi-parallelism of the browser,

    and load the bundle in the head if possible. The load time
    is then around max(time(bundle), time(html))). which might
    give better user experience. We should try the same

    for our examples, load Dogelog Player in the head. But
    the Prolog text loader is not yet task safe. So this might
    involve some more work until we can try it.

    Also we might nevertheless want to do a little hydration
    when the HTML body is read, like wiring event handlers.

    Mild Shock schrieb:
    Now I have rewritten the Tic-Tac-Toe example
    to be 100% Prolog. Originally the Tic-Tac-Toe example
    was conceived as a first stab in exploring the

    foreign function interface (FFI) of Dogelog Player
    inside the browser to register JavaScript functions
    that do all kind of stuff with the DOM and events.

    But now I have library(markup) for DOM generation
    and library(react) for events. So I rewrote Tic-Tac-Toe
    using these utilities, reducing the amount of

    JavaScript logic to zero. Tic-Tac-Toe is now 100% Prolog.



    --- Synchronet 3.20a-Linux NewsLink 1.114