• Apache + mod_php performance

    From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Tue Sep 24 14:28:05 2024
    I am not impressed by Apache + mod_php performance on VMS.

    The basic numbers I see (simple PHP code for getting some data
    out of a MySQL database and displaying) are:

    Apache + CGI : 4 req/sec = 240 req/min
    Apache + mod_php : 11 req/sec = 660 req/min
    Tomcat + Quercus : 127 req/sec = 7620 req/min

    (VMS x86-64 9.2-2, Apache 2.4-58, Berryman PHP 8.1,
    Java 8u372, Tomcat 8.5-89, Quercus 4.0)

    That CGI is slow is no surprise. Using CGI for performance
    is like doing 100 meter crawl dressed in medieval armor.

    But I had expected much better numbers for mod_php. Instead
    of the actual x2.5 and x10 I had expected like x10 and x2.5
    between the three.

    Anyone having any ideas for why it is like this and what
    can be done about it?

    Arne

    PS: And before anyone jump at the great Quercus numbers - yes
    Quercus is a very nice product, but Resin stopped development
    many years ago and it is stuck at PHP 5.x - so it is only
    a solution for DIY PHP 5.x code not a solution for any
    recent version of common MVC frameworks like Lareval.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Tue Sep 24 21:09:25 2024
    In article <vcv0bl$39mnj$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    The basic numbers I see (simple PHP code for getting some data
    out of a MySQL database and displaying) are:

    Apache + CGI : 4 req/sec = 240 req/min
    Apache + mod_php : 11 req/sec = 660 req/min
    Tomcat + Quercus : 127 req/sec = 7620 req/min

    (VMS x86-64 9.2-2, Apache 2.4-58, Berryman PHP 8.1,
    Java 8u372, Tomcat 8.5-89, Quercus 4.0)

    That CGI is slow is no surprise. Using CGI for performance
    is like doing 100 meter crawl dressed in medieval armor.

    But I had expected much better numbers for mod_php. Instead
    of the actual x2.5 and x10 I had expected like x10 and x2.5
    between the three.

    Anyone having any ideas for why it is like this and what
    can be done about it?

    Did you try running your test script under the PHP interpreter
    directly, without the web stack? What kind of QPS numbers do
    you see if it's just PHP talking to MySQL?

    With no further details, I'd wonder if you're not caching
    connections to the database between queries.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Sep 24 21:28:39 2024
    On Tue, 24 Sep 2024 14:28:05 -0400, Arne Vajhøj wrote:

    I am not impressed by Apache + mod_php performance on VMS.

    I recall that Apache offers a choice of worker processes or worker
    threads. I suspect mod_php is not thread-safe, so you have to use multiple worker processes. And process creation on VMS is expensive.

    I wonder how Nginx deals with this: I don’t think it can load the Apache- specific mod_php, so it offloads PHP to a separate process and uses
    “reverse proxying” (actually server-side proxying) instead.

    Server-side proxying is the way to go, anyway: I use it for my Python code
    now. It lets you manage your own process context, create your own subprocesses/threads/tasks ... whatever you want.

    And I can use WebSockets as well, which PHP has trouble supporting.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Tue Sep 24 20:24:42 2024
    On 9/24/2024 5:28 PM, Lawrence D'Oliveiro wrote:
    On Tue, 24 Sep 2024 14:28:05 -0400, Arne Vajhøj wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    I recall that Apache offers a choice of worker processes or worker
    threads. I suspect mod_php is not thread-safe, so you have to use multiple worker processes. And process creation on VMS is expensive.

    Apache on VMS starts multiple processes. But they should
    be reusable (otherwise it would be CGI reimplemented). The
    client test app use 20 threads, so Apache should
    only need to start 20 child processes and let them
    process requests. So even though process creation indeed
    is expensive on VMS, then it should not kill performance
    like what I see.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Tue Sep 24 20:53:22 2024
    On 9/24/2024 5:09 PM, Dan Cross wrote:
    In article <vcv0bl$39mnj$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    The basic numbers I see (simple PHP code for getting some data
    out of a MySQL database and displaying) are:

    Apache + CGI : 4 req/sec = 240 req/min
    Apache + mod_php : 11 req/sec = 660 req/min
    Tomcat + Quercus : 127 req/sec = 7620 req/min

    (VMS x86-64 9.2-2, Apache 2.4-58, Berryman PHP 8.1,
    Java 8u372, Tomcat 8.5-89, Quercus 4.0)

    That CGI is slow is no surprise. Using CGI for performance
    is like doing 100 meter crawl dressed in medieval armor.

    But I had expected much better numbers for mod_php. Instead
    of the actual x2.5 and x10 I had expected like x10 and x2.5
    between the three.

    Anyone having any ideas for why it is like this and what
    can be done about it?

    Did you try running your test script under the PHP interpreter
    directly, without the web stack? What kind of QPS numbers do
    you see if it's just PHP talking to MySQL?

    Just executing the same PHP code in a loop give much higher
    performance.

    Single process : 158 executions per second = 9480 executions per minute

    And multi process could probably get significantly higher.

    With no further details, I'd wonder if you're not caching
    connections to the database between queries.

    Does not matter.

    I just found out that Tomcat+Quercus numbers get even higher
    after some warmup.

    no db con pool db con pool
    Apache + CGI 4 N/A
    Apache + mod_php 11 11
    Tomcat + Quercus 208 214

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Sep 25 12:25:20 2024
    On 2024-09-24, Arne Vajhj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.


    Is the PHP FPM option available to you on VMS ?

    https://www.php.net/manual/en/install.fpm.php

    If it is, be aware that .htaccess no longer works to control PHP when
    it is in FPM mode and you need to use .user.ini files instead:

    https://www.php.net/manual/en/configuration.file.per-user.php

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Sep 25 12:48:46 2024
    In article <vcvmu1$3cnv1$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/24/2024 5:09 PM, Dan Cross wrote:
    In article <vcv0bl$39mnj$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    The basic numbers I see (simple PHP code for getting some data
    out of a MySQL database and displaying) are:

    Apache + CGI : 4 req/sec = 240 req/min
    Apache + mod_php : 11 req/sec = 660 req/min
    Tomcat + Quercus : 127 req/sec = 7620 req/min

    (VMS x86-64 9.2-2, Apache 2.4-58, Berryman PHP 8.1,
    Java 8u372, Tomcat 8.5-89, Quercus 4.0)

    That CGI is slow is no surprise. Using CGI for performance
    is like doing 100 meter crawl dressed in medieval armor.

    But I had expected much better numbers for mod_php. Instead
    of the actual x2.5 and x10 I had expected like x10 and x2.5
    between the three.

    Anyone having any ideas for why it is like this and what
    can be done about it?

    Did you try running your test script under the PHP interpreter
    directly, without the web stack? What kind of QPS numbers do
    you see if it's just PHP talking to MySQL?

    Just executing the same PHP code in a loop give much higher
    performance.

    Single process : 158 executions per second = 9480 executions per minute

    And multi process could probably get significantly higher.

    So this suggests that your PHP code, by itself, is not the
    bottleneck, though it remains unclear to me what you mean when
    you say, "just executing the same PHP code in a loop...": does
    this mean that you're running the PHP interpreter itself in a
    loop? As in, starting it fresh on every iteration? Or does
    this mean that you've got a loop inside the PHP program that
    runs your test and you're measuring the throughput of that? And
    is this standalone, or executed under the web framework? That
    is, are you running this under Apache and hitting some query
    that then causes the PHP interpreter to repeatedly query the
    database?

    With no further details, I'd wonder if you're not caching
    connections to the database between queries.

    Does not matter.

    Surely it does. If, for whatever reason, you're not holding
    onto the connection to the database between queries, but rather, re-establishing it each time, that will obviously have overhead
    that will impact performance.

    Or perhaps you're saying this because of some unstated
    assumption alluded to in the questions above?

    I just found out that Tomcat+Quercus numbers get even higher
    after some warmup.

    no db con pool db con pool
    Apache + CGI 4 N/A
    Apache + mod_php 11 11
    Tomcat + Quercus 208 214

    That's nice, but that seems irrelevant to the question of why
    PHP under Apache is so slow.

    Perhaps a simpler question: what sort of throughput does Apache
    on VMS give you if you just hit a simple static resource
    repeatedly?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Sep 25 09:24:06 2024
    On 9/25/2024 8:25 AM, Simon Clubley wrote:
    On 2024-09-24, Arne Vajhøj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    Is the PHP FPM option available to you on VMS ?

    I don't see anything in neither Apache or PHP to
    indicate so.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Sep 25 11:49:13 2024
    On 9/25/2024 8:48 AM, Dan Cross wrote:
    In article <vcvmu1$3cnv1$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/24/2024 5:09 PM, Dan Cross wrote:
    In article <vcv0bl$39mnj$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    I am not impressed by Apache + mod_php performance on VMS.

    The basic numbers I see (simple PHP code for getting some data
    out of a MySQL database and displaying) are:

    Apache + CGI : 4 req/sec = 240 req/min
    Apache + mod_php : 11 req/sec = 660 req/min
    Tomcat + Quercus : 127 req/sec = 7620 req/min

    (VMS x86-64 9.2-2, Apache 2.4-58, Berryman PHP 8.1,
    Java 8u372, Tomcat 8.5-89, Quercus 4.0)

    That CGI is slow is no surprise. Using CGI for performance
    is like doing 100 meter crawl dressed in medieval armor.

    But I had expected much better numbers for mod_php. Instead
    of the actual x2.5 and x10 I had expected like x10 and x2.5
    between the three.

    Anyone having any ideas for why it is like this and what
    can be done about it?

    Did you try running your test script under the PHP interpreter
    directly, without the web stack? What kind of QPS numbers do
    you see if it's just PHP talking to MySQL?

    Just executing the same PHP code in a loop give much higher
    performance.

    Single process : 158 executions per second = 9480 executions per minute

    And multi process could probably get significantly higher.

    So this suggests that your PHP code, by itself, is not the
    bottleneck,

    The PHP code is very simple: read 3 rows from a database table
    and output 35 lines of HTML.

    though it remains unclear to me what you mean when
    you say, "just executing the same PHP code in a loop...": does
    this mean that you're running the PHP interpreter itself in a
    loop? As in, starting it fresh on every iteration? Or does
    this mean that you've got a loop inside the PHP program that
    runs your test and you're measuring the throughput of that? And
    is this standalone, or executed under the web framework? That
    is, are you running this under Apache and hitting some query
    that then causes the PHP interpreter to repeatedly query the
    database?

    PHP script with a loop executing the same code as the web
    request inside the loop. PHP script run command line.
    No Apache or mod_php involved.

    With no further details, I'd wonder if you're not caching
    connections to the database between queries.

    Does not matter.

    Surely it does. If, for whatever reason, you're not holding
    onto the connection to the database between queries, but rather, re-establishing it each time, that will obviously have overhead
    that will impact performance.

    Or perhaps you're saying this because of some unstated
    assumption alluded to in the questions above?

    I am saying this because the numbers were the same. 11 req/sec
    in both cases.

    I just found out that Tomcat+Quercus numbers get even higher
    after some warmup.

    no db con pool db con pool
    Apache + CGI 4 N/A
    Apache + mod_php 11 11
    Tomcat + Quercus 208 214

    That's nice, but that seems irrelevant to the question of why
    PHP under Apache is so slow.

    You brought up the topic, so I tested.

    Perhaps a simpler question: what sort of throughput does Apache
    on VMS give you if you just hit a simple static resource
    repeatedly?

    Now it becomes interesting.

    nop.php also gives 11 req/sec.

    And nop.txt also gives 11 req/sec.

    So the arrow is definitely pointing towards Apache.

    So either something to speed up Apache or switching to WASD or OSU.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Sep 25 18:41:17 2024
    In article <vd1bdp$3npm3$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 8:48 AM, Dan Cross wrote:
    [snip]
    Just executing the same PHP code in a loop give much higher
    performance.

    Single process : 158 executions per second = 9480 executions per minute

    And multi process could probably get significantly higher.

    So this suggests that your PHP code, by itself, is not the
    bottleneck,

    The PHP code is very simple: read 3 rows from a database table
    and output 35 lines of HTML.

    though it remains unclear to me what you mean when
    you say, "just executing the same PHP code in a loop...": does
    this mean that you're running the PHP interpreter itself in a
    loop? As in, starting it fresh on every iteration? Or does
    this mean that you've got a loop inside the PHP program that
    runs your test and you're measuring the throughput of that? And
    is this standalone, or executed under the web framework? That
    is, are you running this under Apache and hitting some query
    that then causes the PHP interpreter to repeatedly query the
    database?

    PHP script with a loop executing the same code as the web
    request inside the loop. PHP script run command line.
    No Apache or mod_php involved.

    So PHP talking to your database seems fine, then.

    With no further details, I'd wonder if you're not caching
    connections to the database between queries.

    Does not matter.

    Surely it does. If, for whatever reason, you're not holding
    onto the connection to the database between queries, but rather,
    re-establishing it each time, that will obviously have overhead
    that will impact performance.

    Or perhaps you're saying this because of some unstated
    assumption alluded to in the questions above?

    I am saying this because the numbers were the same. 11 req/sec
    in both cases.

    Oh, I see what you mean now. That was a statement of fact based
    on your findings, not an assertion. Sorry, I missed your "db
    con pool" numbers in your previous post.

    I just found out that Tomcat+Quercus numbers get even higher
    after some warmup.

    no db con pool db con pool
    Apache + CGI 4 N/A
    Apache + mod_php 11 11
    Tomcat + Quercus 208 214

    That's nice, but that seems irrelevant to the question of why
    PHP under Apache is so slow.

    You brought up the topic, so I tested.

    Hmm, I just went back and looked at the thread, and I don't see
    where I asked about Tomcat/Quercus.

    Perhaps a simpler question: what sort of throughput does Apache
    on VMS give you if you just hit a simple static resource
    repeatedly?

    Now it becomes interesting.

    nop.php also gives 11 req/sec.

    And nop.txt also gives 11 req/sec.

    So the arrow is definitely pointing towards Apache.

    I should think so. Lesson #1: always verify your base
    assumptions when investigating something like this.

    So either something to speed up Apache or switching to WASD or OSU.

    Well, the question now becomes, "what makes Apache so slow?"

    I would concentrate on your nop.txt test; I assume that's a
    small (possibly empty) text file and as an example has the
    fewest number of variables.

    Do your logs give any indications of what might be going on?
    For example, do the logs have host names in them, possibly
    implying your stalling on reverse DNS lookups or something
    similar?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Sep 25 17:10:43 2024
    On 9/25/2024 2:41 PM, Dan Cross wrote:
    In article <vd1bdp$3npm3$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 8:48 AM, Dan Cross wrote:
    Perhaps a simpler question: what sort of throughput does Apache
    on VMS give you if you just hit a simple static resource
    repeatedly?

    Now it becomes interesting.

    nop.php also gives 11 req/sec.

    And nop.txt also gives 11 req/sec.

    So the arrow is definitely pointing towards Apache.

    I should think so. Lesson #1: always verify your base
    assumptions when investigating something like this.

    So either something to speed up Apache or switching to WASD or OSU.

    Well, the question now becomes, "what makes Apache so slow?"

    I would concentrate on your nop.txt test; I assume that's a
    small (possibly empty) text file and as an example has the
    fewest number of variables.

    Do your logs give any indications of what might be going on?
    For example, do the logs have host names in them, possibly
    implying your stalling on reverse DNS lookups or something
    similar?

    Just logging IP address.

    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Sep 25 17:22:18 2024
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    But the system did not like further increases.

    And in case someone wonders what "did not like" means:

    $ anal/crash

    OpenVMS system dump analyzer
    ...analyzing an x86-64 interleaved memory dump...

    %SDA-W-DUMPINCOMPL, the dump file write was not completed
    %SDA-I-LMBEMPTY, empty "Non-Key Global Pages" LMB in file #1 at VBN 000006DE %SDA-W-NOTSAVED, some processes not found in dump file
    Dump taken on 25-SEP-2024 15:27:12.64 using version V9.2-2
    RESEXH, Resources exhausted, system shutting down

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Sep 25 17:17:32 2024
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    Apache on VMS is prefork MPM. Yuck.

    Which puzzles me.

    VMS is a threading OS not a forking OS.

    And prefork MPM is really an early 90's traditional Unix design.

    Using worker MPM on VMS would make more sense IMHO.

    The best would probably have been to create a VMS MPM
    based on the WinNT MPM.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Sep 25 21:49:22 2024
    On Wed, 25 Sep 2024 17:17:32 -0400, Arne Vajhøj wrote:

    Using worker MPM on VMS would make more sense IMHO.

    Server-side proxy is the way to go.

    The suggestion to use PHP-FPM is basically along these lines, except that
    the whole FastCGI protocol is IMHO best considered “legacy” at this point. Proxying (or “reverse proxying”, if you prefer) makes use of standard
    HTTP, and easily supports extras like WebSocket connections.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Sep 25 19:14:58 2024
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    Does anyone know internals of Apache on VMS?

    Based on some messages in error_log it looks like
    it uses mailboxes APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between
    master process and a child process, then that could
    slow down things.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Sep 25 19:10:34 2024
    On 9/25/2024 6:24 PM, Lawrence D'Oliveiro wrote:
    On Wed, 25 Sep 2024 17:17:32 -0400, Arne Vajhøj wrote:
    Using worker MPM on VMS would make more sense IMHO.

    According to the docs
    <https://httpd.apache.org/docs/2.4/mod/worker.html>, this is a hybrid multithread/multiprocess model.

    Yes. And I think that would fit better with VMS.

    But threading won’t work with PHP, because mod_php isn’t threadsafe.

    The worker MPM works fine with PHP.

    Two different ways:
    A) Build mod_php and PHP extensions thread safe
    B) Use fcgi or fpm

    Option #A is common on Windows.

    Option #B is common on Linux.

    I think #A would fit better with VMS.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Sep 25 22:24:43 2024
    On Wed, 25 Sep 2024 17:17:32 -0400, Arne Vajhøj wrote:

    Using worker MPM on VMS would make more sense IMHO.

    According to the docs
    <https://httpd.apache.org/docs/2.4/mod/worker.html>, this is a hybrid multithread/multiprocess model. But threading won’t work with PHP, because mod_php isn’t threadsafe.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Sep 26 00:21:26 2024
    On Wed, 25 Sep 2024 19:10:34 -0400, Arne Vajhøj wrote:

    The worker MPM works fine with PHP.

    Two different ways:
    A) Build mod_php and PHP extensions thread safe
    B) Use fcgi or fpm

    Option #A is common on Windows.

    Option #B is common on Linux.

    I think #A would fit better with VMS.

    I don’t think the Windows option is known for good performance. Just
    saying ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Sep 25 20:57:44 2024
    On 9/25/2024 8:20 PM, Lawrence D'Oliveiro wrote:
    On Wed, 25 Sep 2024 19:14:58 -0400, Arne Vajhøj wrote:

    Based on some messages in error_log it looks like it uses mailboxes
    APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between master process and a
    child process, then that could slow down things.

    I also wonder about the difference in handling nondeterministic communication.

    On *nix systems, you have poll/select (also other options like epoll or kqueue, depending on the *nix variant) for monitoring multiple
    communication channels at once, and all your files/pipes/sockets are
    treated as byte streams.

    On VMS, you have to have async QIO calls pending on every channel that you want to monitor, and all the communication channels are treated as record- oriented.

    I don't recognize that.

    On VMS you can use select if using the socket API and
    IO$_SETMODE|IO$M_READATTN if using $QIO(W) API.

    And both socket API and $QIO(W) API are stream oriented.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Sep 26 00:20:23 2024
    On Wed, 25 Sep 2024 19:14:58 -0400, Arne Vajhøj wrote:

    Based on some messages in error_log it looks like it uses mailboxes APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between master process and a
    child process, then that could slow down things.

    I also wonder about the difference in handling nondeterministic
    communication.

    On *nix systems, you have poll/select (also other options like epoll or
    kqueue, depending on the *nix variant) for monitoring multiple
    communication channels at once, and all your files/pipes/sockets are
    treated as byte streams.

    On VMS, you have to have async QIO calls pending on every channel that you
    want to monitor, and all the communication channels are treated as record- oriented.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Sep 26 01:52:57 2024
    On Wed, 25 Sep 2024 20:57:44 -0400, Arne Vajhøj wrote:

    On VMS you can use select if using the socket API and IO$_SETMODE|IO$M_READATTN if using $QIO(W) API.

    That sends an AST to tell you there is something to read. Extra mechanism overhead.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to All on Thu Sep 26 07:38:35 2024
    On 9/25/24 6:14 PM, Arne Vajhøj wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    Does anyone know internals of Apache on VMS?

    Based on some messages in error_log it looks like
    it uses mailboxes APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between
    master process and a child process, then that could
    slow down things.

    I vaguely remember that there was a separate image installed with
    privileges that increased socket buffer size from 255 bytes to something reasonable and these sockets were used as pipes for IPC.

    The following links still seem to work if you want (old) sources:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-ALPHA-SRC-KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-I64-SRC-KIT.BCK_SFX_I64EXE

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Craig A. Berry on Thu Sep 26 09:30:04 2024
    On 9/26/24 7:38 AM, Craig A. Berry wrote:

    On 9/25/24 6:14 PM, Arne Vajhøj wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    Does anyone know internals of Apache on VMS?

    Based on some messages in error_log it looks like
    it uses mailboxes APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between
    master process and a child process, then that could
    slow down things.

    I vaguely remember that there was a separate image installed with
    privileges that increased socket buffer size from 255 bytes to something reasonable and these sockets were used as pipes for IPC.

    The following links still seem to work if you want (old) sources:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-ALPHA-SRC-KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-I64-SRC-KIT.BCK_SFX_I64EXE


    Trial and error shows that *slightly* later versions are available at
    the same place:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-ALPHA-SRC-KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-I64-SRC-KIT.BCK_SFX_I64EXE

    Dunno why VSI doesn't release source code for their v2.4 port.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to All on Thu Sep 26 09:44:14 2024
    On 9/25/24 4:17 PM, Arne Vajhøj wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    Apache on VMS is prefork MPM. Yuck.

    Which puzzles me.

    VMS is a threading OS not a forking OS.

    Preforking in Apache just means it creates subprocesses at start-up
    time. Whoever invented the term apparently thought fork() was the only
    way to create a subprocess. On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    And prefork MPM is really an early 90's traditional Unix design.

    Using worker MPM on VMS would make more sense IMHO.

    That requires everything running in each MPM process to be thread-safe.
    It also probably doesn't provide the scaling advantages on VMS that it
    would on unixen because there is no pthread_sigsetmask: all signals are delivered in the main thread. Which means that somewhere around where
    threads could provide a scaling advantage, the main thread will get
    saturated and the advantage disappears. This based on the assumption
    that signals would be used for things like asynchronous I/O completion;
    I don't really know that for sure, but it seems like a pretty safe
    assumption.

    The best would probably have been to create a VMS MPM
    based on the WinNT MPM.

    And all of the Apache extensions would have to be rewritten to use QIOs
    and ASTs? That's a pretty big ask.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Thu Sep 26 10:55:00 2024
    On 9/26/2024 10:44 AM, Craig A. Berry wrote:
    On 9/25/24 4:17 PM, Arne Vajhøj wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    Apache on VMS is prefork MPM. Yuck.

    Which puzzles me.

    VMS is a threading OS not a forking OS.

    Preforking in Apache just means it creates subprocesses at start-up
    time.  Whoever invented the term apparently thought fork() was the only
    way to create a subprocess.  On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    Yes. But they behave different from fork.

    And prefork MPM is really an early 90's traditional Unix design.

    Using worker MPM on VMS would make more sense IMHO.

    That requires everything running in each MPM process to be thread-safe.
    It also probably doesn't provide the scaling advantages on VMS that it
    would on unixen because there is no pthread_sigsetmask: all signals are delivered in the main thread. Which means that somewhere around where
    threads could provide a scaling advantage, the main thread will get
    saturated and the advantage disappears. This based on the assumption
    that signals would be used for things like asynchronous I/O completion;
    I don't really know that for sure, but it seems like a pretty safe assumption.

    Well - the threaded PHP engine that does run on VMS (Tomcat + Quercus)
    performs much better, so I am optimistic. I am pretty sure that the
    Java RT use standard socket IO and pthreads, so it must be possible
    to achieve the same numbers in C.

    The best would probably have been to create a VMS MPM
    based on the WinNT MPM.

    And all of the Apache extensions would have to be rewritten to use QIOs
    and ASTs?  That's a pretty big ask.

    Why would extensions require being rewritten to use QIO's and
    AST's?

    Thread safe IO does not require those.

    And most extensions are already available in a thread safe
    version. Obviously no guarantee that it will build unchanged
    on VMS, but ...

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Craig A. Berry on Thu Sep 26 16:59:57 2024
    On 26/09/2024 15:30, Craig A. Berry wrote:
    On 9/26/24 7:38 AM, Craig A. Berry wrote:

    The following links still seem to work if you want (old) sources:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-ALPHA-SRC-KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-I64-SRC-KIT.BCK_SFX_I64EXE >>

    Trial and error shows that *slightly* later versions are available at
    the same place:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-ALPHA-SRC-KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-I64-SRC-KIT.BCK_SFX_I64EXE

    Dunno why VSI doesn't release source code for their v2.4 port.


    ISTR that for all the VSI versions of opensource that requires source to
    be available, they say they do not publish, will release source on
    request. Not sure how we request, or if there will be any caveats...

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Thu Sep 26 15:44:51 2024
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 2:41 PM, Dan Cross wrote:
    In article <vd1bdp$3npm3$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 8:48 AM, Dan Cross wrote:
    Perhaps a simpler question: what sort of throughput does Apache
    on VMS give you if you just hit a simple static resource
    repeatedly?

    Now it becomes interesting.

    nop.php also gives 11 req/sec.

    And nop.txt also gives 11 req/sec.

    So the arrow is definitely pointing towards Apache.

    I should think so. Lesson #1: always verify your base
    assumptions when investigating something like this.

    So either something to speed up Apache or switching to WASD or OSU.

    Well, the question now becomes, "what makes Apache so slow?"

    I would concentrate on your nop.txt test; I assume that's a
    small (possibly empty) text file and as an example has the
    fewest number of variables.

    Do your logs give any indications of what might be going on?
    For example, do the logs have host names in them, possibly
    implying your stalling on reverse DNS lookups or something
    similar?

    Just logging IP address.

    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Chris Townley on Thu Sep 26 12:35:35 2024
    On 9/26/2024 11:59 AM, Chris Townley wrote:
    On 26/09/2024 15:30, Craig A. Berry wrote:
    On 9/26/24 7:38 AM, Craig A. Berry wrote:
    The following links still seem to work if you want (old) sources:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-ALPHA-SRC-
    KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-I64-SRC-
    KIT.BCK_SFX_I64EXE


    Trial and error shows that *slightly* later versions are available at
    the same place:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-ALPHA-SRC-
    KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-I64-SRC-
    KIT.BCK_SFX_I64EXE

    Dunno why VSI doesn't release source code for their v2.4 port.

    ISTR that for all the VSI versions of opensource that requires source to
    be available, they say they do not publish, will release source on
    request. Not sure how we request, or if there will be any caveats...

    (they have published some: https://github.com/vmssoftware)

    Apache httpd is under Apache license, which does not make such
    requirement.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Craig A. Berry on Thu Sep 26 20:40:03 2024
    On Thu, 26 Sep 2024 09:44:14 -0500, Craig A. Berry wrote:

    Whoever invented the term apparently thought fork() was the only
    way to create a subprocess.

    It is the most natural way in this case, because it creates a complete
    copy of the parent process, which is what you want.

    On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    Not only is that more expensive, it also requires additional setup to
    recreate the effect of fork(2).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sat Sep 28 09:12:53 2024
    On 9/28/2024 1:07 AM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 22:27:30 -0400, Arne Vajhøj wrote:
    On 9/27/2024 10:18 PM, Arne Vajhøj wrote:
    On 9/27/2024 10:03 PM, Lawrence D'Oliveiro wrote:
    Facebook, for example, has billions of active users. And Facebook uses >>>> MySQL.

    FaceBook have a lot of MySQL/MariaDB servers. Sharded! :-)

    Also note that FaceBook are using a rather customized version. RocksDB
    as storage engine not normal InnoDB.
    And they have done some stuff to manage failover and replication (Raft
    based??).

    And being Open Source, they can do that kind of thing.

    Yes.

    They even developed their own PHP implementation, HHVM, which they have open-sourced.

    Note that:

    very old versions of HHVM: support PHP
    old versions of HHVM: support PHP and Hack
    recent versions of HHVM: support Hack

    Hack being what Facebook thought PHP 7.x should have been.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sat Sep 28 09:26:51 2024
    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:
    SQLServer is used at a few high volume places like MS own Office 365 web
    and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Sat Sep 28 10:52:46 2024
    On 9/27/2024 8:07 PM, Arne Vajhøj wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    It is a bug in the code.

    Comment in httpd.conf say:

    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.

    It does not say that it will reduce throughput to 1/10'th if on.

    Note that the problem may not impact anyone in
    the real world.

    I am simulating thousands of independent users using keep alive
    with a single simulator not using keep alive.

    It could very well be the case that the problem only arise for
    the simulator and not for the real users.

    Still weird though.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to All on Sat Sep 28 16:21:43 2024
    On 28/09/2024 14:26, Arne Vajhøj wrote:

    I wonder if it was used as part of that London Stock Exchange system that
    imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Arne


    and the NYSE outage last year was due to Berkshire Hathaway A shares
    being valued too nigh!

    Mind they fixed in hours

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Sat Sep 28 15:51:59 2024
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    Hmm. You had already said that you were _Not_ using keep alives
    because that would somehow mimic multiple machines querying
    simultaneously.

    That is correct.

    The client was not using keep alive.

    But the server was configured to support keep alive.

    Turning that capability off on the server solved the performance
    problem.

    No changes on client.

    No keep alive used before - no keep alive used after.

    Just disabling the capability on the server.

    This was, of course, the area of investigation I had suggested
    to you previously to try and nail down the baseline. I question
    whether this will impact your single query latency, however, or
    whether this is masking it in your benchmark.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    What is your single query latency? Not calculated, but
    actually measured.

    It is a rather uninteresting number.

    But easy to test. It obviously vary a bit, but they
    are all in the 50-100 millisecond range.

    It is a bug in the code.

    The evidence in hand is insufficient to make that claim.

    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Arne


    Feature ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 21:33:49 2024
    On Sat, 28 Sep 2024 09:26:51 -0400, Arne Vajhøj wrote:

    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:

    SQLServer is used at a few high volume places like MS own Office 365
    web and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system
    that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Not exactly a recommendation for mission-critical use, is it?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sat Sep 28 19:11:52 2024
    On 9/28/2024 5:33 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 09:26:51 -0400, Arne Vajhøj wrote:
    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:
    SQLServer is used at a few high volume places like MS own Office 365
    web and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system
    that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Not exactly a recommendation for mission-critical use, is it?

    The solution did not work well - it went down several times
    when load were extraordinary high.

    But it has never been documented exactly what the problem was.

    SQLServer vs another RDBMS (most likely Oracle DB or IBM DB2) does
    not make my top 6 of guesses. SQLServer was a rather mature
    product at the time (partly due to Sybase heritage).

    My top 6 guesses would be:

    1) Implementation team consisting of general consultants
    without domain expertise doing a poor job implementing.
    2) The choice of a relative new technology at the time .NET
    for implementation - the version is not known, but
    the system went into production in 2007, so most
    likely the project was started with .NET 1.1 (2003) and
    not .NET 2.0 (2005) - new stuff and critical systems
    is not a good combo because all bugs may not have been
    sorted out yet and peoples understanding of the new stuff
    may be limited
    3) Inadequate hardware to handle unexpected high peak load
    4) Decision to use GC language and RDBMS for something that
    is let us call it soft real time
    5) Other bad architectural decisions
    6) Network issues - just because that was what LSE actually claimed

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Sat Sep 28 20:55:37 2024
    On 9/28/2024 8:50 PM, Arne Vajhøj wrote:
    With KeepAlive On then we have a performance problem.

    The cause is that worker processes are unavailable while
    waiting for next request from client even though client is
    long gone.

    That indicates that the cap is:

    max throughput (req/sec) = MaxClients / KeepAliveTimeout

    The formula holds for low resulting throughput but it does
    not scale and seems to be more like 1/3 of that for higher
    resulting throughput.

    But if one wants keep alive enabled, then it is something one
    can work with.

    My experiments indicate that:

    KeepAlive On
    KeepAliveTimeout 15 -> 1
    MaxSpareServers 50 -> 300
    MaxClients 150 -> 300

    is almost acceptable.

    nop.txt : 100 req/sec

    MaxSpareServers increase is necessary to improve numbers. It seems
    like without that then Apache spend too much time killings childs
    when not needed and starting them when needed (and process creation
    is expensive on VMS).

    Downside is obviously that all those processes are kept even
    if load is small for a long time.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Sat Sep 28 20:50:21 2024
    On 9/28/2024 10:52 AM, Arne Vajhøj wrote:
    On 9/27/2024 8:07 PM, Arne Vajhøj wrote:
    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    It is a bug in the code.

    Comment in httpd.conf say:

    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.

    It does not say that it will reduce throughput to 1/10'th if on.

    Note that the problem may not impact anyone in
    the real world.

    I am simulating thousands of independent users using keep alive
    with a single simulator not using keep alive.

    It could very well be the case that the problem only arise for
    the simulator and not for the real users.

    Still weird though.

    Another update.

    Client side can also impact keep alive.

    HTTP 1.0 : no problem
    HTTP 1.1 with "Connection: close" header : no problem
    HTTP 1.1 without "Connection: close" header : problem

    Server side:

    KeepAlive On -> Off

    solves the problem. But obviously has the drawback of loosing
    keep alive capability.

    Not a disaster. Back in the early 00's when prefork MPM was
    common, then KeepAlive Off was sometimes suggested for high
    volume sites. But inconvenient.

    With KeepAlive On then we have a performance problem.

    The cause is that worker processes are unavailable while
    waiting for next request from client even though client is
    long gone.

    That indicates that the cap is:

    max throughput (req/sec) = MaxClients / KeepAliveTimeout

    The formula holds for low resulting throughput but it does
    not scale and seems to be more like 1/3 of that for higher
    resulting throughput.

    But if one wants keep alive enabled, then it is something one
    can work with.

    My experiments indicate that:

    KeepAlive On
    KeepAliveTimeout 15 -> 1
    MaxSpareServers 50 -> 300
    MaxClients 150 -> 300

    is almost acceptable.

    nop.txt : 100 req/sec

    And 1 second should be more than enough for a browser to request
    additional assets within a static HTML page.

    But having hundreds of processes each using 25 MB for serving a 2 byte
    file at such a low throughput is ridiculous.

    OSU (or WASD) still seems as a better option.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sat Sep 28 21:31:22 2024
    On 9/28/2024 9:18 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 20:50:21 -0400, Arne Vajhøj wrote:
    The cause is that worker processes are unavailable while
    waiting for next request from client even though client is
    long gone.

    That shouldn’t matter, if the client closed the connection properly.

    It doesn't know the client closed connection.

    Also, why shouldn’t a worker handle a request for another client?

    This is singlethreaded all sync workers so when they wait for a new
    request from an existing client, then they can't handle a new
    client.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Sep 29 01:18:45 2024
    On Sat, 28 Sep 2024 20:50:21 -0400, Arne Vajhøj wrote:

    The cause is that worker processes are unavailable while
    waiting for next request from client even though client is
    long gone.

    That shouldn’t matter, if the client closed the connection properly.

    Also, why shouldn’t a worker handle a request for another client?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Sep 29 01:41:31 2024
    On Sat, 28 Sep 2024 21:31:22 -0400, Arne Vajhøj wrote:

    On 9/28/2024 9:18 PM, Lawrence D'Oliveiro wrote:

    On Sat, 28 Sep 2024 20:50:21 -0400, Arne Vajhøj wrote:

    The cause is that worker processes are unavailable while waiting for
    next request from client even though client is long gone.

    That shouldn’t matter, if the client closed the connection properly.

    It doesn't know the client closed connection.

    That would only happen if the client crashed.

    Note also that TLS connections require an explicit connection-closing
    exchange at the end, to guard against data-truncation attacks.

    Also, why shouldn’t a worker handle a request for another client?

    This is singlethreaded all sync workers so when they wait for a new
    request from an existing client, then they can't handle a new client.

    Why not? The whole point of fork(2) is that all the processes are
    effectively clones. If you put all the client context into shared memory sections, then it becomes possible for any process to service any client.

    Of course, I’m assuming that all the processes can share the same network socket connections. This might not be true under VMS ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sat Sep 28 22:35:07 2024
    On 9/28/2024 9:41 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 21:31:22 -0400, Arne Vajhøj wrote:
    On 9/28/2024 9:18 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 20:50:21 -0400, Arne Vajhøj wrote:
    The cause is that worker processes are unavailable while waiting for
    next request from client even though client is long gone.

    That shouldn’t matter, if the client closed the connection properly.

    It doesn't know the client closed connection.

    That would only happen if the client crashed.

    OK. Then it sounds like the client doesn't actually close the socket
    but just stop using it and move on to a new connection.

    I wonder why the HttpClient library does not do an actual close. But
    it may be the best simulation of a browser - the browser doesn't know
    if the user will want to view another page at the same site, so it
    probably don't close the socket.

    I also wonder why "Connection: close" header exist in request if the
    client could just close the socket. But doesn't change how things
    are.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Sep 29 03:38:19 2024
    On Sat, 28 Sep 2024 22:35:07 -0400, Arne Vajhøj wrote:

    On 9/28/2024 9:41 PM, Lawrence D'Oliveiro wrote:

    On Sat, 28 Sep 2024 21:31:22 -0400, Arne Vajhøj wrote:

    It doesn't know the client closed connection.

    That would only happen if the client crashed.

    OK. Then it sounds like the client doesn't actually close the socket
    but just stop using it and move on to a new connection.

    So your load simulator is buggy?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 10:46:12 2024
    On 9/28/2024 9:41 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 21:31:22 -0400, Arne Vajhøj wrote:
    On 9/28/2024 9:18 PM, Lawrence D'Oliveiro wrote:
    Also, why shouldn’t a worker handle a request for another client?

    This is singlethreaded all sync workers so when they wait for a new
    request from an existing client, then they can't handle a new client.

    Why not? The whole point of fork(2) is that all the processes are
    effectively clones. If you put all the client context into shared memory sections, then it becomes possible for any process to service any client.

    Of course, I’m assuming that all the processes can share the same network socket connections. This might not be true under VMS ...

    That is not how Apache prefork MPM works.

    It is not how the newer worker and event MPM's work either.

    The end state sounds more like how single process multi-thread
    works.

    And I don't understand the "put all the client context into
    shared memory" either. Are you saying that if socket descriptors
    are put in shared memory then any process that map that memory
    can use those sockets????

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Sun Sep 29 10:59:20 2024
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    And note that keep alive was not needed for me, but it is needed in many
    other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Actually, it's useful for any scenario in which you may send
    several requests to the same server at roughly the same time,
    such as an HTML document and separate CSS stylesheet, not just
    graphics or "server to server web services".

    There is no difference in how graphics and CSS are handled,
    so the benefits of reusing a connection is the same.

    But there is a difference in number of requests. CSS will typical
    be cached by the browser. So number of CSS requests will be a fraction
    of number of HTML requests, while pages with lots of graphics
    will have many graphics requests per HTML request.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 10:01:10 2024
    On 9/28/24 4:33 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 09:26:51 -0400, Arne Vajhøj wrote:

    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:

    SQLServer is used at a few high volume places like MS own Office 365
    web and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system
    that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Not exactly a recommendation for mission-critical use, is it?

    Saying SQL Server is a poor choice for anything based on one story about
    SQL 2000 is like saying you should never use a web browser because
    Netscape 1.0 had its problems. In the last 20+ years, Microsoft has
    made massive investments in improving SQL Server's performance and
    scalability, has ported it to Linux, and has added boatloads of new
    features. Whether it would be first choice for a trading system I don't
    know, but as Arne said, they run quite a bit of their own mission
    critical stuff on it.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Sun Sep 29 11:41:23 2024
    On 9/29/2024 11:01 AM, Craig A. Berry wrote:
    On 9/28/24 4:33 PM, Lawrence D'Oliveiro wrote:
    On Sat, 28 Sep 2024 09:26:51 -0400, Arne Vajhøj wrote:
    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:
    SQLServer is used at a few high volume places like MS own Office 365 >>>>> web and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system
    that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which was
    not a success) used SQLServer 2000 as database.

    Not exactly a recommendation for mission-critical use, is it?

    Saying SQL Server is a poor choice for anything based on one story about
    SQL 2000 is like saying you should never use a web browser because
    Netscape 1.0 had its problems.  In the last 20+ years, Microsoft has
    made massive investments in improving SQL Server's performance and scalability, has ported it to Linux, and has added boatloads of new features.  Whether it would be first choice for a trading system I don't know, but as Arne said, they run quite a bit of their own mission
    critical stuff on it.

    I consider SQLServer a very nice database. I love the ability to
    write CLR SP and UDF.

    But a Windows license + SQLServer license for a big box is
    not cheap.

    (and despite SQLServer being available for Linux then I believe Windows
    is still by far the most common)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Craig A. Berry on Sun Sep 29 23:08:47 2024
    On Sun, 29 Sep 2024 10:01:10 -0500, Craig A. Berry wrote:

    On 9/28/24 4:33 PM, Lawrence D'Oliveiro wrote:

    On Sat, 28 Sep 2024 09:26:51 -0400, Arne Vajhøj wrote:

    On 9/28/2024 1:08 AM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:

    SQLServer is used at a few high volume places like MS own Office 365 >>>>> web and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system
    that imploded so spectacularly?

    The TradElect system used by London Stock Exchange 2007-2011 (which
    was not a success) used SQLServer 2000 as database.

    Not exactly a recommendation for mission-critical use, is it?

    Saying SQL Server is a poor choice for anything based on one story about
    SQL 2000 is like saying you should never use a web browser because
    Netscape 1.0 had its problems. In the last 20+ years, Microsoft has
    made massive investments in improving SQL Server's performance and scalability, has ported it to Linux, and has added boatloads of new
    features.

    And yet the whole Windows Server thing is very definitely in its sunset
    years -- at least the on-prem version. Did Microsoft’s reputation ever recover from that screwup, especially after it made such a big, noisy deal about winning such an important contract against a Linux alternative in
    the first place? The “Highly Reliable Times” ad campaign, and all that self-serving bullshit?

    What was George C Scott’s line from “Dr Strangelove”:

    “I don’t think it’s quite fair to condemn a whole program because
    of a single slipup, sir.”

    Remember what the slipup was ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Sep 29 22:57:11 2024
    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:

    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more than one member of the worker pool?

    And I don't understand the "put all the client context into shared
    memory" either. Are you saying that if socket descriptors are put in
    shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table of
    socket descriptors in private per-process memory. If the process trying to server a client context does not actually have a socket descriptor in the
    slot for that context, it can ask for one.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 19:16:48 2024
    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:
    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more than one member of the worker pool?

    A new request on a new connection goes to another worker. No problem.

    And I don't understand the "put all the client context into shared
    memory" either. Are you saying that if socket descriptors are put in
    shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table of
    socket descriptors in private per-process memory. If the process trying to server a client context does not actually have a socket descriptor in the slot for that context, it can ask for one.

    I still can't follow the idea.

    Client X has a connection to server worker A. That means that A has
    index 77 in shared memory that points to the socket descriptor for
    the connection from X.

    Worker B wants to serve X as well and it get index 77 from shared
    memory. And then it does what?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sun Sep 29 23:43:01 2024
    On Sun, 29 Sep 2024 19:16:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:

    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more
    than one member of the worker pool?

    A new request on a new connection goes to another worker. No problem.

    But with keepalive, the request will come in on the existing connection.
    So you have to dedicate a worker process to each connection? That’s inefficient.

    And I don't understand the "put all the client context into shared
    memory" either. Are you saying that if socket descriptors are put in
    shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table of
    socket descriptors in private per-process memory. If the process trying
    to server a client context does not actually have a socket descriptor
    in the slot for that context, it can ask for one.

    I still can't follow the idea.

    Client X has a connection to server worker A. That means that A has
    index 77 in shared memory that points to the socket descriptor for the connection from X.

    Worker B wants to serve X as well and it get index 77 from shared
    memory. And then it does what?

    Looks up its entry in its process-private copy of the array that contains
    the socket descriptors, to see if it has its own valid fd for that socket.

    You would also want to associate a generation number with that socket
    entry, so you can detect that the client connection associated with the previous socket has been closed, so that client entry is in fact for a different client connection.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 20:02:59 2024
    On 9/29/2024 7:43 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 19:16:48 -0400, Arne Vajhøj wrote:
    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:
    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more
    than one member of the worker pool?

    A new request on a new connection goes to another worker. No problem.

    But with keepalive, the request will come in on the existing connection.
    So you have to dedicate a worker process to each connection? That’s inefficient.

    There is a reason that prefork MPM has been replaced by other
    MPM's.

    Worker and event MPM on Linux.

    WinNT MPM on Windows.

    And I don't understand the "put all the client context into shared
    memory" either. Are you saying that if socket descriptors are put in
    shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table of
    socket descriptors in private per-process memory. If the process trying
    to server a client context does not actually have a socket descriptor
    in the slot for that context, it can ask for one.

    I still can't follow the idea.

    Client X has a connection to server worker A. That means that A has
    index 77 in shared memory that points to the socket descriptor for the
    connection from X.

    Worker B wants to serve X as well and it get index 77 from shared
    memory. And then it does what?

    Looks up its entry in its process-private copy of the array that contains
    the socket descriptors, to see if it has its own valid fd for that socket.

    Yes. And if it does not then what?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Sep 30 01:21:54 2024
    On Sun, 29 Sep 2024 20:02:59 -0400, Arne Vajhøj wrote:

    On 9/29/2024 7:43 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 19:16:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:

    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more >>>> than one member of the worker pool?

    A new request on a new connection goes to another worker. No problem.

    But with keepalive, the request will come in on the existing
    connection. So you have to dedicate a worker process to each
    connection? That’s inefficient.

    There is a reason that prefork MPM has been replaced by other MPM's.

    No need. Threading inherently opens its own can of worms, which is why it
    is useful to keep the option of running multiple single-threaded
    processes.

    And I don't understand the "put all the client context into shared
    memory" either. Are you saying that if socket descriptors are put in >>>>> shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table
    of socket descriptors in private per-process memory. If the process
    trying to server a client context does not actually have a socket
    descriptor in the slot for that context, it can ask for one.

    I still can't follow the idea.

    Client X has a connection to server worker A. That means that A has
    index 77 in shared memory that points to the socket descriptor for the
    connection from X.

    Worker B wants to serve X as well and it get index 77 from shared
    memory. And then it does what?

    Looks up its entry in its process-private copy of the array that
    contains the socket descriptors, to see if it has its own valid fd for
    that socket.

    Yes. And if it does not then what?

    Then it asks another process for a copy of that socket descriptor. Perhaps there is one overall connection-management process that accepts all new connections; if not, another worker that has that socket can pass it
    along.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 21:41:25 2024
    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 20:02:59 -0400, Arne Vajhøj wrote:
    On 9/29/2024 7:43 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 19:16:48 -0400, Arne Vajhøj wrote:
    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:
    That is not how Apache prefork MPM works.

    If that’s not how it works, then how can you serve a client from more >>>>> than one member of the worker pool?

    A new request on a new connection goes to another worker. No problem.

    But with keepalive, the request will come in on the existing
    connection. So you have to dedicate a worker process to each
    connection? That’s inefficient.

    There is a reason that prefork MPM has been replaced by other MPM's.

    No need. Threading inherently opens its own can of worms, which is why it
    is useful to keep the option of running multiple single-threaded
    processes.

    It is still an option on Linux.

    But default is event.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Sep 30 01:46:47 2024
    On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:

    Then it asks another process for a copy of that socket descriptor.
    Perhaps there is one overall connection-management process that accepts
    all new connections; if not, another worker that has that socket can
    pass it along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    That’s not how you do it. You pass it with the SCM_RIGHTS ancillary-data option in Unix-family sockets
    <https://manpages.debian.org/7/unix.7.en.html>.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 21:42:48 2024
    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 20:02:59 -0400, Arne Vajhøj wrote:
    On 9/29/2024 7:43 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 19:16:48 -0400, Arne Vajhøj wrote:
    On 9/29/2024 6:57 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 10:46:12 -0400, Arne Vajhøj wrote:
    And I don't understand the "put all the client context into shared >>>>>> memory" either. Are you saying that if socket descriptors are put in >>>>>> shared memory then any process that map that memory can use those
    sockets????

    No, but the shared-memory context can contain an index into a table
    of socket descriptors in private per-process memory. If the process
    trying to server a client context does not actually have a socket
    descriptor in the slot for that context, it can ask for one.

    I still can't follow the idea.

    Client X has a connection to server worker A. That means that A has
    index 77 in shared memory that points to the socket descriptor for the >>>> connection from X.

    Worker B wants to serve X as well and it get index 77 from shared
    memory. And then it does what?

    Looks up its entry in its process-private copy of the array that
    contains the socket descriptors, to see if it has its own valid fd for
    that socket.

    Yes. And if it does not then what?

    Then it asks another process for a copy of that socket descriptor. Perhaps there is one overall connection-management process that accepts all new connections; if not, another worker that has that socket can pass it
    along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 22:10:23 2024
    On 9/28/2024 9:41 PM, Lawrence D'Oliveiro wrote:

    Of course, I’m assuming that all the processes can share the same network socket connections. This might not be true under VMS ...


    TCP/IP services for VMS allows a socket to be created with sharing. At least the docs claim that.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 21:58:45 2024
    On 9/29/2024 9:46 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:
    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:
    Then it asks another process for a copy of that socket descriptor.
    Perhaps there is one overall connection-management process that accepts
    all new connections; if not, another worker that has that socket can
    pass it along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    That’s not how you do it. You pass it with the SCM_RIGHTS ancillary-data option in Unix-family sockets
    <https://manpages.debian.org/7/unix.7.en.html>.

    Worker A has a AF_INET socket to client so what AF_UNIX socket does
    it pass to worker B?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Sep 30 02:03:30 2024
    On Sun, 29 Sep 2024 21:58:45 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:46 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:

    Then it asks another process for a copy of that socket descriptor.
    Perhaps there is one overall connection-management process that
    accepts all new connections; if not, another worker that has that
    socket can pass it along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    That’s not how you do it. You pass it with the SCM_RIGHTS
    ancillary-data option in Unix-family sockets
    <https://manpages.debian.org/7/unix.7.en.html>.

    Worker A has a AF_INET socket to client so what AF_UNIX socket does it
    pass to worker B?

    You can pass any FD (AF_INET socket, file, pipe, even another AF_UNIX
    socket) over an AF_UNIX socket.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Sun Sep 29 22:34:04 2024
    On 9/29/2024 10:03 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 21:58:45 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:46 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:

    Then it asks another process for a copy of that socket descriptor.
    Perhaps there is one overall connection-management process that
    accepts all new connections; if not, another worker that has that
    socket can pass it along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    That’s not how you do it. You pass it with the SCM_RIGHTS
    ancillary-data option in Unix-family sockets
    <https://manpages.debian.org/7/unix.7.en.html>.

    Worker A has a AF_INET socket to client so what AF_UNIX socket does it
    pass to worker B?

    You can pass any FD (AF_INET socket, file, pipe, even another AF_UNIX
    socket) over an AF_UNIX socket.

    Ah. Interesting. Very interesting.

    But I am pretty sure that it will not work on VMS.

    :-)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Mon Sep 30 03:15:47 2024
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:

    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use threads.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Sep 30 12:48:08 2024
    In article <vd7l3k$tgu3$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    Hmm. You had already said that you were _Not_ using keep alives
    because that would somehow mimic multiple machines querying
    simultaneously.

    That is correct.

    The client was not using keep alive.

    What protocol version was the client using, and what, exactly,
    _is_ the client? Was this some ersatz thing, or an actual load
    testing tool of some kind?

    But the server was configured to support keep alive.

    Keep alive is the default for HTTP/1.1 (and I presume later,
    though I haven't looked at HTTP/2 or HTTP/3 in much detail)
    unless explicitly disabled. KeepwAlive is optional in some
    implementations of HTTP/1.0.

    One wonders whether your client was using 1.1 and not sending a
    `Connection: close` header. Presumably the effect of that would
    be that the server sends the requested data and then blocks for
    some time waiting for another request, eventually closing the
    connection when no such request is quickly forthcoming. A 20
    second timeout is reasonable.

    Turning that capability off on the server solved the performance
    problem.

    No changes on client.

    No keep alive used before - no keep alive used after.

    Just disabling the capability on the server.

    While I believe you've observed these results, I still think you
    haven't sufficiently explored the problem. Here's a test that
    you may consider trying:

    1. Re-enable the keep-alive configuration option and restart the
    server.
    2. Use `telnet` or another command-line client of your choice to
    connect to the HTTP port on that server.
    3. Type, `GET /path/to/nop.txt HTTP/1.1`
    4. Hit return twice.

    What do you observe? How long does it take for data to be
    returned, and then what happens?

    This was, of course, the area of investigation I had suggested
    to you previously to try and nail down the baseline. I question
    whether this will impact your single query latency, however, or
    whether this is masking it in your benchmark.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    What is your single query latency? Not calculated, but
    actually measured.

    It is a rather uninteresting number.

    But easy to test. It obviously vary a bit, but they
    are all in the 50-100 millisecond range.

    See above.

    It is a bug in the code.

    The evidence in hand is insufficient to make that claim.

    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    See above. There are many unanswered questions about this, and
    about your experimental setup, that really ought to be addressed
    before you consider the space sufficiently explored to draw
    definitive conclusions.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Sep 30 12:50:48 2024
    In article <vdbq08$1pg2p$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    And note that keep alive was not needed for me, but it is needed in many >>> other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Actually, it's useful for any scenario in which you may send
    several requests to the same server at roughly the same time,
    such as an HTML document and separate CSS stylesheet, not just
    graphics or "server to server web services".

    There is no difference in how graphics and CSS are handled,
    so the benefits of reusing a connection is the same.

    But there is a difference in number of requests. CSS will typical
    be cached by the browser. So number of CSS requests will be a fraction
    of number of HTML requests, while pages with lots of graphics
    will have many graphics requests per HTML request.

    Why do you assume CSS will be cached and graphics will not?
    Your understanding of where re-using HTTP connections does not
    seem to be drawn from real-world experience.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Sep 30 12:56:35 2024
    In article <66f8a44c$0$716$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/28/2024 10:52 AM, Arne Vajhøj wrote:
    On 9/27/2024 8:07 PM, Arne Vajhøj wrote:
    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    It is a bug in the code.

    Comment in httpd.conf say:

    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.

    It does not say that it will reduce throughput to 1/10'th if on.

    Note that the problem may not impact anyone in
    the real world.

    I am simulating thousands of independent users using keep alive
    with a single simulator not using keep alive.

    It could very well be the case that the problem only arise for
    the simulator and not for the real users.

    Still weird though.

    Another update.

    Client side can also impact keep alive.

    HTTP 1.0 : no problem
    HTTP 1.1 with "Connection: close" header : no problem
    HTTP 1.1 without "Connection: close" header : problem

    Server side:

    KeepAlive On -> Off

    solves the problem. But obviously has the drawback of loosing
    keep alive capability.

    Well ... yes. That's how the protocol works. Keep-alive is the
    default with HTTP/1.1 unless you explicitly send
    `Connection: close`. See RFC 9112, section 9.3 for details.

    Not a disaster. Back in the early 00's when prefork MPM was
    common, then KeepAlive Off was sometimes suggested for high
    volume sites. But inconvenient.

    With KeepAlive On then we have a performance problem.

    Actually, sounds like the bug is in your client, which expects
    behavior at odds with that specified in the RFC.

    The cause is that worker processes are unavailable while
    waiting for next request from client even though client is
    long gone.

    That indicates that the cap is:

    max throughput (req/sec) = MaxClients / KeepAliveTimeout

    The formula holds for low resulting throughput but it does
    not scale and seems to be more like 1/3 of that for higher
    resulting throughput.

    But if one wants keep alive enabled, then it is something one
    can work with.

    My experiments indicate that:

    KeepAlive On
    KeepAliveTimeout 15 -> 1
    MaxSpareServers 50 -> 300
    MaxClients 150 -> 300

    is almost acceptable.

    nop.txt : 100 req/sec

    And 1 second should be more than enough for a browser to request
    additional assets within a static HTML page.

    But having hundreds of processes each using 25 MB for serving a 2 byte
    file at such a low throughput is ridiculous.

    OSU (or WASD) still seems as a better option.

    See above. Looks like the problem ended up being between the
    keyboard and the chair.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Mon Sep 30 19:50:38 2024
    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:
    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Mon Sep 30 20:07:00 2024
    On 9/30/2024 8:50 AM, Dan Cross wrote:
    In article <vdbq08$1pg2p$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    And note that keep alive was not needed for me, but it is needed in many >>>> other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Actually, it's useful for any scenario in which you may send
    several requests to the same server at roughly the same time,
    such as an HTML document and separate CSS stylesheet, not just
    graphics or "server to server web services".

    There is no difference in how graphics and CSS are handled,
    so the benefits of reusing a connection is the same.

    But there is a difference in number of requests. CSS will typical
    be cached by the browser. So number of CSS requests will be a fraction
    of number of HTML requests, while pages with lots of graphics
    will have many graphics requests per HTML request.

    Why do you assume CSS will be cached and graphics will not?

    Different usage patterns.

    CSS and JS libraries are usually identical among all
    pages at site or a section of a site (to give an identical
    look and feel and to make development easier).

    The graphics (photo, drawings or whatever) on a graphics heavy
    page is usually unique for the page.

    Users usually view several pages at a site or a section of
    a site in a session.

    So when the browser reach a page, then it is very likely that
    the CSS and JS are in the cache because they were fetched for
    a previous viewed page while it is unlikely that the graphics
    is in the cache.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Mon Sep 30 20:33:59 2024
    On 9/30/2024 8:24 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 19:50:38 -0400, Arne Vajhøj wrote:
    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:
    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use
    threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Threads require shared memory, though. Processes allow you to have a mix
    of shared and private data, plus the use of IPC mechanisms like message passing. This makes for a looser coupling, which better suits the way massively parallel systems are built.

    It is undeniable that multiple processes are more loosely coupled
    than multiple threads.

    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Oct 1 00:24:18 2024
    On Mon, 30 Sep 2024 19:50:38 -0400, Arne Vajhøj wrote:

    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:

    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use
    threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Threads require shared memory, though. Processes allow you to have a mix
    of shared and private data, plus the use of IPC mechanisms like message passing. This makes for a looser coupling, which better suits the way
    massively parallel systems are built.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Oct 1 00:41:35 2024
    On Mon, 30 Sep 2024 20:33:59 -0400, Arne Vajhøj wrote:

    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    In other words, VMS still lives in a past world where its kind of
    programming model worked fine, and has never adapted to the era of massive parallelism and serving thousands of concurrent client connections.

    (I can remember some benchmarks on NFS performance showing our VAX running
    VMS outperforming the Unix machines -- very disconcerting to some Unix
    fans in our Comp Sci department. Those days are long gone.)

    VMS is the very definition of a “legacy platform”. Is it worth using for new development? Doesn’t seem like it. Is there much point in porting old
    VMS code from Alpha or Itanium to x86? Seems that, technical-debt-wise,
    that is just treading water for a little longer, and prolonging the
    inevitable.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Mon Sep 30 20:48:53 2024
    On 9/30/2024 8:41 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:33:59 -0400, Arne Vajhøj wrote:
    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    In other words, VMS still lives in a past world where its kind of
    programming model worked fine, and has never adapted to the era of massive parallelism and serving thousands of concurrent client connections.

    More like VMS living in the future world.

    :-)

    The world is moving from forking processes to starting threads.

    As soon as Python are done getting rid of GIL then it will
    join the thread party!

    :-)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Mon Sep 30 21:10:51 2024
    On 9/30/2024 8:33 PM, Arne Vajhøj wrote:
    On 9/30/2024 8:24 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 19:50:38 -0400, Arne Vajhøj wrote:
    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:
    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use
    threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Threads require shared memory, though. Processes allow you to have a mix
    of shared and private data, plus the use of IPC mechanisms like message
    passing. This makes for a looser coupling, which better suits the way
    massively parallel systems are built.

    It is undeniable that multiple processes are more loosely coupled
    than multiple threads.

    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    Arne


    Well, now, that is a rather bold statement.

    Granted, starting up a new process involves some overhead.

    But it really depends upon the requirements. The more use out of a process once
    it is started, the better overall performance. If a group of worker processes is started once, then used for many tasks, then that overhead happens only once.
    Perhaps once a day, week, month, and even year. There are various communication methods available on VMS.

    In the end, it comes down to the requirements. An engineer must evaluate the task(s) and determine what methods will give adequate results.



    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Oct 1 01:36:12 2024
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhøj wrote:

    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even multithreaded
    GUIs. It was soon discovered that was not a great idea.

    Java, perhaps, embraced threads more than anybody: it made such heavy use
    of threads that it never even bothered to define a separate “lock” object type: instead, locking calls are built into the behaviour of every object!

    No other language copied that feature. Wonder why not?

    As soon as Python are done getting rid of GIL then it will
    join the thread party!

    We understand better what to use threads for these days. They are good for CPU-intensive tasks that are parallelizable, not so much for anything
    else. That CPU-intensive stuff is not something you would tend to do in
    Python itself anyway: for high performance, you would delegate those tasks
    to “extension modules” written in C or such compiled languages. The usual flow within the extension code is

    * Grab data from Python objects into some efficient native format
    * Free the GIL
    * Perform CPU-intensive tasks
    * Re-acquire the GIL
    * return results in Python objects

    That third step takes full advantage of multithreading, without having to
    worry about the strictures of the Python GIL.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Mon Sep 30 21:25:20 2024
    On 9/30/2024 9:10 PM, Dave Froble wrote:
    On 9/30/2024 8:33 PM, Arne Vajhøj wrote:
    On 9/30/2024 8:24 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 19:50:38 -0400, Arne Vajhøj wrote:
    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:
    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use
    threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Threads require shared memory, though. Processes allow you to have a mix >>> of shared and private data, plus the use of IPC mechanisms like message
    passing. This makes for a looser coupling, which better suits the way
    massively parallel systems are built.

    It is undeniable that multiple processes are more loosely coupled
    than multiple threads.

    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    Well, now, that is a rather bold statement.

    Sometimes I make such.

    :-)

    Granted, starting up a new process involves some overhead.

    But it really depends upon the requirements.  The more use out of a
    process once it is started, the better overall performance.  If a group
    of worker processes is started once, then used for many tasks, then that overhead happens only once.  Perhaps once a day, week, month, and even year.  There are various communication methods available on VMS.

    In the end, it comes down to the requirements.  An engineer must
    evaluate the task(s) and determine what methods will give adequate results.

    There are obviously a scale.

    But the Apache case is to start with 5 processes, start 145 new
    processes in a few seconds and then kill 140 again after maybe
    30-45 seconds. And repeat.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Mon Sep 30 21:49:33 2024
    On 9/30/2024 9:36 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhøj wrote:
    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even multithreaded GUIs. It was soon discovered that was not a great idea.

    Practically all GUI's are multi-threaded.

    At least a main thread and an event thread.

    Java, perhaps, embraced threads more than anybody: it made such heavy use
    of threads that it never even bothered to define a separate “lock” object type: instead, locking calls are built into the behaviour of every object!

    No other language copied that feature. Wonder why not?

    There is no data in the object itself for it.

    Java chose the syntax:

    o.xxxx()

    while .NET chose the syntax:

    Monitor.Xxxx(o)

    for this functionality.

    Different syntax but same functionality.

    I think the .NET syntax better explains what it does.

    But it is just syntax.

    As soon as Python are done getting rid of GIL then it will
    join the thread party!

    We understand better what to use threads for these days. They are good for CPU-intensive tasks that are parallelizable, not so much for anything
    else. That CPU-intensive stuff is not something you would tend to do in Python itself anyway: for high performance, you would delegate those tasks
    to “extension modules” written in C or such compiled languages. The usual flow within the extension code is

    * Grab data from Python objects into some efficient native format
    * Free the GIL
    * Perform CPU-intensive tasks
    * Re-acquire the GIL
    * return results in Python objects

    That third step takes full advantage of multithreading, without having to worry about the strictures of the Python GIL.

    Threading is also a very convenient programming model for IO.

    Blocking IO API's has some limits on scalability (like 500 threads
    per CPU core).

    But then there are various flavors of non-blocking API's.

    And then there are blocking looking but not blocking under
    the hood API's.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Oct 1 02:31:51 2024
    On Mon, 30 Sep 2024 21:49:33 -0400, Arne Vajhøj wrote:

    Practically all GUI's are multi-threaded.

    No, they are not. We use event loops nowadays. I know, because I have done
    GUI programming using things like GTK and direct X11 calls.

    Threading is also a very convenient programming model for IO.

    Unnecessary. That’s why we have poll/epoll, as already discussed in this,
    um, thread. If the performance bottleneck is in the I/O (or in a GUI,
    waiting for the user’s next action), then threading doesn’t buy you anything, and just adds potential for trouble.

    Blocking IO API's has some limits on scalability (like 500 threads per
    CPU core).

    Surely only one thread is necessary.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Dallman@21:1/5 to Simon Clubley on Tue Oct 1 13:23:00 2024
    In article <vdgp60$2nh73$1@dont-email.me>, clubley@remove_me.eisner.decus.org-Earth.UFP (Simon Clubley) wrote:

    No. In the GUIs I am aware of, the main GUI thread _is_ the event
    thread.

    On at least Android and iOS, developers are warned that if the GUI thread
    is unresponsive to events for more than a few seconds, the OS will assume
    that it has hung or is infinite looping, and will start popping up
    warnings and/or killing the application. The GUI thread is required to
    start other threads to do anything that may take significant time.

    These OSes consider the GUI to be the main thing of an application. Since
    they are very user-focused OSes, at least as much about emotional
    gratification as computing, this makes some sense.

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Tue Oct 1 12:16:00 2024
    On 2024-09-30, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 9/30/2024 9:36 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhj wrote:
    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even multithreaded
    GUIs. It was soon discovered that was not a great idea.

    Practically all GUI's are multi-threaded.


    No. The GUIs I know of (GTK, Android, etc) are all single threaded and any other threads which need to use the GUI need to queue a request on the GUI thread.

    For example, in Android, you can define a Handler on the GUI thread which receives messages from other threads:

    https://developer.android.com/reference/android/os/Handler

    I tend to use:

    https://developer.android.com/reference/android/os/Handler#sendMessage(android.os.Message)

    to send messages from the other threads to the GUI thread.

    At least a main thread and an event thread.


    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Tue Oct 1 13:02:32 2024
    In article <66fb3d25$0$717$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/30/2024 8:50 AM, Dan Cross wrote:
    In article <vdbq08$1pg2p$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    And note that keep alive was not needed for me, but it is needed in many >>>>> other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Actually, it's useful for any scenario in which you may send
    several requests to the same server at roughly the same time,
    such as an HTML document and separate CSS stylesheet, not just
    graphics or "server to server web services".

    There is no difference in how graphics and CSS are handled,
    so the benefits of reusing a connection is the same.

    But there is a difference in number of requests. CSS will typical
    be cached by the browser. So number of CSS requests will be a fraction
    of number of HTML requests, while pages with lots of graphics
    will have many graphics requests per HTML request.

    Why do you assume CSS will be cached and graphics will not?

    Different usage patterns.

    CSS and JS libraries are usually identical among all
    pages at site or a section of a site (to give an identical
    look and feel and to make development easier).

    The graphics (photo, drawings or whatever) on a graphics heavy
    page is usually unique for the page.

    You have an awful lot of assumptions doing a lot of heavy
    lifting for you there, all to justify avoiding using a default
    feature of the protocol. Sorry, I don't find that convincing.

    Users usually view several pages at a site or a section of
    a site in a session.

    So when the browser reach a page, then it is very likely that
    the CSS and JS are in the cache because they were fetched for
    a previous viewed page while it is unlikely that the graphics
    is in the cache.

    I don't think this reflects how modern web apps are actually
    authored.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to clubley@remove_me.eisner.decus.org- on Tue Oct 1 13:08:55 2024
    In article <vdgp60$2nh73$1@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
    On 2024-09-30, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 9/30/2024 9:36 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhj wrote:
    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even multithreaded >>> GUIs. It was soon discovered that was not a great idea.

    Practically all GUI's are multi-threaded.

    No. The GUIs I know of (GTK, Android, etc) are all single threaded and any >other threads which need to use the GUI need to queue a request on the GUI >thread.

    For example, in Android, you can define a Handler on the GUI thread which >receives messages from other threads:

    https://developer.android.com/reference/android/os/Handler

    I tend to use:

    https://developer.android.com/reference/android/os/Handler#sendMessage(android.os.Message)

    to send messages from the other threads to the GUI thread.

    At least a main thread and an event thread.


    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    Most modern applications, even graphical applications running on
    hosted systems, are multithreaded. Whether the programming
    model of the GUI library is multithreaded or not is another
    matter, but those things must be _capable_ of being used in a
    multithreaded environment, which means that they need to at
    least be able to participate in a locking protocol of some sort,
    etc. For example, the incoming event queue must have some sort
    of interlocking on it in order to be accessible from multiple
    threads, otherwise, how could other threads safely enqueue
    events to it?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to John Dallman on Tue Oct 1 17:52:59 2024
    On 2024-10-01, John Dallman <jgd@cix.co.uk> wrote:
    In article <vdgp60$2nh73$1@dont-email.me>, clubley@remove_me.eisner.decus.org-Earth.UFP (Simon Clubley) wrote:

    No. In the GUIs I am aware of, the main GUI thread _is_ the event
    thread.

    On at least Android and iOS, developers are warned that if the GUI thread
    is unresponsive to events for more than a few seconds, the OS will assume that it has hung or is infinite looping, and will start popping up
    warnings and/or killing the application. The GUI thread is required to
    start other threads to do anything that may take significant time.


    Exactly. And at least on Android (I don't know about iOS), those new
    threads have no direct access to the GUI, the GUI event queue, or its
    widgets. They have to post a message to the GUI thread, or communicate
    with the GUI thread in another way, and then let code running within
    the GUI thread update the GUI on its behalf.

    Note that the message queue mentioned above is NOT the GUI event queue.
    It is a generic Android message queue facility which is nothing to do
    with the GUI. Multiple threads can create their own message queues and
    receive messages from other threads. The messages are processed by a
    handler within the thread that is registered when the message queue is
    created.

    These OSes consider the GUI to be the main thing of an application. Since they are very user-focused OSes, at least as much about emotional gratification as computing, this makes some sense.


    The vendors have also seriously lost the plot with the decisions they
    are making with the new Android versions.

    I've just had to move to a new Android phone due to the turning off of
    3G here in the UK. I was very happy with my old phone even though it
    was quite limited in resources compared to the current phones.

    In particular, I could have multiple applications open in the background
    at the same time without them getting killed. Now, on the new phones,
    as soon as you let the screen power off, the background applications are
    now killed within a couple of minutes and are killed in a way that doesn't
    even allow them to save their state via the standard Android API. :-(

    This happens even when you allow the applications to have unrestricted
    battery usage and exclude them from memory cleaning. When you need a
    website like the following, the phone vendors have lost the plot:

    https://dontkillmyapp.com/

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to Dan Cross on Tue Oct 1 18:02:41 2024
    On 2024-10-01, Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    In article <vdgp60$2nh73$1@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:

    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    Most modern applications, even graphical applications running on
    hosted systems, are multithreaded. Whether the programming
    model of the GUI library is multithreaded or not is another
    matter, but those things must be _capable_ of being used in a
    multithreaded environment, which means that they need to at
    least be able to participate in a locking protocol of some sort,
    etc. For example, the incoming event queue must have some sort
    of interlocking on it in order to be accessible from multiple
    threads, otherwise, how could other threads safely enqueue
    events to it?


    They don't enqueue events to the GUI event queue itself (at least
    on the GUIs I am aware of). See my detailed response to John about
    Android and look at the link I posted earlier.

    Non-GUI threads on Android have no direct access to the GUI and they
    have to communicate with the GUI thread via some form of generic
    messaging and let code running within the GUI thread perform the GUI
    operations on their behalf.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From John Dallman@21:1/5 to Simon Clubley on Tue Oct 1 20:29:00 2024
    In article <vdhctr$2qrst$1@dont-email.me>, clubley@remove_me.eisner.decus.org-Earth.UFP (Simon Clubley) wrote:
    On 2024-10-01, John Dallman <jgd@cix.co.uk> wrote:
    On at least Android and iOS, developers are warned that if the
    GUI thread is unresponsive to events for more than a few seconds,
    the OS will assume that it has hung or is infinite looping, and
    will start popping up warnings and/or killing the application.
    The GUI thread is required to start other threads to do anything
    that may take significant time.

    Exactly. And at least on Android (I don't know about iOS), those new
    threads have no direct access to the GUI, the GUI event queue, or
    its widgets.

    From the documentation I was reading about Clang sanitizers in Xcode,
    other threads can access the GUI but should not. Apple created a special sanitizer to find them.

    John

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Tue Oct 1 19:45:47 2024
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Arne

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It is illustrative how OP immediately blamed the server, the
    least likely outcome, without sufficiently investigating and
    finding his own error.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to clubley@remove_me.eisner.decus.org- on Tue Oct 1 19:26:17 2024
    In article <vdhdg1$2qrst$2@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
    On 2024-10-01, Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    In article <vdgp60$2nh73$1@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:

    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    Most modern applications, even graphical applications running on
    hosted systems, are multithreaded. Whether the programming
    model of the GUI library is multithreaded or not is another
    matter, but those things must be _capable_ of being used in a
    multithreaded environment, which means that they need to at
    least be able to participate in a locking protocol of some sort,
    etc. For example, the incoming event queue must have some sort
    of interlocking on it in order to be accessible from multiple
    threads, otherwise, how could other threads safely enqueue
    events to it?


    They don't enqueue events to the GUI event queue itself (at least
    on the GUIs I am aware of). See my detailed response to John about
    Android and look at the link I posted earlier.

    Non-GUI threads on Android have no direct access to the GUI and they
    have to communicate with the GUI thread via some form of generic
    messaging and let code running within the GUI thread perform the GUI >operations on their behalf.

    Sure. But, at least as far as the point I was trying to make,
    this is a distinction without a difference. The point is that
    the GUI exists in a shared address space with other threads, and
    must be intelligent about doing so. Even something as simple as
    memory allocation must be thread-safe.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Tue Oct 1 16:17:18 2024
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Tue Oct 1 21:34:33 2024
    On Tue, 1 Oct 2024 16:17:18 -0400, Arne Vajhøj wrote:

    It does not really make any sense for the test client to send
    "Connection: close".

    I think you’re right, but it still should be closing the connection
    cleanly, so the server side can get notification of that.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Tue Oct 1 23:55:38 2024
    In article <66fc58ce$0$708$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It makes even less sense to implement the protocol improperly
    and then blame the other side when it doesn't work the way you
    expect, wouldn't you agree?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Tue Oct 1 19:56:01 2024
    On 10/1/2024 7:46 PM, Arne Vajhøj wrote:
    On 10/1/2024 8:16 AM, Simon Clubley wrote:
    On 2024-09-30, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/30/2024 9:36 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhøj wrote:
    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even
    multithreaded
    GUIs. It was soon discovered that was not a great idea.

    Practically all GUI's are multi-threaded.


    No. The GUIs I know of (GTK, Android, etc) are all single threaded and
    any
    other threads which need to use the GUI need to queue a request on the
    GUI
    thread.

    I am used to Java Swing and .NET WinForms where event thread is not
    main thread.

    But I guess it sort of makes sense to combine them. Main thread
    usually doesn't do anything after kicking of the GUI stuff.

    But any time one need to do anything time consuming in the GUI
    then it needs to be done in its own thread but GUI updates
    need to be done by the GUI thread.

    But I assume that the typical GTK application does use many threads.

    If I look at Windows GUI applications that also runs on Linux then I see:

    FireFox (just 1 tab open) - 96 threads
    ThunderBird - 72 threads
    LibreOffice - 22 threads

    Is it different on Linux?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Tue Oct 1 19:46:53 2024
    On 10/1/2024 8:16 AM, Simon Clubley wrote:
    On 2024-09-30, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/30/2024 9:36 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 20:48:53 -0400, Arne Vajhøj wrote:
    The world is moving from forking processes to starting threads.

    That was tried in the 1990s -- threads for everything, even multithreaded >>> GUIs. It was soon discovered that was not a great idea.

    Practically all GUI's are multi-threaded.


    No. The GUIs I know of (GTK, Android, etc) are all single threaded and any other threads which need to use the GUI need to queue a request on the GUI thread.

    For example, in Android, you can define a Handler on the GUI thread which receives messages from other threads:

    https://developer.android.com/reference/android/os/Handler

    I tend to use:

    https://developer.android.com/reference/android/os/Handler#sendMessage(android.os.Message)

    to send messages from the other threads to the GUI thread.

    At least a main thread and an event thread.


    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    OK.

    I am used to Java Swing and .NET WinForms where event thread is not
    main thread.

    But I guess it sort of makes sense to combine them. Main thread
    usually doesn't do anything after kicking of the GUI stuff.

    But any time one need to do anything time consuming in the GUI
    then it needs to be done in its own thread but GUI updates
    need to be done by the GUI thread.

    Java Swing:

    EventQueue.invokeLater(() -> { ... });

    or:

    SwingUtilities.invokeLater(() -> { ... });

    .NET WinForms:

    if(ctl.InvokeRequired)
    {
    ctl.Invoke(new Action(() => ...));
    }
    else
    {
    ...
    }

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Tue Oct 1 20:00:49 2024
    On 10/1/2024 7:55 PM, Dan Cross wrote:
    In article <66fc58ce$0$708$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It makes even less sense to implement the protocol improperly
    and then blame the other side when it doesn't work the way you
    expect, wouldn't you agree?

    Not sending "Connection: close" header is perfectly valid.
    And it is the normal scenario.

    Sending "Connection: close" with every request is the client
    way to disable keep alive. And the unusual scenario.

    Disabling keep alive client side not surprisingly has
    the same effect as disabling keep alive server side.

    But while disabling keep alive server side makes sense
    then it doesn't make sense to disable it client side.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Tue Oct 1 20:30:04 2024
    On 10/1/2024 7:46 PM, Arne Vajhøj wrote:
    On 10/1/2024 8:16 AM, Simon Clubley wrote:
    On 2024-09-30, Arne Vajhøj <arne@vajhoej.dk> wrote:
    At least a main thread and an event thread.


    No. In the GUIs I am aware of, the main GUI thread _is_ the event thread.

    OK.

    I am used to Java Swing and .NET WinForms where event thread is not
    main thread.

    And that was not correct.

    I checked the docs.

    in .NET Application.Run does start the event loop in current thread,
    which will usually be main thread.

    Not sure why I have always thought it was a separate thread.

    Mea culpa.

    But I guess it sort of makes sense to combine them. Main thread
    usually doesn't do anything after kicking of the GUI stuff.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 00:46:21 2024
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhøj wrote:

    But any time one need to do anything time consuming in the GUI then it
    needs to be done in its own thread ...

    Note that “cpu-intensive” and “time-consuming” are not synonymous. Something can take a long time to complete, but not require much CPU time during that time, so running it in the main thread would be fine and have minimal impact.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 00:48:29 2024
    On Tue, 1 Oct 2024 19:56:01 -0400, Arne Vajhøj wrote:

    But I assume that the typical GTK application does use many threads.

    I tried to do a GTK application with threading, once. Even though the
    calls were supposed to be thread-safe, I kept hitting strange crashes.

    In the end, I gave up and used asyncio tasks instead. And my code was now
    able to scale well beyond the point where I was hitting those crashes
    before, and still run fine.

    It was the animsort example in this repo <https://bitbucket.org/ldo17/glibcoro_examples/>, if you’re curious.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Tue Oct 1 20:50:30 2024
    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhøj wrote:
    But any time one need to do anything time consuming in the GUI then it
    needs to be done in its own thread ...

    Note that “cpu-intensive” and “time-consuming” are not synonymous. Something can take a long time to complete, but not require much CPU time during that time, so running it in the main thread would be fine and have minimal impact.

    But how do you keep the GUI responsive if the event/main loop
    is doing something that is time consuming??

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Tue Oct 1 22:42:36 2024
    On 10/1/2024 10:21 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 20:50:30 -0400, Arne Vajhøj wrote:
    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhøj wrote:
    But any time one need to do anything time consuming in the GUI then it >>>> needs to be done in its own thread ...

    Note that “cpu-intensive” and “time-consuming” are not synonymous. >>> Something can take a long time to complete, but not require much CPU
    time during that time, so running it in the main thread would be fine
    and have minimal impact.

    But how do you keep the GUI responsive if the event/main loop is doing
    something that is time consuming??

    The task waiting for the operation to complete blocks on a notification
    back from the event loop that it can proceed.

    Now you have confused me again.

    We had:
    * some time consuming task that need to run
    * some unrelated GUI events that need to be processed in the event loop

    And now you say that the thread instead of blocking on the task block
    waiting for a notification from the event loop.

    I don't get that.

    The first two look like:

    while(has_next_event())
    {
    ev = get_next_event()
    switch(ev.event_type)
    {
    case START_LONG_RUNNING:
    call calculate_all_primes_in_int64_and_display_count()
    break
    case SOMETHING_ELSE:
    call handle_something_else()
    break
    }
    }

    which hangs the GUI.

    So you do what?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 02:21:05 2024
    On Tue, 1 Oct 2024 20:50:30 -0400, Arne Vajhøj wrote:

    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:

    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhøj wrote:

    But any time one need to do anything time consuming in the GUI then it
    needs to be done in its own thread ...

    Note that “cpu-intensive” and “time-consuming” are not synonymous. >> Something can take a long time to complete, but not require much CPU
    time during that time, so running it in the main thread would be fine
    and have minimal impact.

    But how do you keep the GUI responsive if the event/main loop is doing something that is time consuming??

    The task waiting for the operation to complete blocks on a notification
    back from the event loop that it can proceed.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 03:04:11 2024
    On Tue, 1 Oct 2024 22:42:36 -0400, Arne Vajhøj wrote:

    And now you say that the thread instead of blocking on the task block
    waiting for a notification from the event loop.

    If you want to see a concrete example, have a look at the animsort program
    I alluded to earlier.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 10:54:20 2024
    In article <66fc8d31$0$716$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 7:55 PM, Dan Cross wrote:
    In article <66fc58ce$0$708$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It makes even less sense to implement the protocol improperly
    and then blame the other side when it doesn't work the way you
    expect, wouldn't you agree?

    Not sending "Connection: close" header is perfectly valid.
    And it is the normal scenario.

    Indeed. Because persistent connections are the default in
    HTTP/1.1. If you want the server to close the connection after
    every request, which you said that you did, you would send
    `Connection: close`.

    Sending "Connection: close" with every request is the client
    way to disable keep alive. And the unusual scenario.

    Yes. Colloquially, we call persistent connections "keep alive".
    You were asked if your client was using keep-alive was disabled,
    and you said that it was. Clearly it was not.

    Disabling keep alive client side not surprisingly has
    the same effect as disabling keep alive server side.

    Indeed. I'm glad that you were able to recognize that, after
    suggesting that there was a "problem" when the server didn't
    close the connection when you didn't send `Connection: close`.
    Why would you expect it to?

    But while disabling keep alive server side makes sense
    then it doesn't make sense to disable it client side.

    Huh? The RFC is quite clear on the behavior of persistent
    connections and the use of the `Connection: close` header. You
    appear to have been sending HTTP/1.1 requests, sans header, and
    then asserting that there was a bug in the server software when
    it didn't behave as you expected. Were you unable to understand
    section 9.3 of RFC 9112, which I referred you to earlier? https://www.rfc-editor.org/rfc/rfc9112#name-persistence

    Again, it seems that the "bug" was yours.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Wed Oct 2 10:02:39 2024
    On 10/2/2024 9:31 AM, Dave Froble wrote:
    On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble  <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It does if the server is holding the connection open, waiting for more.

    Not really.

    The real goal is to make it work well for users not to make the
    test program work well.

    Having the test program send "Connection: close" will improve
    performance for the test program.

    But it does not improve anything for the web browsers that
    does not send "Connection: close".

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Wed Oct 2 09:31:48 2024
    On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    Arne


    It does if the server is holding the connection open, waiting for more.

    Not claiming this happens in the real world. Things aren't that clean.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dave Froble on Wed Oct 2 10:00:02 2024
    On 10/2/2024 9:45 AM, Dave Froble wrote:
    On 9/30/2024 9:25 PM, Arne Vajhøj wrote:
    On 9/30/2024 9:10 PM, Dave Froble wrote:
    Granted, starting up a new process involves some overhead.

    But it really depends upon the requirements.  The more use out of a
    process
    once it is started, the better overall performance.  If a group of
    worker
    processes is started once, then used for many tasks, then that overhead
    happens only once.  Perhaps once a day, week, month, and even year.
    There are
    various communication methods available on VMS.

    In the end, it comes down to the requirements.  An engineer must
    evaluate the
    task(s) and determine what methods will give adequate results.

    There are obviously a scale.

    But the Apache case is to start with 5 processes, start 145 new
    processes in a few seconds and then kill 140 again after maybe
    30-45 seconds. And repeat.

    Perhaps the real problem is using a poorly designed application,
    regardless of how popular it might be?

    Or taking code designed for a different OS and expecting
    it to work on another OS.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Wed Oct 2 09:45:33 2024
    On 9/30/2024 9:25 PM, Arne Vajhøj wrote:
    On 9/30/2024 9:10 PM, Dave Froble wrote:
    On 9/30/2024 8:33 PM, Arne Vajhøj wrote:
    On 9/30/2024 8:24 PM, Lawrence D'Oliveiro wrote:
    On Mon, 30 Sep 2024 19:50:38 -0400, Arne Vajhøj wrote:
    On 9/29/2024 11:15 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 22:34:04 -0400, Arne Vajhøj wrote:
    But I am pretty sure that it will not work on VMS.

    That’s what I figured. VMS, like Windows, really wants you to use >>>>>> threads.

    For massive parallel processing on VMS then threads not
    processes is the way to go.

    Threads require shared memory, though. Processes allow you to have a mix >>>> of shared and private data, plus the use of IPC mechanisms like message >>>> passing. This makes for a looser coupling, which better suits the way
    massively parallel systems are built.

    It is undeniable that multiple processes are more loosely coupled
    than multiple threads.

    But efficiency is a problem. VMS does not do fork. Process creation
    is expensive on VMS. None of that fancy moving descriptors over
    Unix socket stuff.

    VMS got plenty of methods for IPC. A solution with a fixed number
    of processes doing IPC between each other may work fine.

    But the concept of constantly starting new processes and killing
    old processes is not going to perform great.

    Well, now, that is a rather bold statement.

    Sometimes I make such.

    :-)

    Granted, starting up a new process involves some overhead.

    But it really depends upon the requirements. The more use out of a process >> once it is started, the better overall performance. If a group of worker
    processes is started once, then used for many tasks, then that overhead
    happens only once. Perhaps once a day, week, month, and even year. There are
    various communication methods available on VMS.

    In the end, it comes down to the requirements. An engineer must evaluate the
    task(s) and determine what methods will give adequate results.

    There are obviously a scale.

    But the Apache case is to start with 5 processes, start 145 new
    processes in a few seconds and then kill 140 again after maybe
    30-45 seconds. And repeat.

    Arne




    Perhaps the real problem is using a poorly designed application, regardless of how popular it might be?

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Oct 2 10:08:46 2024
    On 10/2/2024 6:54 AM, Dan Cross wrote:
    In article <66fc8d31$0$716$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 7:55 PM, Dan Cross wrote:
    In article <66fc58ce$0$708$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It makes even less sense to implement the protocol improperly
    and then blame the other side when it doesn't work the way you
    expect, wouldn't you agree?

    Not sending "Connection: close" header is perfectly valid.
    And it is the normal scenario.

    Indeed. Because persistent connections are the default in
    HTTP/1.1. If you want the server to close the connection after
    every request, which you said that you did, you would send
    `Connection: close`.

    Sending "Connection: close" with every request is the client
    way to disable keep alive. And the unusual scenario.

    Yes. Colloquially, we call persistent connections "keep alive".
    You were asked if your client was using keep-alive was disabled,
    and you said that it was. Clearly it was not.

    I said that it was not using it. And it is not. It is just
    not informing the server that it has no intention of using it.

    Disabling keep alive client side not surprisingly has
    the same effect as disabling keep alive server side.

    Indeed. I'm glad that you were able to recognize that, after
    suggesting that there was a "problem" when the server didn't
    close the connection when you didn't send `Connection: close`.
    Why would you expect it to?

    I have never expected that.

    But while disabling keep alive server side makes sense
    then it doesn't make sense to disable it client side.

    Huh? The RFC is quite clear on the behavior of persistent
    connections and the use of the `Connection: close` header. You
    appear to have been sending HTTP/1.1 requests, sans header, and
    then asserting that there was a bug in the server software when
    it didn't behave as you expected. Were you unable to understand
    section 9.3 of RFC 9112, which I referred you to earlier? https://www.rfc-editor.org/rfc/rfc9112#name-persistence

    Again, it seems that the "bug" was yours.

    You are not making any sense.

    It is perfectly valid per RFS to make HTTP 1.1 connections
    without "Connection: close".

    It is the normal case.

    It is what browsers do.

    Changing the test client to always send "Connection: close"
    does improve performance for the test client.

    But it does not improve performance for the browsers that
    do not send "Connection: close".

    There is no point on improving test results for a test
    program by having the test program do something that the browsers
    it is simulating does not.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 10:09:23 2024
    On 10/1/2024 5:34 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 16:17:18 -0400, Arne Vajhøj wrote:
    It does not really make any sense for the test client to send
    "Connection: close".

    I think you’re right, but it still should be closing the connection cleanly, so the server side can get notification of that.

    Browsers doesn't, so ...

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 14:32:11 2024
    In article <vdjjl2$37f8q$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 9:45 AM, Dave Froble wrote:
    On 9/30/2024 9:25 PM, Arne Vajhøj wrote:
    On 9/30/2024 9:10 PM, Dave Froble wrote:
    Granted, starting up a new process involves some overhead.

    But it really depends upon the requirements.  The more use out of a
    process
    once it is started, the better overall performance.  If a group of
    worker
    processes is started once, then used for many tasks, then that overhead >>>> happens only once.  Perhaps once a day, week, month, and even year.
    There are
    various communication methods available on VMS.

    In the end, it comes down to the requirements.  An engineer must
    evaluate the
    task(s) and determine what methods will give adequate results.

    There are obviously a scale.

    But the Apache case is to start with 5 processes, start 145 new
    processes in a few seconds and then kill 140 again after maybe
    30-45 seconds. And repeat.

    Perhaps the real problem is using a poorly designed application,
    regardless of how popular it might be?

    Or taking code designed for a different OS and expecting
    it to work on another OS.

    I don't see any evidence that leads me to believe that was
    actually a problem. I do see evidence that you assumed there
    was a problem where, in fact, one did not exist, and that you
    failed to investigate sufficiently before jumping to
    conclusions.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Wed Oct 2 14:29:27 2024
    In article <vdji17$38hdb$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It does if the server is holding the connection open, waiting for more.

    Which is precisely the behavior Arne observed, and is also what
    the RFC says the server should do.

    Not claiming this happens in the real world. Things aren't that clean.

    I decided to do what Arne was either unwilling or unable to do:
    connect to the server directly and observe its behavior. This
    is an example of the sort of problem report that Arne _should_
    have sent; had he given some useful details on the experimental
    setup he used, and his observed results, we probably could have
    been able to see his error much earlier, but he was rather
    cagey with details and this conversation dragged on. Anyway.

    I did not set Apache up under VMS, but instead, did so on
    FreeBSD. Everything is stock; installation was just via the
    normal `pkg install apache24`.

    I then created a simple text file under apache's DocumentRoot:

    ```
    : fbsd; cat /usr/local/www/apache24/data/nop.txt
    hi
    : fbsd;
    ```

    I verified that I could get that via `curl`:

    ```
    : fbsd; curl http://localhost/nop.txt
    hi
    : fbsd;
    ```

    (Note, that returns almost immediately.)

    To get a baseline on performance, I used the `ab` tool ("Apache
    Bench"). I hit it with 100,000 requests using 20 concurrent
    requestors.

    ```
    : fbsd; ab -c 20 -n 100000 http://localhost/nop.txt
    This is ApacheBench, Version 2.3 <$Revision: 1913912 $>
    Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/ Licensed to The Apache Software Foundation, http://www.apache.org/

    Benchmarking localhost (be patient)
    Completed 10000 requests
    Completed 20000 requests
    Completed 30000 requests
    Completed 40000 requests
    Completed 50000 requests
    Completed 60000 requests
    Completed 70000 requests
    Completed 80000 requests
    Completed 90000 requests
    Completed 100000 requests
    Finished 100000 requests


    Server Software: Apache/2.4.62
    Server Hostname: localhost
    Server Port: 80

    Document Path: /nop.txt
    Document Length: 3 bytes

    Concurrency Level: 20
    Time taken for tests: 1.247 seconds
    Complete requests: 100000
    Failed requests: 0
    Total transferred: 24900000 bytes
    HTML transferred: 300000 bytes
    Requests per second: 80200.05 [#/sec] (mean)
    Time per request: 0.249 [ms] (mean)
    Time per request: 0.012 [ms] (mean, across all concurrent requests) Transfer rate: 19501.77 [Kbytes/sec] received

    Connection Times (ms)
    min mean[+/-sd] median max
    Connect: 0 0 0.0 0 0
    Processing: 0 0 0.0 0 0
    Waiting: 0 0 0.0 0 0
    Total: 0 0 0.0 0 0

    Percentage of the requests served within a certain time (ms)
    50% 0
    66% 0
    75% 0
    80% 0
    90% 0
    95% 0
    98% 0
    99% 0
    100% 0 (longest request)
    : fbsd;
    ```

    I then observed what happened if I connected directly to the
    HTTP server and sent commands. I used the "netcat" (`nc`)
    command to connect to the HTTP server port, and issued a
    `GET` request via a pipe; I timed the `nc` command to see how
    long it took until the server disconnected.

    ```
    : fbsd; (printf "GET /nop.txt HTTP/1.1\r\nHost: localhost\r\n\r\n") | time nc localhost 80
    HTTP/1.1 200 OK
    Date: Wed, 02 Oct 2024 14:00:42 GMT
    Server: Apache/2.4.62 (FreeBSD)
    Last-Modified: Wed, 02 Oct 2024 13:44:20 GMT
    ETag: "3-6237ea2939a43"
    Accept-Ranges: bytes
    Content-Length: 3
    Content-Type: text/plain

    hi
    nc localhost 80 0.00s user 0.00s system 0% cpu 5.106 total
    : fbsd;
    ```

    My observation was that the resposne to the query returned
    almost immediately (within milliseconds), and the server
    disconnected around the 5 second mark, as indicated by the
    `time` command.

    This, and having some familiarity with reading RFCs, makes clear
    what is going on: without sending the `Connection: close` header
    the server is waiting for the another request; eventually it
    times out closes the connection. Where does the 5 seconds come
    from, though? It's probably a configuration parameter, but let
    us see if we can verify. Using the "ripgrep" tool (`rg`), I
    search for the number "5" in the Apache configuration:

    ```
    : fbsd; rg '\b5\b' /usr/local/etc/apache24
    [snip]

    /usr/local/etc/apache24/extra/httpd-default.conf
    29:KeepAliveTimeout 5

    [snip]

    /usr/local/etc/apache24/extra/httpd-mpm.conf.sample
    29: StartServers 5
    30: MinSpareServers 5
    97: MinSpareThreads 5
    : fbsd;
    ```

    I cut out a number of irrelvant matches (magic numbers and MIME
    types and the like), but the output isn't that big, and
    certainly `KeepAliveTimeout` shines like a bright light in the
    middle of it. That matches our observed results, but what
    happens if I change it to, say, 20 seconds? I edit the config
    file and restart the server and re-run my test:

    ```
    : fbsd; (printf "GET /nop.txt HTTP/1.1\r\nHost: localhost\r\n\r\n") | time nc localhost 80
    HTTP/1.1 200 OK
    Date: Wed, 02 Oct 2024 14:19:50 GMT
    Server: Apache/2.4.62 (FreeBSD)
    Last-Modified: Wed, 02 Oct 2024 13:44:20 GMT
    ETag: "3-6237ea2939a43"
    Accept-Ranges: bytes
    Content-Length: 3
    Content-Type: text/plain

    hi
    nc localhost 80 0.00s user 0.00s system 0% cpu 20.317 total
    : fbsd;
    ```

    And there we have it. This behavior clearly matches what Arne
    saw, and we can speculate that the "problem" that Arne observed
    was almost certainly due to the default setting of
    `KeepAliveTimeout` on VMS being 20 seconds. I'd bet cookies to
    cake that, if Arne changed that value, he'd see different
    timeouts with his test client.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 14:41:20 2024
    In article <vdjk5e$37f8p$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 6:54 AM, Dan Cross wrote:
    In article <66fc8d31$0$716$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 7:55 PM, Dan Cross wrote:
    In article <66fc58ce$0$708$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It makes even less sense to implement the protocol improperly
    and then blame the other side when it doesn't work the way you
    expect, wouldn't you agree?

    Not sending "Connection: close" header is perfectly valid.
    And it is the normal scenario.

    Indeed. Because persistent connections are the default in
    HTTP/1.1. If you want the server to close the connection after
    every request, which you said that you did, you would send
    `Connection: close`.

    Sending "Connection: close" with every request is the client
    way to disable keep alive. And the unusual scenario.

    Yes. Colloquially, we call persistent connections "keep alive".
    You were asked if your client was using keep-alive was disabled,
    and you said that it was. Clearly it was not.

    I said that it was not using it. And it is not. It is just
    not informing the server that it has no intention of using it.

    So then it was, because it's the default to use it unless the
    client tells it otherwise, or you explicitly disable it in the
    server configuration.

    Disabling keep alive client side not surprisingly has
    the same effect as disabling keep alive server side.

    Indeed. I'm glad that you were able to recognize that, after
    suggesting that there was a "problem" when the server didn't
    close the connection when you didn't send `Connection: close`.
    Why would you expect it to?

    I have never expected that.

    Apparently you did. You said there was a "problem" when you
    made an HTTP/1.1 request without the `Connection: close` header.

    But while disabling keep alive server side makes sense
    then it doesn't make sense to disable it client side.

    Huh? The RFC is quite clear on the behavior of persistent
    connections and the use of the `Connection: close` header. You
    appear to have been sending HTTP/1.1 requests, sans header, and
    then asserting that there was a bug in the server software when
    it didn't behave as you expected. Were you unable to understand
    section 9.3 of RFC 9112, which I referred you to earlier?
    https://www.rfc-editor.org/rfc/rfc9112#name-persistence

    Again, it seems that the "bug" was yours.

    You are not making any sense.

    No, I'm afraid you are just confused.

    It is perfectly valid per RFS to make HTTP 1.1 connections
    without "Connection: close".

    It is the normal case.

    It is what browsers do.

    Changing the test client to always send "Connection: close"
    does improve performance for the test client.

    But it does not improve performance for the browsers that
    do not send "Connection: close".

    There is no point on improving test results for a test
    program by having the test program do something that the browsers
    it is simulating does not.

    I don't think you understand how the protocol works, or how a
    browser might use it. A browser will opportunistically reuse a
    persistent connection; evidently, your test program does not.

    In your test program, you had some number of threads sending
    requests to the server; those requests did not include a
    `Connection: close` header. But those threads received the
    expected response from the server, but then paused waiting for
    the server to close the connection, which it did after the
    `KeepAliveTimeout` number of seconds. What did you expect the
    server to do differently? Why you were surprised by the results
    you observed?

    For some strange and unexplained reason, you then concluded that
    the server had a bug. That makes no sense.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 14:47:30 2024
    In article <vdjjpv$37f8q$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 9:31 AM, Dave Froble wrote:
    On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble  <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It does if the server is holding the connection open, waiting for more.

    Not really.

    The real goal is to make it work well for users not to make the
    test program work well.

    Having the test program send "Connection: close" will improve
    performance for the test program.

    But it does not improve anything for the web browsers that
    does not send "Connection: close".

    If a web browser sends an HTTP/1.1 request without the
    `Connection: close` header, it's likely that it wants that
    connection to be persistent, presumably so that it can use it
    for another request.

    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    Do you understand that the protocol definition specifies that
    the connection should be persistent unless the client says
    differently via the `Connection: close` header?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 15:07:44 2024
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do? And what is the "problem" that
    you are imagining here? Please be specific. Better yet, why
    don't you post your test program somewhere so folks who
    understand how the protocol works can look at it and point out
    the bug?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Oct 2 10:53:56 2024
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    In article <vdjjpv$37f8q$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 9:31 AM, Dave Froble wrote:
    On 10/1/2024 4:17 PM, Arne Vajhøj wrote:
    On 10/1/2024 3:45 PM, Dan Cross wrote:
    In article <vd9mqn$1cm1v$1@dont-email.me>,
    Dave Froble  <davef@tsoft-inc.com> wrote:
    On 9/27/2024 9:11 PM, Arne Vajhøj wrote:
    [snip]
    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Feature ...

    Yes, it is a feature, despite this report of a non-problem.

    In this case, later posts revealed the real culprit: Arne's test
    program did not follow the protocol, and was not sending
    `Connection: close` with an HTTP/1.1 request; in response, the
    server (correctly) kept the connection open waiting for the
    client to send another request.

    It does not really make any sense for the test client
    to send "Connection: close".

    It does if the server is holding the connection open, waiting for more.

    Not really.

    The real goal is to make it work well for users not to make the
    test program work well.

    Having the test program send "Connection: close" will improve
    performance for the test program.

    But it does not improve anything for the web browsers that
    does not send "Connection: close".

    If a web browser sends an HTTP/1.1 request without the
    `Connection: close` header, it's likely that it wants that
    connection to be persistent, presumably so that it can use it
    for another request.

    That is the purpose.

    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Oct 2 11:20:53 2024
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

    And what is the "problem" that
    you are imagining here? Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Oct 2 11:30:26 2024
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj  <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

                                And what is the "problem" that
    you are imagining here?  Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    And the numbers are low due to keep alive.

    Basically Apache on VMS keep an entire process around for
    a kept alive connection.

    When Apache configuration does not allow more
    processes to start then new requests get queued
    until keep alive starts to timeout and processes
    free up.

    And one can not just increase number of processes
    allowed because they use 25 MB each. The system
    runs out of memory/pagefile fast.

    An it does not help that if Apache kills some
    processes then it is expensive to start a new one again,
    which means that either the large number of memory
    consuming processes are kept around or Apache
    will be slow to adjust to increasing load.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Oct 2 11:32:58 2024
    Summary numbers and analysis.

    no db con pool db con pool
    Apache + CGI 4 req/sec N/A
    Apache + mod_php (cfg A) 11 req/sec 11 req/sec
    Apache + mod_php (cfg B) 22 req/sec 22 req/sec
    Apache + mod_php (cfg C) 94 req/sec 103 req/sec
    Apache + mod_php (cfg D) 85 req/sec 83 req/sec
    Tomcat + Quercus 208 req/sec 214 req/sec
    Apache + mod_php (win) ~1200 req/sec ~6000 req/sec

    Note that Windows got more CPU and RAM than VMS, so not really
    comparable. With resources similar to VMS then I would expect
    maybe 1/10'th of througput.

    I have not tested Apache on Linux, but I would expect the numbers
    to be even higher than Windows - it is what is used by most of the web.

    config KeepAlive KeepALiveTimeout MaxSpareServers MaxClients
    A On 15 10 150
    B On 15 50 300
    C Off N/A 50 300
    D On 1 300 300

    A is default config
    B is as many resources that my VMS system could support
    C is keep alive disabled
    D is keep alive limited

    Allocating as many resources as one can spare make sense. But it can
    be a lot of resources. Expect memory usage to be MaxClients * 25 MB.

    But for the rest then as usual there are tradeoffs.

    config browser benefit browser benefit througput
    keep alive keep alive
    within page across pages
    B yes yes low
    C no no acceptable
    D yes no almost acceptable

    I consider 100 req/sec as acceptable. Good would be 200-300 which
    is what Quercus can do and the exterpolation from:
    (througput PHP Apache / throughput static Apache) * throughput
    static OSU

    I suspect that most will find D attractive.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 15:42:54 2024
    In article <vdjocl$37f8p$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    Does the client close the connection? Why do you think that it
    moves on to the next request?

    Despite repeated requests for more information, you haven't told
    us much of anything at all about the client or your setup. I
    gather that the client is something you wrote yourself; why not
    put that code somewhere for someone else to inspect and
    understand?

    That request will block if the server can't serve it
    because all processes are busy.

    You haven't shown sufficient evidence to support that
    conclusion; perhaps you have it, but you haven't shared
    it. Have you even attempted any of the debugging steps
    I suggested to you, for instance?

    And what is the "problem" that
    you are imagining here? Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    Yes. I don't see any evidence to support your claims.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 15:45:00 2024
    In article <vdjoui$37f8q$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj  <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

                                And what is the "problem" that
    you are imagining here?  Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    And the numbers are low due to keep alive.

    Basically Apache on VMS keep an entire process around for
    a kept alive connection.

    When Apache configuration does not allow more
    processes to start then new requests get queued
    until keep alive starts to timeout and processes
    free up.

    And one can not just increase number of processes
    allowed because they use 25 MB each. The system
    runs out of memory/pagefile fast.

    An it does not help that if Apache kills some
    processes then it is expensive to start a new one again,
    which means that either the large number of memory
    consuming processes are kept around or Apache
    will be slow to adjust to increasing load.

    These are all claims not supported by the _actual_ evidence that
    you've posted here. While your argument is plausible on the
    face of it, how did you arrive at this conclusion?

    Post more details about your setup and experiments.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Oct 2 12:58:46 2024
    On 10/2/2024 12:25 PM, Dan Cross wrote:
    In article <vdjpps$fk2$2@reader1.panix.com>,
    Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    In article <vdjoui$37f8q$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj  <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close` >>>>>>> with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

    >                            And what is the "problem" that
    > you are imagining here?  Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    And the numbers are low due to keep alive.

    Basically Apache on VMS keep an entire process around for
    a kept alive connection.

    When Apache configuration does not allow more
    processes to start then new requests get queued
    until keep alive starts to timeout and processes
    free up.

    And one can not just increase number of processes
    allowed because they use 25 MB each. The system
    runs out of memory/pagefile fast.

    An it does not help that if Apache kills some
    processes then it is expensive to start a new one again,
    which means that either the large number of memory
    consuming processes are kept around or Apache
    will be slow to adjust to increasing load.

    These are all claims not supported by the _actual_ evidence that
    you've posted here. While your argument is plausible on the
    face of it, how did you arrive at this conclusion?

    Post more details about your setup and experiments.

    Let's dig a little deeper here and show that Arne's pro blem
    is not specific to VMS. Indeed, I can replicate something more
    or less like the results he showed on FreeBSD.

    I'm using "seige", which is another testing tool; here, I can
    force HTTP/1.1 and also enable keep-alive via options in its
    configuration file. With 25 worker threads 1000 queries each,
    I easily saturate the number of workers and hang waiting for
    timeouts, tanking throughput.

    So...Not a VMS problem at all.

    The basic mechanism is not VMS specific at all.

    I assume that it is inherent in prefork MPM on all
    platforms and other servers that use a similar
    worker process model.

    As I have noted a couple of times then back when
    prefork MPM was common (20 years ago) then the question
    about whether to have keep alive on or off was
    often discussed.

    The problem does not seem to impact newer designs
    using threads. They obviously still need to keep
    the connection open, but I guess they do some
    select/poll/epoll/whatever to detect when there is a
    new request to keep resource usage minimal.

    But the mechanism hits VMS harder than other platforms.
    The *nix fork is way more efficient than SYS$CREPRC for
    creating those hundreds or thousands of worker processes.

    We can have fewer worker processes on VMS and it creates
    longer delay to start them up.

    As described above.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to Dan Cross on Wed Oct 2 16:25:08 2024
    In article <vdjpps$fk2$2@reader1.panix.com>,
    Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    In article <vdjoui$37f8q$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj  <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

                                And what is the "problem" that
    you are imagining here?  Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    And the numbers are low due to keep alive.

    Basically Apache on VMS keep an entire process around for
    a kept alive connection.

    When Apache configuration does not allow more
    processes to start then new requests get queued
    until keep alive starts to timeout and processes
    free up.

    And one can not just increase number of processes
    allowed because they use 25 MB each. The system
    runs out of memory/pagefile fast.

    An it does not help that if Apache kills some
    processes then it is expensive to start a new one again,
    which means that either the large number of memory
    consuming processes are kept around or Apache
    will be slow to adjust to increasing load.

    These are all claims not supported by the _actual_ evidence that
    you've posted here. While your argument is plausible on the
    face of it, how did you arrive at this conclusion?

    Post more details about your setup and experiments.

    Let's dig a little deeper here and show that Arne's pro blem
    is not specific to VMS. Indeed, I can replicate something more
    or less like the results he showed on FreeBSD.

    I'm using "seige", which is another testing tool; here, I can
    force HTTP/1.1 and also enable keep-alive via options in its
    configuration file. With 25 worker threads 1000 queries each,
    I easily saturate the number of workers and hang waiting for
    timeouts, tanking throughput.

    So...Not a VMS problem at all.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 17:44:48 2024
    On 2024-10-01, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhj wrote:
    But any time one need to do anything time consuming in the GUI then it
    needs to be done in its own thread ...

    Note that ?cpu-intensive? and ?time-consuming? are not synonymous.
    Something can take a long time to complete, but not require much CPU time
    during that time, so running it in the main thread would be fine and have
    minimal impact.

    But how do you keep the GUI responsive if the event/main loop
    is doing something that is time consuming??


    You can add events to the main GTK loop (such as an I/O channel becoming
    ready) for GTK to listen on. Not sure if that is what Lawrence is thinking
    of.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 17:32:23 2024
    On 2024-10-01, Arne Vajhj <arne@vajhoej.dk> wrote:

    If I look at Windows GUI applications that also runs on Linux then I see:

    FireFox (just 1 tab open) - 96 threads
    ThunderBird - 72 threads
    LibreOffice - 22 threads

    Is it different on Linux?


    What makes you think those extra threads are doing anything directly
    with the GUI ?

    Also, I thought Windows was a single-thread GUI model (at least it was
    back in the traditional Win32 days IIRC). Has that changed recently ?

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Oct 2 13:50:42 2024
    On 10/2/2024 1:44 PM, Simon Clubley wrote:
    On 2024-10-01, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhøj wrote:
    But any time one need to do anything time consuming in the GUI then it >>>> needs to be done in its own thread ...

    Note that ?cpu-intensive? and ?time-consuming? are not synonymous.
    Something can take a long time to complete, but not require much CPU time >>> during that time, so running it in the main thread would be fine and have >>> minimal impact.

    But how do you keep the GUI responsive if the event/main loop
    is doing something that is time consuming??

    You can add events to the main GTK loop (such as an I/O channel becoming ready) for GTK to listen on. Not sure if that is what Lawrence is thinking of.

    So the event loop is not executing the long running task, but
    it is asking the OS to do something and moves on, and then the
    OS stuff an event into the vent loop when whatever is done?

    Lawrence actually posted a link to some code. I will have
    to take a look at that. Sometime.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Oct 2 13:46:54 2024
    On 10/2/2024 1:32 PM, Simon Clubley wrote:
    On 2024-10-01, Arne Vajhøj <arne@vajhoej.dk> wrote:
    If I look at Windows GUI applications that also runs on Linux then I see:

    FireFox (just 1 tab open) - 96 threads
    ThunderBird - 72 threads
    LibreOffice - 22 threads

    Is it different on Linux?

    What makes you think those extra threads are doing anything directly
    with the GUI ?

    Also, I thought Windows was a single-thread GUI model (at least it was
    back in the traditional Win32 days IIRC). Has that changed recently ?

    Maybe we are not talking about the same.

    Are we talking about how many threads can update the GUI
    widgets/controls or are we talking about how many threads
    in the GUI application?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 17:52:35 2024
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.


    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive settings) or does it always create a brand-new connection for the next
    request ?

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Oct 2 13:57:51 2024
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive settings) or does it always create a brand-new connection for the next request ?

    New connection.

    It is simulating multiple browser instances.

    Browser #1 open connection to request the page - keep
    the connection alive, because it may want to use it later.

    Browser #2 open connection to request the page - keep
    the connection alive, because it may want to use it later.

    etc.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Oct 2 14:06:51 2024
    On 10/2/2024 11:32 AM, Arne Vajhøj wrote:
    Summary numbers and analysis.

                            no db con pool     db con pool
    Apache + CGI               4 req/sec           N/A Apache + mod_php (cfg A)  11 req/sec         11 req/sec
    Apache + mod_php (cfg B)  22 req/sec         22 req/sec
    Apache + mod_php (cfg C)  94 req/sec        103 req/sec
    Apache + mod_php (cfg D)  85 req/sec         83 req/sec
    Tomcat + Quercus         208 req/sec        214 req/sec
    Apache + mod_php (win) ~1200 req/sec      ~6000 req/sec

    Note that Windows got more CPU and RAM than VMS, so not really
    comparable. With resources similar to VMS then I would expect
    maybe 1/10'th of througput.

    I have not tested Apache on Linux, but I would expect the numbers
    to be even higher than Windows - it is what is used by most of the web.

    config       KeepAlive   KeepALiveTimeout     MaxSpareServers    MaxClients
      A             On             15                   10               150
      B             On             15                   50               300
      C             Off            N/A                  50               300
      D             On             1                   300               300

    A is default config
    B is as many resources that my VMS system could support
    C is keep alive disabled
    D is keep alive limited

    Allocating as many resources as one can spare make sense. But it can
    be a lot of resources. Expect memory usage to be MaxClients * 25 MB.

    But for the rest then as usual there are tradeoffs.

    config    browser benefit    browser benefit    througput
              keep alive         keep alive
              within page        across pages
       B          yes                yes               low
       C          no                 no                acceptable
       D          yes                no                almost acceptable

    I consider 100 req/sec as acceptable. Good would be 200-300 which
    is what Quercus can do and the exterpolation from:
        (througput PHP Apache / throughput static Apache) * throughput
    static OSU

    I suspect that most will find D attractive.

    What would be nice to have had was a MaxKeepAliveConnections
    config parameter.

    KeepAlive=On,MaxClients=300,KeepAliveTimeout=15,
    MaxKeepAliveConnections=150 would work like:
    * the first 150 clients get full 15 seconds keep alive
    * the last 150 clients would not get keep alive

    That would utilize keep alive for everyone at low volume,
    but turn off keep alive for some clients at high load
    to keep throughput up.

    That config parameter does not exist though.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 18:04:10 2024
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:32 PM, Simon Clubley wrote:
    On 2024-10-01, Arne Vajhj <arne@vajhoej.dk> wrote:
    If I look at Windows GUI applications that also runs on Linux then I see: >>>
    FireFox (just 1 tab open) - 96 threads
    ThunderBird - 72 threads
    LibreOffice - 22 threads

    Is it different on Linux?

    What makes you think those extra threads are doing anything directly
    with the GUI ?

    Also, I thought Windows was a single-thread GUI model (at least it was
    back in the traditional Win32 days IIRC). Has that changed recently ?

    Maybe we are not talking about the same.

    Are we talking about how many threads can update the GUI
    widgets/controls or are we talking about how many threads
    in the GUI application?


    How many threads can _directly_ update the GUI widgets/controls.

    In Android that answer is exactly one, regardless of the number of
    additional threads the application is running.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 17:59:43 2024
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:44 PM, Simon Clubley wrote:
    On 2024-10-01, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/1/2024 8:46 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 19:46:53 -0400, Arne Vajhj wrote:
    But any time one need to do anything time consuming in the GUI then it >>>>> needs to be done in its own thread ...

    Note that ?cpu-intensive? and ?time-consuming? are not synonymous.
    Something can take a long time to complete, but not require much CPU time >>>> during that time, so running it in the main thread would be fine and have >>>> minimal impact.

    But how do you keep the GUI responsive if the event/main loop
    is doing something that is time consuming??

    You can add events to the main GTK loop (such as an I/O channel becoming
    ready) for GTK to listen on. Not sure if that is what Lawrence is thinking >> of.

    So the event loop is not executing the long running task, but
    it is asking the OS to do something and moves on, and then the
    OS stuff an event into the vent loop when whatever is done?


    If the long-running task is quickly kicking off some network request
    and then waiting for the result to arrive at some point in the future,
    then you can do all this in the GUI thread (provided you don't stall
    the GUI thread while creating the request).

    I have actually done this in the past with GTK on Linux.

    Still not sure if this is what Lawrence is thinking of however.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Oct 2 14:08:52 2024
    On 10/2/2024 2:04 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:32 PM, Simon Clubley wrote:
    On 2024-10-01, Arne Vajhøj <arne@vajhoej.dk> wrote:
    If I look at Windows GUI applications that also runs on Linux then I see: >>>>
    FireFox (just 1 tab open) - 96 threads
    ThunderBird - 72 threads
    LibreOffice - 22 threads

    Is it different on Linux?

    What makes you think those extra threads are doing anything directly
    with the GUI ?

    Also, I thought Windows was a single-thread GUI model (at least it was
    back in the traditional Win32 days IIRC). Has that changed recently ?

    Maybe we are not talking about the same.

    Are we talking about how many threads can update the GUI
    widgets/controls or are we talking about how many threads
    in the GUI application?

    How many threads can _directly_ update the GUI widgets/controls.

    I am not aware of any GUI frameworks where it is more than one.

    I showed the code for Java Swing and C# Win Forms for how to
    get the GUI update into the event thread from another thread.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Wed Oct 2 18:15:26 2024
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive
    settings) or does it always create a brand-new connection for the next
    request ?

    New connection.

    It is simulating multiple browser instances.

    Browser #1 open connection to request the page - keep
    the connection alive, because it may want to use it later.

    Browser #2 open connection to request the page - keep
    the connection alive, because it may want to use it later.


    Are you closing down the current instance of the client and then
    starting up a new instance of the client ?

    or

    Are you keeping the existing process running and creating a new
    instance from it ?

    In either case, are you _cleanly_ and _fully_ closing the existing
    connection _before_ you exit or create a new connection in the existing
    process ?

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Wed Oct 2 14:30:16 2024
    On 10/2/2024 2:15 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive >>> settings) or does it always create a brand-new connection for the next
    request ?

    New connection.

    It is simulating multiple browser instances.

    Browser #1 open connection to request the page - keep
    the connection alive, because it may want to use it later.

    Browser #2 open connection to request the page - keep
    the connection alive, because it may want to use it later.


    Are you closing down the current instance of the client and then
    starting up a new instance of the client ?

    or

    Are you keeping the existing process running and creating a new
    instance from it ?

    Existing process.

    In either case, are you _cleanly_ and _fully_ closing the existing
    connection _before_ you exit or create a new connection in the existing process ?

    No.

    Because browser instances do not do that. Browsers keeps
    connections open for a long time. I believe 300 seconds is common.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Wed Oct 2 14:53:59 2024
    On 10/2/2024 2:30 PM, Arne Vajhøj wrote:
    On 10/2/2024 2:15 PM, Simon Clubley wrote:
    In either case, are you _cleanly_ and _fully_ closing the existing
    connection _before_ you exit or create a new connection in the existing
    process ?

    No.

    Because browser instances do not do that. Browsers keeps
    connections open for a long time. I believe 300 seconds is common.

    The client side is rather uninteresting.

    Chrome, Safari, Firefox etc. behave like they do - nothing
    to do about it.

    It is definitely possible to change config values in httpd.conf
    (which on VMS is in APACHE$ROOT:[CONF]).

    VSI could change the source code of VMS Apache and provide
    a new version.

    If they uploaded the source to their public Github repo, then
    in theory anyone could update the source code.

    That is the constraints.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to clubley@remove_me.eisner.decus.org- on Wed Oct 2 19:13:21 2024
    In article <vdk2ju$3bapl$1@dont-email.me>,
    Simon Clubley <clubley@remove_me.eisner.decus.org-Earth.UFP> wrote:
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close` >>>>>>> with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive >>> settings) or does it always create a brand-new connection for the next
    request ?

    New connection.

    It is simulating multiple browser instances.

    Browser #1 open connection to request the page - keep
    the connection alive, because it may want to use it later.

    Browser #2 open connection to request the page - keep
    the connection alive, because it may want to use it later.


    Are you closing down the current instance of the client and then
    starting up a new instance of the client ?

    or

    Are you keeping the existing process running and creating a new
    instance from it ?

    In either case, are you _cleanly_ and _fully_ closing the existing
    connection _before_ you exit or create a new connection in the existing >process ?

    It seems clear that it does not.

    When asked about keep-alives initially, Arne said that the
    client does not make use of persistent connections. Subsequent
    posts revelated that it actually does; he seemed to be confused
    about how the protocol actually works there.

    He also posted this was a bug in the VMS implementation of
    Apache, going as far as to suggest something about expectations
    due to careless porting. But the same behavior manifests itself
    on other systems.

    Arne keeps moving the goal posts of what, exactly, he claims is
    wrong and why, while being cagey about how exactly he's testing
    and what the experimental setup looks like. It's intern-level
    investigation, at best.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 19:38:26 2024
    In article <vdd2mr$1tq3s$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/29/2024 10:03 PM, Lawrence D'Oliveiro wrote:
    On Sun, 29 Sep 2024 21:58:45 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:46 PM, Lawrence D'Oliveiro wrote:

    On Sun, 29 Sep 2024 21:42:48 -0400, Arne Vajhøj wrote:

    On 9/29/2024 9:21 PM, Lawrence D'Oliveiro wrote:

    Then it asks another process for a copy of that socket descriptor. >>>>>> Perhaps there is one overall connection-management process that
    accepts all new connections; if not, another worker that has that
    socket can pass it along.

    It should not be a problem of copying a socket descriptor from one
    process to another process - I believe it is just an int.

    But will it work in the other process????

    That’s not how you do it. You pass it with the SCM_RIGHTS
    ancillary-data option in Unix-family sockets
    <https://manpages.debian.org/7/unix.7.en.html>.

    Worker A has a AF_INET socket to client so what AF_UNIX socket does it
    pass to worker B?

    You can pass any FD (AF_INET socket, file, pipe, even another AF_UNIX
    socket) over an AF_UNIX socket.

    Ah. Interesting. Very interesting.

    Access rights passing over Unix domain sockets was introduced in
    4.2BSD, in 1983: more than 40 years ago. The basic mechanism
    was updated in 4.4BSD, in 1994: 30 years ago. Here's a working
    example:

    // Passing access rights between processes over Unix domain
    // sockets.
    //
    // Dan Cross <cross@gajendra.net>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/uio.h>

    #include <stddef.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    // Sends a file descripter, `fd`, over a Unix domain socket `sd`
    // via the 4.4BSD access rights passing mechanism.
    //
    // Returns 1 on success, -1 on failure.
    int
    sendfd(int sd, int fd)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    // Construct the control message header. Note this is
    // malloc'ed to ensure proper alignment.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;
    memset(ptr, 0, len);
    ptr->cmsg_len = len;
    ptr->cmsg_level = SOL_SOCKET;
    ptr->cmsg_type = SCM_RIGHTS;
    memcpy(CMSG_DATA(ptr), &fd, sizeof(int));

    // We send a single byte of dummy data in case the
    // implementation does not pass control data with an
    // otherwise empty data transfer.
    dummy = 0;
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Construct the message header. Points to the dummy
    // data and the control message header.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = (caddr_t)ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    // Loop in case there's no room in the kernel buffer
    // to send. Cf.Stevens et al.
    do {
    ret = sendmsg(sd, &mh, 0);
    } while (ret == 0);
    free(ptr);

    return ret;
    }

    // Receives a file descriptor over the Unix domain socket `sd`
    // and store it into `*fdp` on success.
    //
    // Returns 1 on success, 0 on EOF, -1 on error.
    int
    recv_fd(int sd, int *fdp)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    if (fdp == NULL)
    return -1;

    // Allocate space for the control structure.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;

    // Fill in an iovec to receive one byte of dummy data.
    // Required on some systems that do not pass control
    // messages on empty data transfers.
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Fill in the msghdr structure. `recvmsg(2)` will
    // update it.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    ret = recvmsg(sd, &mh, 0);
    if (ret <= 0) {
    free(ptr);
    return ret;
    }
    if (mh.msg_flags != 0) {
    free(ptr);
    return -1;
    }
    memcpy(fdp, CMSG_DATA(ptr), sizeof(int));
    free(ptr);

    return 1;
    }

    But I am pretty sure that it will not work on VMS.

    There's some chatter that suggests Unix domain sockets were
    added in OpenVMS 8.4, in 2010: 14 years ago: https://de.openvms.org/TUD2011/Unix_Portability_Updates_and_Open_Source.pdf

    I haven't checked myself; even if the basic Unix domain sockets
    mechanism was added for IPC, it's not clear if the access rights
    transfer functionality was also implemented.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Wed Oct 2 20:15:37 2024
    In article <66fd7bc6$0$715$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 12:25 PM, Dan Cross wrote:
    [snip]
    So...Not a VMS problem at all.

    The basic mechanism is not VMS specific at all.

    That's odd, because in <vdjjl2$37f8q$1@dont-email.me> you wrote:
    Or taking code designed for a different OS and expecting
    it to work on another OS.

    But that's clearly not the case here.

    I assume that it is inherent in prefork MPM on all
    platforms and other servers that use a similar
    worker process model.

    As I have noted a couple of times then back when
    prefork MPM was common (20 years ago) then the question
    about whether to have keep alive on or off was
    often discussed.

    I wonder if you forget that you had done that until today?

    The problem does not seem to impact newer designs
    using threads. They obviously still need to keep
    the connection open, but I guess they do some
    select/poll/epoll/whatever to detect when there is a
    new request to keep resource usage minimal.

    But the mechanism hits VMS harder than other platforms.

    Nah. The issue is pretty much the same.

    The *nix fork is way more efficient than SYS$CREPRC for
    creating those hundreds or thousands of worker processes.

    This may be true, and it certainly is the common wisdom, but it
    would be useful to provide an actual profile showing it to be
    the case.

    We can have fewer worker processes on VMS and it creates
    longer delay to start them up.

    As described above.

    The real failure here is in mismatched expectations vis how the
    protocol works and the server configuration. If you wanted to
    do this in a real shop, one would hope you'd have some sort of
    caching load balancer in front of your apache servers. Then
    again, Apache is pretty long in the tooth for this kind of
    thing.


    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 21:48:13 2024
    On Wed, 2 Oct 2024 10:00:02 -0400, Arne Vajhøj wrote:

    Or taking code designed for a different OS and expecting it to work on another OS.

    Does VMS need its own natively-developed web server? Who would create it?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 21:56:59 2024
    On Wed, 2 Oct 2024 14:08:52 -0400, Arne Vajhøj wrote:

    How many threads can _directly_ update the GUI widgets/controls.

    I am not aware of any GUI frameworks where it is more than one.

    That’s quite usual. There should also be some call so a background thread
    can safely post a callback to be executed on the GUI thread when it gets
    an idle moment.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 21:58:35 2024
    On Wed, 2 Oct 2024 10:09:23 -0400, Arne Vajhøj wrote:

    On 10/1/2024 5:34 PM, Lawrence D'Oliveiro wrote:

    On Tue, 1 Oct 2024 16:17:18 -0400, Arne Vajhøj wrote:

    It does not really make any sense for the test client to send
    "Connection: close".

    I think you’re right, but it still should be closing the connection
    cleanly, so the server side can get notification of that.

    Browsers doesn't ...

    I’m sure they do.

    I have a Websocket test somewhere, which I wrote to detect when a browser closes a window/tab, because the Websocket connection gets closed at that point. That does work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Dan Cross on Wed Oct 2 17:14:49 2024
    On 10/2/24 2:38 PM, Dan Cross wrote:

    There's some chatter that suggests Unix domain sockets were
    added in OpenVMS 8.4, in 2010: 14 years ago: https://de.openvms.org/TUD2011/Unix_Portability_Updates_and_Open_Source.pdf

    I haven't checked myself; even if the basic Unix domain sockets
    mechanism was added for IPC, it's not clear if the access rights
    transfer functionality was also implemented.

    Last I heard the domain sockets were just an emulation, implemented in
    terms of loopback AF_INET sockets. The most annoying limitation of the implementation that I remember was that you had to define logical names
    in the system table to tell it what ports to use:

    $ define/system TCPIP$AF_UNIX_MIN_PORT 1000
    $ define/system TCPIP$AF_UNIX_MAX_PORT 5000


    SCM_RIGHTS _is_ defined in socket.h, but that may not mean much.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 18:56:10 2024
    On 10/2/2024 5:48 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 10:00:02 -0400, Arne Vajhøj wrote:
    Or taking code designed for a different OS and expecting it to work on
    another OS.

    Does VMS need its own natively-developed web server? Who would create it?

    2 such exist: OSU and WASD. Thanks to David Jones and Mark Daniels.

    But Apache with a different MPM would do fine as well. The winnt MPM
    would be best fit. But the hybrid process and thread MPM's that
    Linux has used for the last 15-20 years would also fit fine.
    Practically anything but Apache prefork MPM. Porting another MPM
    could be VSI as Apache is supported by VSI or a volunteer.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 17:35:59 2024
    On 10/2/24 4:48 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 10:00:02 -0400, Arne Vajhøj wrote:

    Or taking code designed for a different OS and expecting it to work on
    another OS.

    Does VMS need its own natively-developed web server? Who would create it?

    There are at least three that have already been created and have been
    available for a very long time (though I think Purveyor may no longer be available?).

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Wed Oct 2 19:05:31 2024
    On 10/2/2024 6:14 PM, Craig A. Berry wrote:
    On 10/2/24 2:38 PM, Dan Cross wrote:
    There's some chatter that suggests Unix domain sockets were
    added in OpenVMS 8.4, in 2010: 14 years ago:
    https://de.openvms.org/TUD2011/
    Unix_Portability_Updates_and_Open_Source.pdf

    I haven't checked myself; even if the basic Unix domain sockets
    mechanism was added for IPC, it's not clear if the access rights
    transfer functionality was also implemented.

    Last I heard the domain sockets were just an emulation, implemented in
    terms of loopback AF_INET sockets.  The most annoying limitation of the implementation that I remember was that you had to define logical names
    in the system table to tell it what ports to use:

    $ define/system TCPIP$AF_UNIX_MIN_PORT 1000
    $ define/system TCPIP$AF_UNIX_MAX_PORT 5000

    SCM_RIGHTS _is_ defined in socket.h, but that may not mean much.

    It would be pretty hard to make it work as on *nix.

    The descriptor being moved is a kernel close thing
    on *nix, so for a kernel reassigning is work but not
    crazy much work.

    VMS is totally different. Especially for a file.
    A file descriptor is pointing to some user mode
    C RTL data structures that reference some RMS
    user mode data structures that reference some
    RMS executive mode data structures that reference
    some VMS kernel mode data structures. Lots of stuff
    to get copied over. Sockets would probably be a lot easier.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 19:07:19 2024
    On 10/2/2024 5:58 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 10:09:23 -0400, Arne Vajhøj wrote:
    On 10/1/2024 5:34 PM, Lawrence D'Oliveiro wrote:
    On Tue, 1 Oct 2024 16:17:18 -0400, Arne Vajhøj wrote:
    It does not really make any sense for the test client to send
    "Connection: close".

    I think you’re right, but it still should be closing the connection
    cleanly, so the server side can get notification of that.

    Browsers doesn't ...

    I’m sure they do.

    I have a Websocket test somewhere, which I wrote to detect when a browser closes a window/tab, because the Websocket connection gets closed at that point. That does work.

    Eventually they do.

    But it takes a long time. Way longer than the server side keep
    alive timeout.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 23:52:07 2024
    On Wed, 2 Oct 2024 19:07:19 -0400, Arne Vajhøj wrote:

    On 10/2/2024 5:58 PM, Lawrence D'Oliveiro wrote:

    I have a Websocket test somewhere, which I wrote to detect when a
    browser closes a window/tab, because the Websocket connection gets
    closed at that point. That does work.

    Eventually they do.

    For WebSockets, it happens immediately.

    But it takes a long time. Way longer than the server side keep alive
    timeout.

    OK, this I think I understand: not that the browser never (cleanly) closes
    the HTTP/HTTPS connection, but that it takes its time doing so, in the
    hope it can use it again.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Wed Oct 2 23:50:54 2024
    On Wed, 2 Oct 2024 19:05:31 -0400, Arne Vajhøj wrote:

    The descriptor being moved is a kernel close thing on *nix, so for a
    kernel reassigning is work but not crazy much work.

    VMS is totally different. Especially for a file.
    A file descriptor is pointing to some user mode C RTL data structures
    that reference some RMS user mode data structures that reference some
    RMS executive mode data structures that reference some VMS kernel mode
    data structures.

    If you leave RMS out of it, at the basic QIO level you have a channel,
    which is an index into the CCB array, which is in per-process P1 space (or whatever the 64-bit equivalent is). That in turn contains a reference to a
    WCB in system space, which is how VMS kept track of an open file --
    presumably there is some analogous structure for a comms socket etc.

    So sharing those in-kernel structures is not the hard part -- it would be
    easy enough to allocate a channel in the CCB array in another process and
    have it point back to the same in-kernel structures.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 19:56:20 2024
    On 10/2/2024 7:52 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:07:19 -0400, Arne Vajhøj wrote:
    On 10/2/2024 5:58 PM, Lawrence D'Oliveiro wrote:
    I have a Websocket test somewhere, which I wrote to detect when a
    browser closes a window/tab, because the Websocket connection gets
    closed at that point. That does work.

    Eventually they do.

    For WebSockets, it happens immediately.

    But it takes a long time. Way longer than the server side keep alive
    timeout.

    OK, this I think I understand: not that the browser never (cleanly) closes the HTTP/HTTPS connection, but that it takes its time doing so, in the
    hope it can use it again.

    They typical don't close the windows immediately.

    Server side keep alive timeout in Apache is 15 seconds.

    If the reader are done reading the page in less than 15 seconds
    then there is a problem with the content.

    :-)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 19:57:50 2024
    On 10/2/2024 7:50 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:05:31 -0400, Arne Vajhøj wrote:
    The descriptor being moved is a kernel close thing on *nix, so for a
    kernel reassigning is work but not crazy much work.

    VMS is totally different. Especially for a file.
    A file descriptor is pointing to some user mode C RTL data structures
    that reference some RMS user mode data structures that reference some
    RMS executive mode data structures that reference some VMS kernel mode
    data structures.

    If you leave RMS out of it, at the basic QIO level you have a channel,
    which is an index into the CCB array, which is in per-process P1 space (or whatever the 64-bit equivalent is). That in turn contains a reference to a WCB in system space, which is how VMS kept track of an open file -- presumably there is some analogous structure for a comms socket etc.

    So sharing those in-kernel structures is not the hard part -- it would be easy enough to allocate a channel in the CCB array in another process and have it point back to the same in-kernel structures.

    It would be a lot easier without the C RTL data structures and the
    RMS data structures.

    But they exist.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 00:04:09 2024
    On Wed, 2 Oct 2024 19:56:20 -0400, Arne Vajhøj wrote:

    They typical don't close the windows immediately.

    This was for a more interactive app-type thing, not consuming static
    content. Like a chat session or audio/video phone call.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 00:02:49 2024
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:

    On 10/2/2024 7:50 PM, Lawrence D'Oliveiro wrote:

    It would be a lot easier without the C RTL data structures and the RMS
    data structures.

    But they exist.

    VMS doesn’t force you to use them. And I’m not clear what the point of
    them is, for network I/O.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 20:14:20 2024
    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:
    It would be a lot easier without the C RTL data structures and the RMS
    data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally
    rare.

    And I’m not clear what the point of them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor
    over Unix socket as well.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Wed Oct 2 20:18:37 2024
    On 10/2/2024 4:15 PM, Dan Cross wrote:
    If you wanted to
    do this in a real shop, one would hope you'd have some sort of
    caching load balancer in front of your apache servers. Then
    again, Apache is pretty long in the tooth for this kind of
    thing.

    Apache got mod_cache. And there are a few caching reverse proxies
    available - including Varnish.

    But not so interesting for this. This was for dynamic
    content and that would typical not be cached.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 00:44:54 2024
    On Wed, 2 Oct 2024 20:36:48 -0400, Arne Vajhøj wrote:

    Terminal: yes.

    Mailboxes: yes.

    Tapes: yes.

    Disk file: not so much.

    I dabbled with that, too. How do you think RMS was implemented?

    But the C code cannot use it as a file descriptor.

    The C runtime can wrap it in the same sort of thing it does for any other channel.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 00:28:38 2024
    On Wed, 2 Oct 2024 20:14:20 -0400, Arne Vajhøj wrote:

    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:

    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:

    It would be a lot easier without the C RTL data structures and the RMS
    data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally rare.

    I did it all the time. For terminal stuff, it was much easier than trying
    to work through the cumbersome indirection layer imposed by RMS.

    And I’m not clear what the point of them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor
    over Unix socket as well.

    Remember that POSIX has no “RMS” layer. A VMS “channel” might be considered equivalent to a POSIX “file descriptor”, except that “files” are just streams of bytes, and “file descriptor” refers equally well to data on persistent storage, or pipes or sockets. On Linux, it even has
    other uses to do with certain kernel control/notification APIs, not for
    regular data transfer at all.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 20:36:48 2024
    On 10/2/2024 8:28 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:14:20 -0400, Arne Vajhøj wrote:

    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:

    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:

    It would be a lot easier without the C RTL data structures and the RMS >>>> data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally rare.

    I did it all the time. For terminal stuff, it was much easier than trying
    to work through the cumbersome indirection layer imposed by RMS.

    Terminal: yes.

    Mailboxes: yes.

    Tapes: yes.

    Disk file: not so much.

    And I’m not clear what the point of them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor
    over Unix socket as well.

    Remember that POSIX has no “RMS” layer. A VMS “channel” might be considered equivalent to a POSIX “file descriptor”,

    Yes.

    But the C code cannot use it as a file descriptor.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 20:51:54 2024
    On 10/2/2024 8:44 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:36:48 -0400, Arne Vajhøj wrote:
    Terminal: yes.

    Mailboxes: yes.

    Tapes: yes.

    Disk file: not so much.

    I dabbled with that, too.

    It is obviously doable, but it is cumbersome.

    But the C code cannot use it as a file descriptor.

    The C runtime can wrap it in the same sort of thing it does for any other channel.

    It would have to reimplement a lot of RMS functionality to be
    able to properly work with VMS files in an efficient manner.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 01:18:31 2024
    On Wed, 2 Oct 2024 20:51:54 -0400, Arne Vajhøj wrote:

    On 10/2/2024 8:44 PM, Lawrence D'Oliveiro wrote:

    The C runtime can wrap it in the same sort of thing it does for any
    other channel.

    It would have to reimplement a lot of RMS functionality to be able to properly work with VMS files in an efficient manner.

    I don’t see why RMS needs to come into it at all. RMS seems like a poor
    fit for the whole stdio/POSIX I/O model.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Wed Oct 2 21:57:06 2024
    On 10/2/2024 9:18 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:51:54 -0400, Arne Vajhøj wrote:
    On 10/2/2024 8:44 PM, Lawrence D'Oliveiro wrote:
    The C runtime can wrap it in the same sort of thing it does for any
    other channel.

    It would have to reimplement a lot of RMS functionality to be able to
    properly work with VMS files in an efficient manner.

    I don’t see why RMS needs to come into it at all. RMS seems like a poor
    fit for the whole stdio/POSIX I/O model.

    Process A creates a text file and start writing to it, process A send
    the channel to process B, process B want to write more data to it.

    B send "ABC\n" to wrapper.

    What does the wrapper write to disk?

    RFM=STMLF : 0x41 0x42 0x43 0x0A
    RFM=VAR : 0x03 0x00 0x41 0x42 0x43 0x00
    RFM=VFC : ...
    RFM=FIX MRS=512 : ...

    And that is just for sequential files. We also got index-sequential
    and relative files.

    Yes - C IO and RMS IO are not easy to align, but we have RMS whether we
    like it or no.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Hunter Goatley@21:1/5 to Craig A. Berry on Wed Oct 2 22:43:42 2024
    On 10/2/2024 6:35 PM, Craig A. Berry wrote:

    Does VMS need its own natively-developed web server? Who would create it?

    There are at least three that have already been created and have been available for a very long time (though I think Purveyor may no longer be available?).

    Purveyor was great in its day, but its day ended approximately 22 years
    ago. ;-)

    Hunter
    ------
    Hunter Goatley, Process Software, https://www.process.com/ goathunter@goatley.com https://hunter.goatley.com/

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Oct 3 03:45:33 2024
    On Wed, 2 Oct 2024 21:57:06 -0400, Arne Vajhøj wrote:

    Yes - C IO and RMS IO are not easy to align, but we have RMS whether we
    like it or no.

    I’m not sure that RMS does enough (or any) in-system-space coordination
    among different processes to be able to solve the problem you think it is solving in this case.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Thu Sep 26 23:22:00 2024
    On Thu, 26 Sep 2024 19:15:40 -0400, Arne Vajhøj wrote:

    On 9/26/2024 4:40 PM, Lawrence D'Oliveiro wrote:

    On Thu, 26 Sep 2024 09:44:14 -0500, Craig A. Berry wrote:

    Whoever invented the term apparently thought fork() was the only
    way to create a subprocess.

    It is the most natural way in this case, because it creates a complete
    copy of the parent process, which is what you want.

    On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    Not only is that more expensive, it also requires additional setup to
    recreate the effect of fork(2).

    They have one big advantage over fork on VMS.

    They exist!

    Not enough to make up for the performance disadvantage, though ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Thu Sep 26 19:15:40 2024
    On 9/26/2024 4:40 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 09:44:14 -0500, Craig A. Berry wrote:
    Whoever invented the term apparently thought fork() was the only
    way to create a subprocess.

    It is the most natural way in this case, because it creates a complete
    copy of the parent process, which is what you want.

    On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    Not only is that more expensive, it also requires additional setup to recreate the effect of fork(2).

    They have one big advantage over fork on VMS.

    They exist!

    :-)

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Lawrence D'Oliveiro on Thu Sep 26 19:52:30 2024
    On 9/26/24 6:22 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 19:15:40 -0400, Arne Vajhøj wrote:

    On 9/26/2024 4:40 PM, Lawrence D'Oliveiro wrote:

    On Thu, 26 Sep 2024 09:44:14 -0500, Craig A. Berry wrote:

    Whoever invented the term apparently thought fork() was the only
    way to create a subprocess.

    It is the most natural way in this case, because it creates a complete
    copy of the parent process, which is what you want.

    On VMS it will obviously use LIB$SPAWN or SYS$CREPRC.

    Not only is that more expensive, it also requires additional setup to
    recreate the effect of fork(2).

    They have one big advantage over fork on VMS.

    They exist!

    Not enough to make up for the performance disadvantage, though ...

    The ability to restart Apache in a second or so on Linux rather than a
    couple seconds on VMS is nice but has nothing to do with the problem
    Arne reported, which is about performance after the worker processes are started.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Thu Sep 26 21:20:38 2024
    On 9/26/2024 10:30 AM, Craig A. Berry wrote:
    On 9/26/24 7:38 AM, Craig A. Berry wrote:
    On 9/25/24 6:14 PM, Arne Vajhøj wrote:
    Does anyone know internals of Apache on VMS?

    Based on some messages in error_log it looks like
    it uses mailboxes APACHE$AWS_CONTROL_MBX_nn.

    If every request result in mailbox comm between
    master process and a child process, then that could
    slow down things.

    I vaguely remember that there was a separate image installed with
    privileges that increased socket buffer size from 255 bytes to something
    reasonable and these sockets were used as pipes for IPC.

    The following links still seem to work if you want (old) sources:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-ALPHA-SRC-
    KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V20-2-I64-SRC-
    KIT.BCK_SFX_I64EXE

    Trial and error shows that *slightly* later versions are available at
    the same place:

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-ALPHA-SRC- KIT.BCK_SFX_AXPEXE

    https://ftp.hp.com/pub/openvms/apache/CSWS-V21-1-I64-SRC-KIT.BCK_SFX_I64EXE

    I took a look.

    It has:

    [.httpd.server.mpm.prefork]prefork.c with 1350 lines calling fork [.httpd.server.mpm.vms]prefork.c with 3900 lines calling sys$creprc

    So it looks like the porting approach was to reimplement prefork
    more or less from scratch for VMS.

    A very quick search make me think that the mailbox is only used
    for control not for data.

    So I am still stuck.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Craig A. Berry on Fri Sep 27 01:26:13 2024
    On Thu, 26 Sep 2024 19:52:30 -0500, Craig A. Berry wrote:

    The ability to restart Apache in a second or so on Linux rather than a
    couple seconds on VMS is nice but has nothing to do with the problem
    Arne reported, which is about performance after the worker processes are started.

    That could be to do with the more convoluted way to do nondeterministic
    I/O under VMS.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Sep 27 01:26:51 2024
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhøj wrote:

    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though. That and the need for all the ASTs.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Sep 27 02:36:18 2024
    On Thu, 26 Sep 2024 22:17:29 -0400, Arne Vajhøj wrote:

    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:

    That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is a very common
    design today. DEC was ahead of time with that.

    Set attention AST → wait for AST to trigger → queue actual I/O → wait for AST to signal completion. Too many system calls and transitions back and
    forth between user and kernel modes.

    Note that Linux servers can efficiently handle thousands of concurrent
    client connections without this.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Thu Sep 26 22:17:29 2024
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhøj wrote:
    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though.

    If it is only used for the parent to signal the child to terminate?

    That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is
    a very common design today. DEC was ahead of time with
    that.

    And implementation wise then the AST's worked on VAX 700
    series 45 years ago. Todays systems are extremely much
    faster - maybe a factor 10000 faster.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Thu Oct 3 12:06:42 2024
    On 2024-10-02, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 10/2/2024 2:15 PM, Simon Clubley wrote:

    Are you closing down the current instance of the client and then
    starting up a new instance of the client ?

    or

    Are you keeping the existing process running and creating a new
    instance from it ?

    Existing process.

    In either case, are you _cleanly_ and _fully_ closing the existing
    connection _before_ you exit or create a new connection in the existing
    process ?

    No.

    Because browser instances do not do that. Browsers keeps
    connections open for a long time. I believe 300 seconds is common.


    In that case, in order to accurately duplicate this behaviour, you need a
    VMS webserver capable of holding open 300 (or whatever the number of test clients is you are using) connections at the same time.

    This is a normal capabilty for a modern Linux Apache server BTW.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Thu Oct 3 12:11:07 2024
    In article <vdknst$3dnpf$6@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 4:15 PM, Dan Cross wrote:
    If you wanted to
    do this in a real shop, one would hope you'd have some sort of
    caching load balancer in front of your apache servers. Then
    again, Apache is pretty long in the tooth for this kind of
    thing.

    Apache got mod_cache. And there are a few caching reverse proxies
    available - including Varnish.

    But not so interesting for this. This was for dynamic
    content and that would typical not be cached.

    Load balancing is the critical part, here.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to Hunter Goatley on Thu Oct 3 12:10:46 2024
    On 2024-10-02, Hunter Goatley <goathunter@goatley.com> wrote:
    On 10/2/2024 6:35 PM, Craig A. Berry wrote:

    Does VMS need its own natively-developed web server? Who would create it? >>
    There are at least three that have already been created and have been
    available for a very long time (though I think Purveyor may no longer be
    available?).

    Purveyor was great in its day, but its day ended approximately 22 years
    ago. ;-)


    Careful Hunter, or you will wake Bob up... :-)

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 14:27:55 2024
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

    And what is the "problem" that
    you are imagining here? Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    Arne



    Are you assuming Apache is a well designed and implemented application?

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 14:29:19 2024
    On 10/2/2024 11:30 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

    And what is the "problem" that
    you are imagining here? Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    And the numbers are low due to keep alive.

    Basically Apache on VMS keep an entire process around for
    a kept alive connection.

    When Apache configuration does not allow more
    processes to start then new requests get queued
    until keep alive starts to timeout and processes
    free up.

    And one can not just increase number of processes
    allowed because they use 25 MB each. The system
    runs out of memory/pagefile fast.

    An it does not help that if Apache kills some
    processes then it is expensive to start a new one again,
    which means that either the large number of memory
    consuming processes are kept around or Apache
    will be slow to adjust to increasing load.

    Arne



    Are you assuming that Apache is a well designed and implemented application?

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Thu Oct 3 18:41:11 2024
    In article <vdmnof$3r08j$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/2/2024 11:20 AM, Arne Vajhøj wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.

    That request will block if the server can't serve it
    because all processes are busy.

    And what is the "problem" that
    you are imagining here? Please be specific.

    Go back to the first post in the thread.

    The numbers for Apache are low. Much lower than
    for other servers.

    Are you assuming Apache is a well designed and implemented application?

    Apache was fine for its era. It's the way that Arne is using it
    that's broken. Anyone wanting to host a high-performance web
    app on it would put a load balancer in front of it; that would,
    in turn, mux requests from actual clients and distribute them
    across a set of backend Apache instances. Caching would help
    somewhat, too, so that static resources (like images) were
    closer to the egress point of one's network (hence why I said,
    "caching load balancer" earlier; why take the latency hit for
    seldom-changing stuff?).

    That sort of architecture is more or less still the way that
    things work, but Apache as the backbone of the whole thing is
    rather long in the tooth. I'm sure it's still used all over, on
    a large number of sites. I'm equally sure if someone serious
    were architecting something today for high volume, low-latency
    web applications, Apache wouldn't be high on the list of servers
    for HTTP. Most would just build a web server directly into
    their application, which is almost trivially easy in a lot of
    modern ecosystems; Go and Rust have very nice libraries that
    make this really easy to do.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Thu Oct 3 14:51:39 2024
    On 10/2/2024 3:13 PM, Dan Cross wrote:

    Arne keeps moving the goal posts of what, exactly, he claims is
    wrong and why, while being cagey about how exactly he's testing
    and what the experimental setup looks like. It's intern-level
    investigation, at best.

    Perhaps the question should be, "what is Arne's goal"?

    In another post he suggested that VSI release sources for their port. Perhaps he is trying to enhance that wish?

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Simon Clubley on Thu Oct 3 14:42:49 2024
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.


    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive settings) or does it always create a brand-new connection for the next request ?

    Simon.


    I don't work much with this kind of stuff, but I have questions?

    If a connection is persistent, then there is already a connection, no need for a
    "brand-new" connection. However, perhaps you're asking whether the client uses an existing connection, or always issues a new connection request?

    In the web services I've implemented in the past, the protocol was rather simple. Request a connection, perform transaction, close connection.

    It did bite us on the ass one time. The client would be requesting inventory status for individual parts. The programmer on the client side (not us) was issuing requests for one part number for each connection. That wasn't good. Once we pointed out to him/her that the protocol would accept multiple part numbers in a single transaction, could be thousands, the problem disappeared.

    The thing is, either have well defined transactions, or, be a "jack-of-all-trades" and do nothing well.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Lawrence D'Oliveiro on Thu Oct 3 14:56:14 2024
    On 10/2/2024 5:48 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 10:00:02 -0400, Arne Vajhøj wrote:

    Or taking code designed for a different OS and expecting it to work on
    another OS.

    Does VMS need its own natively-developed web server? Who would create it?


    Uh, that would be:

    Mark Daniel and WASD

    or

    David Jones and OSU

    as two examples.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 14:59:03 2024
    On 10/2/2024 6:56 PM, Arne Vajhøj wrote:
    On 10/2/2024 5:48 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 10:00:02 -0400, Arne Vajhøj wrote:
    Or taking code designed for a different OS and expecting it to work on
    another OS.

    Does VMS need its own natively-developed web server? Who would create it?

    2 such exist: OSU and WASD. Thanks to David Jones and Mark Daniels.

    But Apache with a different MPM would do fine as well. The winnt MPM
    would be best fit. But the hybrid process and thread MPM's that
    Linux has used for the last 15-20 years would also fit fine.
    Practically anything but Apache prefork MPM. Porting another MPM
    could be VSI as Apache is supported by VSI or a volunteer.

    Arne



    Ah-ha, my previous supposition gains traction ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Simon Clubley on Thu Oct 3 14:57:41 2024
    On 10/3/2024 8:10 AM, Simon Clubley wrote:
    On 2024-10-02, Hunter Goatley <goathunter@goatley.com> wrote:
    On 10/2/2024 6:35 PM, Craig A. Berry wrote:

    Does VMS need its own natively-developed web server? Who would create it? >>>
    There are at least three that have already been created and have been
    available for a very long time (though I think Purveyor may no longer be >>> available?).

    Purveyor was great in its day, but its day ended approximately 22 years
    ago. ;-)


    Careful Hunter, or you will wake Bob up... :-)

    Simon.


    Gasp .. please no ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 15:09:59 2024
    On 10/2/2024 8:14 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:
    It would be a lot easier without the C RTL data structures and the RMS
    data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally
    rare.

    Not around here.

    And I’m not clear what the point of
    them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor
    over Unix socket as well.

    I thought sockets was the issue?

    Before we closed down operations, I was looking at passing a socket to another process. Not sure if I could, didn't get that far. From the docs, I should be able to open a socket with the SHARE flag, then have another process open the same socket.


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 15:11:54 2024
    On 10/2/2024 8:36 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:28 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:14:20 -0400, Arne Vajhøj wrote:

    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:

    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:

    It would be a lot easier without the C RTL data structures and the RMS >>>>> data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally rare.

    I did it all the time. For terminal stuff, it was much easier than trying
    to work through the cumbersome indirection layer imposed by RMS.

    Terminal: yes.

    Mailboxes: yes.

    Tapes: yes.

    Disk file: not so much.

    And I’m not clear what the point of them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor >>> over Unix socket as well.

    Remember that POSIX has no “RMS” layer. A VMS “channel” might be
    considered equivalent to a POSIX “file descriptor”,

    Yes.

    But the C code cannot use it as a file descriptor.

    So, don't use C ...


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 15:13:41 2024
    On 10/2/2024 8:51 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:44 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:36:48 -0400, Arne Vajhøj wrote:
    Terminal: yes.

    Mailboxes: yes.

    Tapes: yes.

    Disk file: not so much.

    I dabbled with that, too.

    It is obviously doable, but it is cumbersome.

    But the C code cannot use it as a file descriptor.

    The C runtime can wrap it in the same sort of thing it does for any other
    channel.

    It would have to reimplement a lot of RMS functionality to be
    able to properly work with VMS files in an efficient manner.

    VMS files are not all RMS files. QIO works fine on VMS files. Think not? Then
    what do you think RMS uses to access VMS files?


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Lawrence D'Oliveiro on Thu Oct 3 15:18:24 2024
    On 10/2/2024 11:45 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 21:57:06 -0400, Arne Vajhøj wrote:

    Yes - C IO and RMS IO are not easy to align, but we have RMS whether we
    like it or no.

    I’m not sure that RMS does enough (or any) in-system-space coordination among different processes to be able to solve the problem you think it is solving in this case.


    RMS global buffers might help ...

    Global sections can also be helpful ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to All on Thu Oct 3 15:16:29 2024
    On 10/2/2024 9:57 PM, Arne Vajhøj wrote:
    On 10/2/2024 9:18 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 20:51:54 -0400, Arne Vajhøj wrote:
    On 10/2/2024 8:44 PM, Lawrence D'Oliveiro wrote:
    The C runtime can wrap it in the same sort of thing it does for any
    other channel.

    It would have to reimplement a lot of RMS functionality to be able to
    properly work with VMS files in an efficient manner.

    I don’t see why RMS needs to come into it at all. RMS seems like a poor
    fit for the whole stdio/POSIX I/O model.

    Process A creates a text file and start writing to it, process A send
    the channel to process B, process B want to write more data to it.

    B send "ABC\n" to wrapper.

    What does the wrapper write to disk?

    RFM=STMLF : 0x41 0x42 0x43 0x0A
    RFM=VAR : 0x03 0x00 0x41 0x42 0x43 0x00
    RFM=VFC : ...
    RFM=FIX MRS=512 : ...

    And that is just for sequential files. We also got index-sequential
    and relative files.

    Yes - C IO and RMS IO are not easy to align, but we have RMS whether we like it
    or no.

    Arne



    And if you don't like RMS?

    DAS and VIO are two products that I have some passing familiarity with.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Thu Oct 3 20:28:58 2024
    In article <vdmp51$3r91s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/2/2024 3:13 PM, Dan Cross wrote:

    Arne keeps moving the goal posts of what, exactly, he claims is
    wrong and why, while being cagey about how exactly he's testing
    and what the experimental setup looks like. It's intern-level
    investigation, at best.

    Perhaps the question should be, "what is Arne's goal"?

    In another post he suggested that VSI release sources for their port. Perhaps >he is trying to enhance that wish?

    He'd probably have better luck asking VSI to do that, as opposed
    to posting here.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Robert A. Brooks@21:1/5 to Dan Cross on Thu Oct 3 16:52:47 2024
    On 10/3/2024 4:28 PM, Dan Cross wrote:
    In article <vdmp51$3r91s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/2/2024 3:13 PM, Dan Cross wrote:

    Arne keeps moving the goal posts of what, exactly, he claims is
    wrong and why, while being cagey about how exactly he's testing
    and what the experimental setup looks like. It's intern-level
    investigation, at best.

    Perhaps the question should be, "what is Arne's goal"?

    In another post he suggested that VSI release sources for their port. Perhaps
    he is trying to enhance that wish?

    He'd probably have better luck asking VSI to do that, as opposed
    to posting here.

    I'm trying to sort this out; we appear to have some open source stuff on github, so
    imagine that's how we'd made the Apache sources available.


    --
    -- Rob

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Thu Oct 3 20:40:33 2024
    In article <vdmokf$3r6ke$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/2/2024 1:52 PM, Simon Clubley wrote:
    On 2024-10-02, Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 11:07 AM, Dan Cross wrote:
    In article <vdjmq4$37f8q$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/2/2024 10:47 AM, Dan Cross wrote:
    [snip]
    You do not seem to understand how this is qualitatively
    different from your test program not sending `Connection: close`
    with its single request per connection, and then blocking until
    the server times it out.

    It is qualitative different from what you are imaging.

    The client does not block until the server times out.

    So what, exactly, does it do?

    It moves on to next request.


    Does it reuse an existing connection for the next request (which is
    what you have told the server you are going to do due to your keep-alive
    settings) or does it always create a brand-new connection for the next
    request ?

    I don't work much with this kind of stuff, but I have questions?

    If a connection is persistent, then there is already a connection, no need for a
    "brand-new" connection. However, perhaps you're asking whether the client uses
    an existing connection, or always issues a new connection request?

    I think the last place I saw Arne's goalposts, he was trying to
    match the behavior he expects from a bunch of "browser" users;
    these would presumably connect to his service independently, but
    if they tied up a bunch of resources with idle connections, they
    would starve other users. The issue here is that an Apache
    instance in the configuration he's using is only capable of
    handling a single _connection_ per instance; if that connection
    is idle, then that instance is blocked from performing otherwise
    useful work.

    The issue here is that a browser may open a connection to the
    server and the user may wander away; if that connection is
    persistent, then it's going to tie up an Apache instance, since
    the user has gone to get a cup of coffee or whatever and isn't
    actively using it.

    Of course, this isn't specific to VMS, or a function of how VSI
    ported it or whatever else Arne initially thought. The issue
    was, Arne insisting that his test driver wasn't using persistent
    connections, that it actually was since he didn't know to send a
    `Connection: close` header with HTTP/1.1 to turn off
    keep-alives. It's not a bug in Apache, either, despite his
    protestations that it was because disabling keep-alive on the
    server increased throughput for him; it's curious that he would
    do that for the exact behavior he claimed he was warning people
    about 20 years ago.

    It's odd that he hadn't heard about Unix file descriptor
    passing, which has been around since 1983; particularly since
    when I suggested that a way to build an application like this
    is for a master process to accept a connection and then pass it
    off to a worker process and he said, "that's how it's usually
    done." Given that he was unaware of the mechanism by which one
    might transfer the connection from one process to another, one
    must wonder how he thought it was done?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Dan Cross on Thu Oct 3 16:22:03 2024
    On 10/3/24 3:40 PM, Dan Cross wrote:

    The issue here is that a browser may open a connection to the
    server and the user may wander away; if that connection is
    persistent, then it's going to tie up an Apache instance, since
    the user has gone to get a cup of coffee or whatever and isn't
    actively using it.

    Of course, this isn't specific to VMS, or a function of how VSI
    ported it or whatever else Arne initially thought.

    What's specific to VMS is that pre-fork MPM is the only game in town if
    you want to use Apache. Whether the other mechanisms in use on other
    platforms and designed specifically to address the problem Arne
    encountered could be made to work on VMS is an open question, but not
    something anyone outside VSI could try without the sources. I think
    event is out because there is no kqueue or epoll. The worker model
    might be possible. Or a custom one using ASTs instead of pthreads.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Craig A. Berry on Thu Oct 3 21:41:43 2024
    On Thu, 3 Oct 2024 16:22:03 -0500, Craig A. Berry wrote:

    Or a custom one using ASTs instead of pthreads.

    Trying to work at the AST level would be a lot more complex than doing it
    with threads. That’s why threads were invented.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to arne@vajhoej.dk on Fri Sep 27 13:00:33 2024
    On 2024-09-26, Arne Vajhj <arne@vajhoej.dk> wrote:
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhj wrote:
    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though.

    If it is only used for the parent to signal the child to terminate?

    That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is
    a very common design today. DEC was ahead of time with
    that.

    And implementation wise then the AST's worked on VAX 700
    series 45 years ago. Todays systems are extremely much
    faster - maybe a factor 10000 faster.


    Can you try this on an Alpha system (emulated or otherwise) and see
    how the figures compare ?

    Just wondering if this performance overhead is something that is x86-64 specific.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Fri Sep 27 09:55:48 2024
    On 9/27/2024 9:18 AM, Craig A. Berry wrote:
    On 9/26/24 9:17 PM, Arne Vajhøj wrote:
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhøj wrote:
    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though.

    If it is only used for the parent to signal the child to terminate?

                                         That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is
    a very common design today. DEC was ahead of time with
    that.

    And implementation wise then the AST's worked on VAX 700
    series 45 years ago. Todays systems are extremely much
    faster - maybe a factor 10000 faster.

    There are some limitations around ASTs, especially when mixed with
    threads.  The definitive wizard article is here:

    https://forum.vmssoftware.com/viewtopic.php?t=5198

    Technically interesting.

    But I don't think it is a big problem. To me it is either an event
    driven model with single thread and everything non-blocking where
    AST's make sense or a thread model with multiple threads and everything blocking and no need for AST's.

    But I think your basic question is why Apache is slower than Tomcat,
    right?

    Yes - it can be worded that way.

    The question is why Apache (with PHP but that does not seem to matter)
    is so slow.

    Tomcat (with Quercus to provide PHP support) having much higher
    numbers on the same system proves that it is not HW or VMS.

    Also Apache on Windows on same CPU have much higher numbers
    (number of threads have been bumped).

      The only thing I can think of that hasn't already been mentioned
    is that Tomcat code is JIT-compiled, which is likely to be pretty good, optimized code, whereas Apache is probably either cross-compiled or native-compiled with an early enough field test compiler that there are
    no optimizations.

    That is a possible explanation.

    But the difference in numbers are crazy big.

    Apache getting a static text file with 2 bytes: 22 req/sec

    Tomcat with Quercus and PHP getting data out of a MySQL database on
    Windows and outputting HTML: over 200 req/sec

    Tomcat using JSP (which get triple compiled) getting data out of a MySQL database on Windows (with db connection pool) and outputting HTML: over
    600 req/sec.

    My gut feeling is that cross-compilation may contribute to but not
    fully explain the difference.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 09:59:16 2024
    On 9/26/2024 10:36 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 22:17:29 -0400, Arne Vajhøj wrote:
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is a very common
    design today. DEC was ahead of time with that.

    Set attention AST → wait for AST to trigger → queue actual I/O → wait for
    AST to signal completion. Too many system calls and transitions back and forth between user and kernel modes.

    I don't think anyone would use that flow.

    You setup a read attention AST, it triggers and then you know that
    there are data to be read. There is no reason to make reading async
    then, because you know it will not block.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to All on Fri Sep 27 08:18:07 2024
    On 9/26/24 9:17 PM, Arne Vajhøj wrote:
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhøj wrote:
    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though.

    If it is only used for the parent to signal the child to terminate?

                                         That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is
    a very common design today. DEC was ahead of time with
    that.

    And implementation wise then the AST's worked on VAX 700
    series 45 years ago. Todays systems are extremely much
    faster - maybe a factor 10000 faster.

    There are some limitations around ASTs, especially when mixed with
    threads. The definitive wizard article is here:

    https://forum.vmssoftware.com/viewtopic.php?t=5198

    But I think your basic question is why Apache is slower than Tomcat,
    right? The only thing I can think of that hasn't already been mentioned
    is that Tomcat code is JIT-compiled, which is likely to be pretty good, optimized code, whereas Apache is probably either cross-compiled or native-compiled with an early enough field test compiler that there are
    no optimizations.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Simon Clubley on Fri Sep 27 10:26:02 2024
    On 9/27/2024 9:00 AM, Simon Clubley wrote:
    Can you try this on an Alpha system (emulated or otherwise) and see
    how the figures compare ?

    Just wondering if this performance overhead is something that is x86-64 specific.

    Getting a tiny text file on a slow Alpha emulator gives 5 req/sec.
    Which is damn good compared to the 22 req/sec on 4 VCPU x86-64.
    But then it is probably not a CPU issue.

    I suspect that performance on that slow Alpha emulator would be
    bad doing something more CPU intensive (like actually running PHP).

    The interesting number comparison is:

    Apache: 5 req/sec
    OSU: 100 req/sec

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Fri Sep 27 11:02:26 2024
    On 9/25/2024 11:49 AM, Arne Vajhøj wrote:
    nop.php also gives 11 req/sec.

    And nop.txt also gives 11 req/sec.

    So the arrow is definitely pointing towards Apache.

    So either something to speed up Apache or switching to WASD or OSU.

    Increasing spare servers made it possible to increase performance for
    nop.txt from 11 to 22 req/sec.

    But OSU (with no tuning at all) nop.txt gives 373 req/sec. Which may
    not be great, but is good enough for me.

    Maybe I should try get PHP working with OSU or WASD.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 14:16:31 2024
    In article <vd6dh4$nrif$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 9:18 AM, Craig A. Berry wrote:
    On 9/26/24 9:17 PM, Arne Vajhøj wrote:
    On 9/26/2024 9:26 PM, Lawrence D'Oliveiro wrote:
    On Thu, 26 Sep 2024 21:20:38 -0400, Arne Vajhøj wrote:
    A very quick search make me think that the mailbox is only used for
    control not for data.

    Could still be a bottleneck, though.

    If it is only used for the parent to signal the child to terminate?

                                         That and the need for all the ASTs.

    Why should AST's be a problem?

    The "call this function when task is done" approach is
    a very common design today. DEC was ahead of time with
    that.

    And implementation wise then the AST's worked on VAX 700
    series 45 years ago. Todays systems are extremely much
    faster - maybe a factor 10000 faster.

    There are some limitations around ASTs, especially when mixed with
    threads.  The definitive wizard article is here:

    https://forum.vmssoftware.com/viewtopic.php?t=5198

    Technically interesting.

    But I don't think it is a big problem. To me it is either an event
    driven model with single thread and everything non-blocking where
    AST's make sense or a thread model with multiple threads and everything >blocking and no need for AST's.

    But I think your basic question is why Apache is slower than Tomcat,
    right?

    Yes - it can be worded that way.

    The question is why Apache (with PHP but that does not seem to matter)
    is so slow.

    Tomcat (with Quercus to provide PHP support) having much higher
    numbers on the same system proves that it is not HW or VMS.

    Also Apache on Windows on same CPU have much higher numbers
    (number of threads have been bumped).

      The only thing I can think of that hasn't already been mentioned
    is that Tomcat code is JIT-compiled, which is likely to be pretty good,
    optimized code, whereas Apache is probably either cross-compiled or
    native-compiled with an early enough field test compiler that there are
    no optimizations.

    That is a possible explanation.

    But the difference in numbers are crazy big.

    Apache getting a static text file with 2 bytes: 22 req/sec

    Tomcat with Quercus and PHP getting data out of a MySQL database on
    Windows and outputting HTML: over 200 req/sec

    Tomcat using JSP (which get triple compiled) getting data out of a MySQL >database on Windows (with db connection pool) and outputting HTML: over
    600 req/sec.

    My gut feeling is that cross-compilation may contribute to but not
    fully explain the difference.

    Almost certainly not; this is an IO bound application, not CPU
    bound.

    My strong suspicion is that what you're seeing is the result of
    a serious impedance mismatch between the multi-process model
    Apache was written to use, and its realization using the event
    signalling infrastructure on VMS. You're undoubtedly hitting
    some sort of serialization point, but with added overhead; at
    that point, Amdahl's law dominates.

    Again, I would try to establish a baseline. Cut out the MPM
    stuff as much as you can; ideally, see what kind of numbers you
    can get fetching your text file from a single Apache process.
    Simply adding more threads or worker processes is unlikely to
    significantly increase performance, and indeed the numbers you
    posted are typical of performance collapse one usually sees due
    to some kind of contention bottleneck.

    Some things to consider: are you creating a new network
    connection for each incoming request? It's possible that that's
    hitting a single listener, which is then trying to dispatch the
    connection to an available worker, using some mechanism that is
    slow on VMS. Is there a profiler available? If you can narrow
    down where it's spending its time, that'd provide a huge clue.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 12:06:09 2024
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    Note that even if it had performed great then it would not
    have been a solution because the real thing the PHP scripts
    has significant latency when interacting with external database
    so parallelization is a must.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Chris Townley on Fri Sep 27 12:47:18 2024
    On 9/27/2024 12:28 PM, Chris Townley wrote:
    I would have thought you would have done something with Java, then used tomcat

    If I were to create a web app on VMS to be used for a specific
    purpose, then I would probably chose something JVM based.

    JSF (that I actually like!), Spring MVC or Grails.

    (JSF would mean Tomcat, Spring MVC either Tomcat or Spring Boot and
    Grails either Tomcat or standalone)

    But even though I have a preference for everything J, then
    I am also interested in other stuff.

    And now I wanted to take a deeper dive in Apache and PHP -
    especially those low performance numbers.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to All on Fri Sep 27 17:28:45 2024
    On 27/09/2024 17:06, Arne Vajhøj wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj  <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    Note that even if it had performed great then it would not
    have been a solution because the real thing the PHP scripts
    has significant latency when interacting with external database
    so parallelization is a must.

    Arne


    I would have thought you would have done something with Java, then used
    tomcat

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 12:41:03 2024
    On 9/27/2024 10:16 AM, Dan Cross wrote:
    In article <vd6dh4$nrif$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 9:18 AM, Craig A. Berry wrote:
      The only thing I can think of that hasn't already been mentioned >>> is that Tomcat code is JIT-compiled, which is likely to be pretty good,
    optimized code, whereas Apache is probably either cross-compiled or
    native-compiled with an early enough field test compiler that there are
    no optimizations.

    That is a possible explanation.

    But the difference in numbers are crazy big.

    Apache getting a static text file with 2 bytes: 22 req/sec

    Tomcat with Quercus and PHP getting data out of a MySQL database on
    Windows and outputting HTML: over 200 req/sec

    Tomcat using JSP (which get triple compiled) getting data out of a MySQL
    database on Windows (with db connection pool) and outputting HTML: over
    600 req/sec.

    My gut feeling is that cross-compilation may contribute to but not
    fully explain the difference.

    Almost certainly not; this is an IO bound application, not CPU
    bound.

    With static content yes.

    With dynamic content and the volume Apache+mod_php delivers yes.

    With dynamic content and high volume then CPU can matter. Tomcat
    and Quercus can do over 200 req/sec, but CPU utilization fluctuate
    between 150% and 250% - 4 VCPU used so not CPU bound, but could
    have been if it had been just 2 VCPU.

    My strong suspicion is that what you're seeing is the result of
    a serious impedance mismatch between the multi-process model
    Apache was written to use, and its realization using the event
    signalling infrastructure on VMS.

    Yes.

    Or actually slightly worse.

    Prefork MPM is the multi-process model used in Apache 1.x - it is still
    around in Apache 2.x, but Apache 2.x on Linux use event or worker
    MPM (that are a mix of processes and threads) and Apache 2.x on Windows
    use winnt MPM (that is threads only).

    Again, I would try to establish a baseline. Cut out the MPM
    stuff as much as you can;

    MPM is the core of the server.

    ideally, see what kind of numbers you
    can get fetching your text file from a single Apache process.
    Simply adding more threads or worker processes is unlikely to
    significantly increase performance, and indeed the numbers you
    posted are typical of performance collapse one usually sees due
    to some kind of contention bottleneck.

    It increases but not enough.

    1 -> 0.1 req/sec
    150 -> 11 req/sec
    300 -> 22 req/sec

    Some things to consider: are you creating a new network
    connection for each incoming request?

    Yes. Having the load test program keep connections alive
    would be misleading as real world clients would be on different
    systems.

    It's possible that that's
    hitting a single listener, which is then trying to dispatch the
    connection to an available worker,

    That is the typical web server model.

    using some mechanism that is
    slow on VMS.

    It is a good question how Apache on VMS is actually doing that.

    All thread based solutions (OSU, Tomcat etc.) just pass a
    pointer/reference in memory to the thread. Easy.

    Fork create a process copy with the open socket. I am not quite
    sure about the details of how it works, but it works.

    If the model on VMS is:

    ---(HTTP)---parent---(IPC)---child

    then it could explain being so slow.

    I may have to read some of those bloody 3900 lines of code (in a
    single file!).

    Is there a profiler available? If you can narrow
    down where it's spending its time, that'd provide a huge clue.

    Or I take another path.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 19:16:31 2024
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    Note that even if it had performed great then it would not
    have been a solution because the real thing the PHP scripts
    has significant latency when interacting with external database
    so parallelization is a must.

    We're not at the point of discussing solutions. You still don't
    understand what the actual problem is; we're trying to figure
    that out right now.

    Again, it's about understanding the baseline performance
    characteristics first. Your goal right now ought to be figure
    out why requests for a simple static resource, like a text file,
    are so slow; the point by trying something simple is to reduce
    noise due to confounding variables.

    The fact that this is as slow as it is tells you something. Had
    this performed better, that would tell you something as well,
    but in this case, you know that there's some sort of basic slow
    down even in the simplest cases. If you can figure out why that
    is, and address it, _then_ you move on to re-evaluating your
    actual use case, and if necessary, investigate other slow downs.
    But right now, there's little point in doing that: you know you
    see a non-linear slowdown as you increase threads (you _did_
    notice that, right?).

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 19:40:48 2024
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    How long does it take to serve a single request?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 15:27:14 2024
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 19:39:21 2024
    In article <vd6n70$q3fm$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 10:16 AM, Dan Cross wrote:
    In article <vd6dh4$nrif$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 9:18 AM, Craig A. Berry wrote:
      The only thing I can think of that hasn't already been mentioned >>>> is that Tomcat code is JIT-compiled, which is likely to be pretty good, >>>> optimized code, whereas Apache is probably either cross-compiled or
    native-compiled with an early enough field test compiler that there are >>>> no optimizations.

    That is a possible explanation.

    But the difference in numbers are crazy big.

    Apache getting a static text file with 2 bytes: 22 req/sec

    Tomcat with Quercus and PHP getting data out of a MySQL database on
    Windows and outputting HTML: over 200 req/sec

    Tomcat using JSP (which get triple compiled) getting data out of a MySQL >>> database on Windows (with db connection pool) and outputting HTML: over
    600 req/sec.

    My gut feeling is that cross-compilation may contribute to but not
    fully explain the difference.

    Almost certainly not; this is an IO bound application, not CPU
    bound.

    With static content yes.

    Correct. That's all you ought to be looking at under you
    understand why that's slow.

    With dynamic content and the volume Apache+mod_php delivers yes.

    Maybe, but without a profile you really don't know. But beyond
    that, it is currently irrelevant. You see approximately the
    same numbers with static and dynamic content; this heavily
    implies that the dynamic content case is not related to the
    present slow-down, including it now is premature, and likely
    just masks what's _actually_ wrong.

    With dynamic content and high volume then CPU can matter. Tomcat
    and Quercus can do over 200 req/sec, but CPU utilization fluctuate
    between 150% and 250% - 4 VCPU used so not CPU bound, but could
    have been if it had been just 2 VCPU.

    See above. You know that there's a problem with Apache and
    static content, but you don't know _what_ that problem is. Why
    would you jump ahead of yourself worrying about things like that
    until you actually understand what's going on?

    In this case, concentrating on static content, CPU time consumed
    by Apache itself due to poor optimization or something seems
    like a low-probability root cause of the performance problems
    you are seeing, as static file service like this is IO, not
    compute, bound. Keep your eye on the ball.

    My strong suspicion is that what you're seeing is the result of
    a serious impedance mismatch between the multi-process model
    Apache was written to use, and its realization using the event
    signalling infrastructure on VMS.

    Yes.

    Maybe. You really haven't done enough investigation to know, at
    least going by what you've reported here.

    Or actually slightly worse.

    Prefork MPM is the multi-process model used in Apache 1.x - it is still >around in Apache 2.x, but Apache 2.x on Linux use event or worker
    MPM (that are a mix of processes and threads) and Apache 2.x on Windows
    use winnt MPM (that is threads only).

    Ok, sure. But as you posted earlier, Apache on VMS, as you're
    using it, is using the MPM model, no?

    Again, I would try to establish a baseline. Cut out the MPM
    stuff as much as you can;

    MPM is the core of the server.

    No, you misunderstand. Try to cut down on contention due to
    coordination between multiple entities; you do this by
    _lowering_ the number of things at play (processes, threads,
    whatever). The architecture of the server is irrelevant in
    this case; what _is_ relevant is minimizing concurrency in its
    _configuration_. Does that make sense?

    ideally, see what kind of numbers you
    can get fetching your text file from a single Apache process.
    Simply adding more threads or worker processes is unlikely to
    significantly increase performance, and indeed the numbers you
    posted are typical of performance collapse one usually sees due
    to some kind of contention bottleneck.

    It increases but not enough.

    1 -> 0.1 req/sec
    150 -> 11 req/sec
    300 -> 22 req/sec

    Some things to consider: are you creating a new network
    connection for each incoming request?

    Yes. Having the load test program keep connections alive
    would be misleading as real world clients would be on different
    systems.

    Again, you're getting ahead of yourself. Try simulating a
    single client making multiple, repeated tests to a single
    server, ideally reusing a single HTTP connection. This will
    tell you whether the issue is with query processing _inside_
    the server, or if it has something to do with handling new
    connections for each request. If you use HTTP keep alives
    and the number of QPS jumps up, you've narrowed down your
    search space. If it doesn't, you've eliminated one more
    variable, and again, you've cut down on your search space.

    Does that make sense?

    It's possible that that's
    hitting a single listener, which is then trying to dispatch the
    connection to an available worker,

    That is the typical web server model.

    No, it is _a_ common model, but not _the_ "typical" model. For
    instance, many high-performance web solutions are built on an
    asynchronous model, which effectively implement state machines
    where state transitions yield callbacks that are distributed
    across a collection of executor threads. There's no single
    "worker" or dedicated handoff.

    Moreover, there are many different _ways_ to implement the
    "listener hands connection to worker" model, and it _may_ be
    that the way that Apache on VMS is trying to do it is
    inherently slow. We don't know, do we? But that's what we're
    trying to figure out, and that's why I'm encouraging you to
    start simply and build on what you can actually know from
    observation, as opposed to faffing about making guesses.

    using some mechanism that is
    slow on VMS.

    It is a good question how Apache on VMS is actually doing that.

    All thread based solutions (OSU, Tomcat etc.) just pass a
    pointer/reference in memory to the thread. Easy.

    Fork create a process copy with the open socket. I am not quite
    sure about the details of how it works, but it works.

    If the model on VMS is:

    ---(HTTP)---parent---(IPC)---child

    then it could explain being so slow.

    I may have to read some of those bloody 3900 lines of code (in a
    single file!).

    Precisely. And maybe run some more experiments.

    Is there a profiler available? If you can narrow
    down where it's spending its time, that'd provide a huge clue.

    Or I take another path.

    This is a useful exercise either way; getting to the root cause
    of a problem like this may teach you something you could apply
    to other, similar, problems in the future.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 16:11:36 2024
    On 9/27/2024 3:40 PM, Dan Cross wrote:
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests >>>>>> from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    How long does it take to serve a single request?

    Based on the above information it should be 200 seconds.

    But it is actually more like 340 seconds. So apparently the 0.1
    req/sec is rounded up a bit.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 20:13:50 2024
    In article <vd73ho$q3hr$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:40 PM, Dan Cross wrote:
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests >>>>>>> from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down.
    What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    How long does it take to serve a single request?

    Based on the above information it should be 200 seconds.

    But it is actually more like 340 seconds. So apparently the 0.1
    req/sec is rounded up a bit.

    Ok, just to clarify, you hit the web server with a single
    request for a small static resource, while no other traffic was
    hitting it, and that request took more than _five minutes_ to
    complete?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 16:22:02 2024
    On 9/27/2024 4:13 PM, Dan Cross wrote:
    In article <vd73ho$q3hr$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:40 PM, Dan Cross wrote:
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests >>>>>>>> from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down. >>>>>>> What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    How long does it take to serve a single request?

    Based on the above information it should be 200 seconds.

    But it is actually more like 340 seconds. So apparently the 0.1
    req/sec is rounded up a bit.

    Ok, just to clarify, you hit the web server with a single
    request for a small static resource, while no other traffic was
    hitting it, and that request took more than _five minutes_ to
    complete?

    340 seconds is with 20 client threads.

    With 1 client thread time is 17 seconds.

    As expected.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 20:50:00 2024
    In article <vd745a$q3hr$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 4:13 PM, Dan Cross wrote:
    In article <vd73ho$q3hr$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:40 PM, Dan Cross wrote:
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests >>>>>>>>> from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down. >>>>>>>> What happens if you set these super low, ideally so there's a
    single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding
    requests.

    How long does it take to serve a single request?

    Based on the above information it should be 200 seconds.

    But it is actually more like 340 seconds. So apparently the 0.1
    req/sec is rounded up a bit.

    Ok, just to clarify, you hit the web server with a single
    request for a small static resource, while no other traffic was
    hitting it, and that request took more than _five minutes_ to
    complete?

    340 seconds is with 20 client threads.

    With 1 client thread time is 17 seconds.

    So again, to clarify, the time to issue one request against an
    otherwise idle server and retrieve a small amount of static data
    in response to that request is 17 seconds?

    As expected.

    It is always good to verify. I might add that there's no
    relevant environment where that's a reasonable expectation.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 17:10:05 2024
    On 9/27/2024 4:50 PM, Dan Cross wrote:
    In article <vd745a$q3hr$3@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 4:13 PM, Dan Cross wrote:
    In article <vd73ho$q3hr$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:40 PM, Dan Cross wrote:
    In article <66f70712$0$711$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 3:16 PM, Dan Cross wrote:
    In article <vd6l5h$pmt5$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/26/2024 11:44 AM, Dan Cross wrote:
    In article <vd1u8j$3qqpg$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides >>>>>>>>>> these numbers are absurd high to handle a simulator doing requests >>>>>>>>>> from just 20 threads.

    But not sure what else I can change.

    My guess is that communications overhead is slowing things down. >>>>>>>>> What happens if you set these super low, ideally so there's a >>>>>>>>> single process handling requests, then see what sort of QPS
    numbers you get for your trivial text file.

    I set it down to 1.

    0.1 req/sec

    So a single request takes 10 seconds? Or you can only make one
    request every 10 seconds, but the time taken to process that
    request is relatively small?

    It is throughput.

    N / time it takes to get response for N requests

    With 20 threads in client then there will always be 20 outstanding >>>>>> requests.

    How long does it take to serve a single request?

    Based on the above information it should be 200 seconds.

    But it is actually more like 340 seconds. So apparently the 0.1
    req/sec is rounded up a bit.

    Ok, just to clarify, you hit the web server with a single
    request for a small static resource, while no other traffic was
    hitting it, and that request took more than _five minutes_ to
    complete?

    340 seconds is with 20 client threads.

    With 1 client thread time is 17 seconds.

    So again, to clarify, the time to issue one request against an
    otherwise idle server and retrieve a small amount of static data
    in response to that request is 17 seconds?

    Yes.

    As expected.

    It is always good to verify. I might add that there's no
    relevant environment where that's a reasonable expectation.

    I was referring the math 17 = 340 / 20.

    There is nothing reasonable about those numbers.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Fri Sep 27 21:18:19 2024
    In article <vd76vd$q3hr$4@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/27/2024 4:50 PM, Dan Cross wrote:
    [snip]
    So again, to clarify, the time to issue one request against an
    otherwise idle server and retrieve a small amount of static data
    in response to that request is 17 seconds?

    Yes.

    As expected.

    It is always good to verify. I might add that there's no
    relevant environment where that's a reasonable expectation.

    I was referring the math 17 = 340 / 20.

    There is nothing reasonable about those numbers.

    Agreed. I reiterate my request from https://comp.os.vms.narkive.com/uWy2ouua/apache-mod-php-performance#post50:
    do those numbers change substantially if you send
    multiple queries over a single connection?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Sep 27 23:13:06 2024
    On Fri, 27 Sep 2024 09:59:16 -0400, Arne Vajhøj wrote:

    You setup a read attention AST, it triggers and then you know that there
    are data to be read. There is no reason to make reading async then,
    because you know it will not block.

    I wouldn’t bother with ASTs at all, though I would use async QIOs with I/O status blocks. Here is my proposed control flow, which is very similar to
    a *nix-style poll loop:

    0) Clear the event flag you are going to use in the next step.
    1) Start the initial set of async QIOs on all the channels I want to
    monitor. Give them all the same event flag to set on completion (e.g. the
    usual default EFN 0). Don’t specify any completion ASTs, but do specify
    I/O status blocks.
    2) Wait for the specified EFN to become set.
    3) Clear that EFN.
    4) Go through all your I/O status blocks, and process all I/Os that have completed (status field ≠ 0). Queue new async I/Os for those channels (and any new ones) as appropriate.
    5) If you still have a nonempty set of async QIOs outstanding (i.e. a
    nonempty set of channels being monitored), then go back to step 2.
    Otherwise, you are shutting down, so stop.

    How does that sound?

    Hmmm ... I just realized ... doesn’t QIO immediately clear the EFN you specify, before queueing the actual I/O request? That might blow the whole thing ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 19:34:07 2024
    On 9/27/2024 7:16 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 12:06:09 -0400, Arne Vajhøj wrote:
    ... PHP scripts has significant latency
    when interacting with external database so parallelization is a must.

    I haven’t noticed such latency (albeit mainly with intranet apps written for an SME),

    Sending SQL query from web server to database server over the network,
    having database server find data and sending data from database server
    to web server over the network takes time. Milliseconds.

    but what I have noticed is getting the data with fewer
    queries is faster than getting the same data with more queries.

    total latency from queries = number of queries * average latency of one
    query

    It adds up.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Fri Sep 27 20:07:13 2024
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    It is a bug in the code.

    Comment in httpd.conf say:

    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.

    It does not say that it will reduce throughput to 1/10'th if on.

    And note that keep alive was not needed for me, but it is needed in many
    other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 20:13:01 2024
    On 9/27/2024 7:55 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 19:34:07 -0400, Arne Vajhøj wrote:
    Sending SQL query from web server to database server over the network,
    having database server find data and sending data from database server
    to web server over the network takes time. Milliseconds.

    You know we can use AF_UNIX sockets within the same machine, right?

    If supported.

    But in that case latency will be small. Microseconds.

    But running application and database on same system is not
    an option if it is a high volume solution or a high availability
    solution with load sharing application and failover database.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Sep 27 23:16:20 2024
    On Fri, 27 Sep 2024 12:06:09 -0400, Arne Vajhøj wrote:

    ... PHP scripts has significant latency
    when interacting with external database so parallelization is a must.

    I haven’t noticed such latency (albeit mainly with intranet apps written
    for an SME), but what I have noticed is getting the data with fewer
    queries is faster than getting the same data with more queries.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Fri Sep 27 23:55:38 2024
    On Fri, 27 Sep 2024 19:34:07 -0400, Arne Vajhøj wrote:

    Sending SQL query from web server to database server over the network,
    having database server find data and sending data from database server
    to web server over the network takes time. Milliseconds.

    You know we can use AF_UNIX sockets within the same machine, right?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Fri Sep 27 21:11:15 2024
    On 9/27/2024 8:38 PM, Dan Cross wrote:
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    Hmm. You had already said that you were _Not_ using keep alives
    because that would somehow mimic multiple machines querying
    simultaneously.

    That is correct.

    The client was not using keep alive.

    But the server was configured to support keep alive.

    Turning that capability off on the server solved the performance
    problem.

    No changes on client.

    No keep alive used before - no keep alive used after.

    Just disabling the capability on the server.

    This was, of course, the area of investigation I had suggested
    to you previously to try and nail down the baseline. I question
    whether this will impact your single query latency, however, or
    whether this is masking it in your benchmark.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    What is your single query latency? Not calculated, but
    actually measured.

    It is a rather uninteresting number.

    But easy to test. It obviously vary a bit, but they
    are all in the 50-100 millisecond range.

    It is a bug in the code.

    The evidence in hand is insufficient to make that claim.

    I believe that server config supporting keep alive
    causing performance to drop to 1/10'th for clients
    not using keep alive is a bug.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Sat Sep 28 00:38:18 2024
    In article <vd7hbi$tgu3$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 9/25/2024 5:10 PM, Arne Vajhøj wrote:
    It must be Apache.

    Apache on VMS is prefork MPM. Yuck.

    MaxSpareServers 10 -> 50
    MaxClients 150 -> 300

    actually did improve performance - double from 11 to 22
    req/sec.

    But the system did not like further increases. And besides
    these numbers are absurd high to handle a simulator doing requests
    from just 20 threads.

    But not sure what else I can change.

    And we have a solution.

    httpd.conf

    KeepAlive On

    KeepAlive Off

    And numbers improve dramatically.

    Hmm. You had already said that you were _Not_ using keep alives
    because that would somehow mimic multiple machines querying
    simultaneously.

    This was, of course, the area of investigation I had suggested
    to you previously to try and nail down the baseline. I question
    whether this will impact your single query latency, however, or
    whether this is masking it in your benchmark.

    nop.txt 281 req/sec
    nop.php 176 req/sec
    real PHP no db con pool 94 req/sec
    real PHP db con pool 103 req/sec

    Numbers are not great, but within acceptable.

    What is your single query latency? Not calculated, but
    actually measured.

    It is a bug in the code.

    The evidence in hand is insufficient to make that claim.

    Comment in httpd.conf say:

    # KeepAlive: Whether or not to allow persistent connections (more than
    # one request per connection). Set to "Off" to deactivate.

    It does not say that it will reduce throughput to 1/10'th if on.

    And note that keep alive was not needed for me, but it is needed in many >other scenarios:
    - web pages with lots of graphics
    - high volume server to server web services

    Actually, it's useful for any scenario in which you may send
    several requests to the same server at roughly the same time,
    such as an HTML document and separate CSS stylesheet, not just
    graphics or "server to server web services".

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Fri Sep 27 21:54:54 2024
    On 9/27/2024 8:13 PM, Arne Vajhøj wrote:
    On 9/27/2024 7:55 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 19:34:07 -0400, Arne Vajhøj wrote:
    Sending SQL query from web server to database server over the network,
    having database server find data and sending data from database server
    to web server over the network takes time. Milliseconds.

    You know we can use AF_UNIX sockets within the same machine, right?

    If supported.

    But in that case latency will be small. Microseconds.

    But running application and database on same system is not
    an option if it is a high volume solution or a high availability
    solution with load sharing application and failover database.

    Note that besides the Unix sockets then some databases also
    supports shared memory.

    That includes both MS SQLserver and Oracle Rdb.

    Oracle Rdb is interesting because it out of the box
    supports loadsharing database, which makes application
    and database on same servers a bit easier.

    In that regard Rdb is pretty cool!

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 01:54:11 2024
    On Fri, 27 Sep 2024 20:13:01 -0400, Arne Vajhøj wrote:

    On 9/27/2024 7:55 PM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 19:34:07 -0400, Arne Vajhøj wrote:

    Sending SQL query from web server to database server over the network,
    having database server find data and sending data from database server
    to web server over the network takes time. Milliseconds.

    You know we can use AF_UNIX sockets within the same machine, right?

    If supported.

    But in that case latency will be small. Microseconds.

    Also loopback network connections should be similarly fast. It’s just that Unix sockets allow peers to verify each other’s identity, to shortcut authentication issues.

    But running application and database on same system is not an option if
    it is a high volume solution ...

    Of course it’s an option. Performance is a tradeoff between conflicting system parameters.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 21:58:57 2024
    On 9/27/2024 9:54 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 20:13:01 -0400, Arne Vajhøj wrote:
    But running application and database on same system is not an option if
    it is a high volume solution ...

    Of course it’s an option. Performance is a tradeoff between conflicting system parameters.

    If volume requires sharding then ...

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 02:01:56 2024
    On Fri, 27 Sep 2024 21:58:57 -0400, Arne Vajhøj wrote:

    On 9/27/2024 9:54 PM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 20:13:01 -0400, Arne Vajhøj wrote:

    But running application and database on same system is not an option
    if it is a high volume solution ...

    Of course it’s an option. Performance is a tradeoff between conflicting
    system parameters.

    If volume requires sharding then ...

    “Sharding” means “split across multiple physical persistent storage”.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 22:13:09 2024
    On 9/27/2024 10:01 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 21:58:57 -0400, Arne Vajhøj wrote:
    On 9/27/2024 9:54 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 20:13:01 -0400, Arne Vajhøj wrote:
    But running application and database on same system is not an option
    if it is a high volume solution ...

    Of course it’s an option. Performance is a tradeoff between conflicting >>> system parameters.

    If volume requires sharding then ...

    “Sharding” means “split across multiple physical persistent storage”.

    It means that you have N active database servers each with 1/N of the
    data (possible with replication to N or 2N passive database servers).

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 02:03:18 2024
    On Fri, 27 Sep 2024 21:54:54 -0400, Arne Vajhøj wrote:

    Note that besides the Unix sockets then some databases also supports
    shared memory.

    That includes both MS SQLserver and Oracle Rdb.

    I wonder what are the biggest-scale applications where these products have
    been deployed?

    Facebook, for example, has billions of active users. And Facebook uses
    MySQL.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 01:55:12 2024
    On Fri, 27 Sep 2024 21:11:15 -0400, Arne Vajhøj wrote:

    I believe that server config supporting keep alive causing performance
    to drop to 1/10'th for clients not using keep alive is a bug.

    I would too, since the very reason keepalive was introduced was to improve performance.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 22:18:39 2024
    On 9/27/2024 10:03 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 21:54:54 -0400, Arne Vajhøj wrote:
    Note that besides the Unix sockets then some databases also supports
    shared memory.

    That includes both MS SQLserver and Oracle Rdb.

    I wonder what are the biggest-scale applications where these products have been deployed?

    Rdb probably not so big. Despite the coolness factor.

    SQLServer is used at a few high volume places like MS own Office 365 web
    and StackExchange.

    Facebook, for example, has billions of active users. And Facebook uses
    MySQL.

    FaceBook have a lot of MySQL/MariaDB servers. Sharded! :-)

    They also use some PostgreSQL.

    And for the the real big data they use HBase.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 02:19:38 2024
    On Fri, 27 Sep 2024 22:13:09 -0400, Arne Vajhøj wrote:

    On 9/27/2024 10:01 PM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 21:58:57 -0400, Arne Vajhøj wrote:

    On 9/27/2024 9:54 PM, Lawrence D'Oliveiro wrote:

    On Fri, 27 Sep 2024 20:13:01 -0400, Arne Vajhøj wrote:

    But running application and database on same system is not an option >>>>> if it is a high volume solution ...

    Of course it’s an option. Performance is a tradeoff between
    conflicting system parameters.

    If volume requires sharding then ...

    “Sharding” means “split across multiple physical persistent storage”.

    It means that you have N active database servers each with 1/N of the
    data (possible with replication to N or 2N passive database servers).

    Quite unnecessary, given that the bottleneck is the usually the latency
    and bandwidth of the persistent storage, not the CPU.

    Particularly since your network connections introduce latency and
    bandwidth limitations of their own.

    See what I mean about “tradeoffs”?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to All on Fri Sep 27 22:27:30 2024
    On 9/27/2024 10:18 PM, Arne Vajhøj wrote:
    On 9/27/2024 10:03 PM, Lawrence D'Oliveiro wrote:
    Facebook, for example, has billions of active users. And Facebook uses
    MySQL.

    FaceBook have a lot of MySQL/MariaDB servers. Sharded! :-)

    Also note that FaceBook are using a rather customized
    version. RocksDB as storage engine not normal InnoDB.
    And they have done some stuff to manage failover and
    replication (Raft based??).

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Lawrence D'Oliveiro on Fri Sep 27 22:42:10 2024
    On 9/27/2024 10:19 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 22:13:09 -0400, Arne Vajhøj wrote:
    On 9/27/2024 10:01 PM, Lawrence D'Oliveiro wrote:
    On Fri, 27 Sep 2024 21:58:57 -0400, Arne Vajhøj wrote:
    If volume requires sharding then ...

    “Sharding” means “split across multiple physical persistent storage”.

    It means that you have N active database servers each with 1/N of the
    data (possible with replication to N or 2N passive database servers).

    Quite unnecessary, given that the bottleneck is the usually the latency
    and bandwidth of the persistent storage, not the CPU.

    I don't think Facebook could move their 1800 MySQL shards onto
    a single server.

    Particularly since your network connections introduce latency and
    bandwidth limitations of their own.

    That is not the problem with shards. Applications are usually OK
    with network latency.

    The problem with shards is that not all data usage models fit
    nicely with sharding.

    If you need to get/update a row by primary key then sharding
    works perfect - you go to the right server and just do it.

    If you need to get/update a number of rows and you don't
    know which servers they are on, then it means querying all
    servers, which both create performance and consistency
    problems.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 05:08:18 2024
    On Fri, 27 Sep 2024 22:18:39 -0400, Arne Vajhøj wrote:

    SQLServer is used at a few high volume places like MS own Office 365 web
    and StackExchange.

    I wonder if it was used as part of that London Stock Exchange system that imploded so spectacularly?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 05:07:49 2024
    On Fri, 27 Sep 2024 22:27:30 -0400, Arne Vajhøj wrote:

    On 9/27/2024 10:18 PM, Arne Vajhøj wrote:

    On 9/27/2024 10:03 PM, Lawrence D'Oliveiro wrote:

    Facebook, for example, has billions of active users. And Facebook uses
    MySQL.

    FaceBook have a lot of MySQL/MariaDB servers. Sharded! :-)

    Also note that FaceBook are using a rather customized version. RocksDB
    as storage engine not normal InnoDB.
    And they have done some stuff to manage failover and replication (Raft based??).

    And being Open Source, they can do that kind of thing.

    They even developed their own PHP implementation, HHVM, which they have open-sourced.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to All on Sat Sep 28 05:09:18 2024
    On Fri, 27 Sep 2024 22:42:10 -0400, Arne Vajhøj wrote:

    If you need to get/update a row by primary key then sharding works
    perfect - you go to the right server and just do it.

    If you need to get/update a number of rows and you don't know which
    servers they are on, then it means querying all servers, which both
    create performance and consistency problems.

    Well, you were the one who brought up sharding, not me ...

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dave Froble on Fri Oct 4 00:00:30 2024
    On 03/10/2024 20:09, Dave Froble wrote:
    On 10/2/2024 8:14 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:
    It would be a lot easier without the C RTL data structures and the RMS >>>> data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally
    rare.

    Not around here.

                                        And I’m not clear what the point of
    them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor
    over Unix socket as well.

    I thought sockets was the issue?

    Before we closed down operations, I was looking at passing a socket to another process.  Not sure if I could, didn't get that far.  From the
    docs, I should be able to open a socket with the SHARE flag, then have another process open the same socket.

    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...


    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to Craig A. Berry on Thu Oct 3 23:30:49 2024
    In article <vdn1tr$3sh36$1@dont-email.me>,
    Craig A. Berry <craigberry@nospam.mac.com> wrote:

    On 10/3/24 3:40 PM, Dan Cross wrote:

    The issue here is that a browser may open a connection to the
    server and the user may wander away; if that connection is
    persistent, then it's going to tie up an Apache instance, since
    the user has gone to get a cup of coffee or whatever and isn't
    actively using it.

    Of course, this isn't specific to VMS, or a function of how VSI
    ported it or whatever else Arne initially thought.

    What's specific to VMS is that pre-fork MPM is the only game in town if
    you want to use Apache. Whether the other mechanisms in use on other >platforms and designed specifically to address the problem Arne
    encountered could be made to work on VMS is an open question, but not >something anyone outside VSI could try without the sources. I think
    event is out because there is no kqueue or epoll. The worker model
    might be possible. Or a custom one using ASTs instead of pthreads.

    Apache is open source, it would be possible for someone outside
    of VSI to mount a porting effort and do a threads backend. But
    I do take your point that that would be a bit of work, versus
    modifying what VSI has already done.

    It strikes me that `select` is surely available; this could be
    used to increase scalability quite a bit. It's not as nice as
    kqueue or epoll or whatnot, but it's better than synchronous
    reads blocking on a single socket. Sadly, any of these would
    be subject to head-of-line blocking, but it would scale _better_
    than the prefork-MPM stuff, provided the time to serve requests
    is relatively small (and it probably is).

    Of course, there's a limit to what one can do with a single HTTP
    server instance using _any_ model, be it threads, pre-created
    processes, or some sort of event-driven async task model. And
    then there's a limit to what one can do on a single machine,
    real or virtual. Once you hit a certain scale, you just have to
    be a bit more circumspect with design, and in particular,
    capacity planning; that's where things like load balancers start
    to come into play.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dan Cross on Fri Oct 4 19:14:41 2024
    On 04/10/2024 18:43, Dan Cross wrote:
    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    I was looking on comp.lang.python and I see a post saying has been
    banned from the list, and requesting anybody seeing usenet posts to
    ignore him!

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Chris Townley on Fri Oct 4 13:28:18 2024
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    On 03/10/2024 20:09, Dave Froble wrote:
    On 10/2/2024 8:14 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:
    It would be a lot easier without the C RTL data structures and the RMS >>>>> data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally
    rare.

    Not around here.

    And I’m not clear what the point of >>>> them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file descriptor >>> over Unix socket as well.

    I thought sockets was the issue?

    Before we closed down operations, I was looking at passing a socket to another
    process. Not sure if I could, didn't get that far. From the docs, I should >> be able to open a socket with the SHARE flag, then have another process open >> the same socket.

    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...



    I'm not sure whether I've been insulted?

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Chris Townley@21:1/5 to Dave Froble on Fri Oct 4 19:12:53 2024
    On 04/10/2024 18:28, Dave Froble wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    On 03/10/2024 20:09, Dave Froble wrote:
    On 10/2/2024 8:14 PM, Arne Vajhøj wrote:
    On 10/2/2024 8:02 PM, Lawrence D'Oliveiro wrote:
    On Wed, 2 Oct 2024 19:57:50 -0400, Arne Vajhøj wrote:
    It would be a lot easier without the C RTL data structures and the >>>>>> RMS
    data structures.

    But they exist.

    VMS doesn’t force you to use them.

    True. But using $QIO(W) or $IO_PERFOM(W) for IO is exceptionally
    rare.

    Not around here.

                                        And I’m not clear what the
    point of
    them is, for network I/O.

    None.

    But I believe you said that on *nix you could transfer a file
    descriptor
    over Unix socket as well.

    I thought sockets was the issue?

    Before we closed down operations, I was looking at passing a socket
    to another
    process.  Not sure if I could, didn't get that far.  From the docs, I
    should
    be able to open a socket with the SHARE flag, then have another
    process open
    the same socket.

    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...



    I'm not sure whether I've been insulted?

    Sorry, I wasn't calling you a troll

    --
    Chris

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Fri Oct 4 17:43:02 2024
    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to news@cct-net.co.uk on Fri Oct 4 18:34:47 2024
    In article <vdpbaj$6l1q$1@dont-email.me>,
    Chris Townley <news@cct-net.co.uk> wrote:
    On 04/10/2024 18:43, Dan Cross wrote:
    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    I was looking on comp.lang.python and I see a post saying has been
    banned from the list, and requesting anybody seeing usenet posts to
    ignore him!

    Shocking. :-)

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Dan Cross on Sun Oct 6 18:12:31 2024
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good
    question.
    As a lurker, I am waiting for the expert answer with interest.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Michael S on Mon Oct 7 00:37:34 2024
    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Second post about this question. At the time I was discussing the technique with Mark Daniels, as he does something similar in WASD.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Michael S on Mon Oct 7 00:35:36 2024
    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Well, some of the issue is in the text of the question. What does one mean be "pass socket"?

    When creating a socket, one can specify it to be shared. What I was doing was passing the information to a worker process, then letting the worker process open the existing socket.

    So, would that be considered "passing an open socket"?

    I can post some of the development code is anyone is interested. I was working on the inter-process communications when I dropped the project. I believe I did
    open the shared socket in the worker process.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Dave Froble on Mon Oct 7 11:07:47 2024
    On Mon, 7 Oct 2024 00:35:36 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP
    socket to child process (or, may be, to unrelated process) under
    VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Well, some of the issue is in the text of the question. What does
    one mean be "pass socket"?

    When creating a socket, one can specify it to be shared. What I was
    doing was passing the information to a worker process, then letting
    the worker process open the existing socket.

    So, would that be considered "passing an open socket"?


    Yes, it would be.

    On Windows one has to go through similar 3-stage procedure:
    - [in parent process] acquire magic record from the open socket by
    means of WSADuplicateSocket()
    - pass the record to child by any of available IPC mechanisms
    - [in child process] use magic record to re-open socket with
    WSASocket()

    I never had a need of for it in practice. Looking at docs it seems
    that the procedure above has at least one inconvenient aspect - the
    target process has to exist at the moment of WSADuplicateSocket() call.
    Still, I suppose that it's better than nothing.

    I can post some of the development code is anyone is interested. I
    was working on the inter-process communications when I dropped the
    project. I believe I did open the shared socket in the worker
    process.


    May be, others are interested in the code.
    For me, I'd rather read textual description of the procedure and war
    story of making it work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Simon Clubley@21:1/5 to Chris Townley on Mon Oct 7 12:07:27 2024
    On 2024-10-04, Chris Townley <news@cct-net.co.uk> wrote:
    On 04/10/2024 18:43, Dan Cross wrote:
    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    I was looking on comp.lang.python and I see a post saying has been
    banned from the list, and requesting anybody seeing usenet posts to
    ignore him!


    He is now trolling comp.lang.ada.

    Simon.

    --
    Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
    Walking destinations on a map are further away than they appear.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Mon Oct 7 15:52:21 2024
    In article <vdvoeq$1jerg$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good
    question.
    As a lurker, I am waiting for the expert answer with interest.

    Well, some of the issue is in the text of the question. What does one mean be >"pass socket"?

    Perhaps an example will be illuminating. See the program at the
    bottom of this post; it is self-contained and, I claim, fairly
    representative of the technique. I wrote and tested it on
    OpenBSD 7.5, on a RISC-V devbox.

    A short explanation: when invoked, this program creates a
    connected, unnamed Unix domain socket pair using the
    `socketpair` system call. It then forks off three other
    (child) processes; these are "workers" that are invoked with one
    end of the socket pair as an argument; the child closes the
    other end and blocks waiting in the `recvmsg` system call,
    waiting to be passed a connected socket.

    Back in the parent, after creating the worker processes, the
    program closes the end of the unnamed socket pair that it passed
    to its children: the effect here is that the parent is holding
    onto one end of the pair, while the children are (correctively)
    holding onto the other. Since there are outstanding references
    on the socket pair, it's still alive. Note that each child is
    blocked waiting to receive a message on the Unix domain socket.

    The parent process then enters a "listener" loop: here, it
    creates a TCP socket on a given port (I used `8200`, but that's
    just a detail) and loops, accepting incoming connections bound
    for that port on any interface.

    This is where it gets interesting, and arguably this is the
    important point: when a client connects, after the `accept` the
    state in the parent is that the process has a fully established
    TCP connection. It then uses the Unix file descriptor passing
    API to transfer that socket to one of the child processes; one
    (that is not otherwise busy; more on that in just a moment) is
    blocked in `recvmsg`, as above and will win a race to be the
    next to read from the childrens' end of the Unix domain socket.
    This has the effect of duplicating the socket descriptor for the just-established connection in the child; the child can now
    execute "normal" IO operations on the socket, communicating with
    the original client, as if it had been the one to accept the
    connection in the first place. Note that the workers never had
    access to the listening socket created by the parent; they were
    forked off before that was created. Of course, the same
    applies to any sockets created when the parent accepted an
    incoming connection.

    The parent then closes the socket descriptor that had been
    created when it `accept`ed the incoming connection, and loops.
    In the client, the program receives the socket descriptor from
    the parent and enters an `echo` loop, doing the obvious thing
    of writing whatever the client sends it back to the client,
    until the client closes the connection.

    This raises an obvious question: given that the child workers
    are is synchronous with respect to receiving sockets from their
    parent, and the `echo` loop makes no attempt at parallelism,
    what happens if all of the workers are busy when a new
    connection is established? The answer is that, modulo some
    buffering in the kernel, things block: the listener will shovel
    new connections into the kernel for as long as the kernel will
    buffer the associated single-byte writes (and other control
    metadata attached to the message copying the IO descriptor to
    one of the children), but then at some point, `sendmsg` will
    block and the kernel will buffer a few incoming connctions that
    haven't been `accept`ed yet, and then it'll start erroring on
    connection establishment. In the meanwhile, IO on the
    established connections that are waiting for a worker to pick
    them up will appear to block. Note that this is basically the
    behavior that Arne saw originally.

    When creating a socket, one can specify it to be shared. What I was doing was >passing the information to a worker process, then letting the worker process >open the existing socket.

    So, would that be considered "passing an open socket"?

    It doesn't really sound like it, but it's hard to say without
    seeing some code. What's missing in the above is any
    description of _how_ the shared socket is shared with the worker
    process, and when.

    The salient characteristic of the Unix model is that a program
    can pass a file descriptor representing any resource to another
    process and that prcoess can interact with that resource as if
    it had opened the descriptor itself (with the privileges of the
    parent). For a socket, for example, the socket in question need
    not exist before the child is created.

    I can post some of the development code is anyone is interested. I was working
    on the inter-process communications when I dropped the project. I believe I did
    open the shared socket in the worker process.

    That might be useful to see.

    - Dan C.

    // Demonstration of a listener process that accepts
    // incoming TCP connections and passes them to a
    // worker process over Unix domain sockets.
    //
    // Dan Cross <cross@gajendra.net>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/uio.h>
    #include <netinet/in.h>

    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    // Sends a file descripter, `fd`, over a Unix domain socket `sd`
    // via the 4.4BSD access rights passing mechanism.
    //
    // Returns 1 on success, -1 on failure.
    int
    sendfd(int sd, int fd)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    // Construct the control message header. Note this is
    // malloc'ed to ensure proper alignment.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;
    memset(ptr, 0, len);
    ptr->cmsg_len = len;
    ptr->cmsg_level = SOL_SOCKET;
    ptr->cmsg_type = SCM_RIGHTS;
    memcpy(CMSG_DATA(ptr), &fd, sizeof(int));

    // We send a single byte of dummy data in case the
    // implementation does not pass control data with an
    // otherwise empty data transfer.
    dummy = 0;
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Construct the message header. Points to the dummy
    // data and the control message header.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = (caddr_t)ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    // Loop in case there's no room in the kernel buffer
    // to send. Cf.Stevens et al.
    do {
    ret = sendmsg(sd, &mh, 0);
    } while (ret == 0);
    free(ptr);

    return ret;
    }

    // Receives a file descriptor over the Unix domain socket `sd`
    // and store it into `*fdp` on success.
    //
    // Returns 1 on success, 0 on EOF, -1 on error.
    int
    recvfd(int sd, int *fdp)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    if (fdp == NULL)
    return -1;

    // Allocate space for the control message.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;

    // Fill in an iovec to receive one byte of dummy data.
    // Required on some systems that do not pass control
    // messages on empty data transfers.
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Fill in the msghdr structure. `recvmsg(2)` will
    // update it.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    ret = recvmsg(sd, &mh, 0);
    if (ret <= 0) {
    free(ptr);
    return ret;
    }
    if (mh.msg_flags != 0) {
    free(ptr);
    return -1;
    }
    memcpy(fdp, CMSG_DATA(ptr), sizeof(int));
    free(ptr);

    return 1;
    }

    void
    dispatcher(int sdworker, int port)
    {
    int sd, nsd;
    struct sockaddr_in sa;
    struct sockaddr_in client;
    socklen_t clientlen;

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0) {
    perror("socket");
    close(sdworker);
    exit(EXIT_FAILURE);
    }
    memset(&sa, 0, sizeof sa);
    sa.sin_family = AF_INET;
    sa.sin_port = htons((unsigned short)port);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sd, (struct sockaddr *)&sa, sizeof sa) < 0) {
    perror("bind");
    close(sdworker);
    close(sd);
    exit(EXIT_FAILURE);
    }
    if (listen(sd, 255) < 0) {
    perror("listen");
    close(sdworker);
    close(sd);
    exit(EXIT_FAILURE);
    }

    memset(&client, 0, sizeof client);
    clientlen = sizeof client;
    while ((nsd = accept(sd, (struct sockaddr *)&client, &clientlen)) >= 0) {
    if (sendfd(sdworker, nsd) < 0) {
    perror("sendfd");
    close(sdworker);
    close(nsd);
    close(sd);
    exit(EXIT_FAILURE);
    }
    close(nsd);
    }
    }

    static void
    echo(int sd)
    {
    char *p;
    char buf[1024];
    ssize_t nb, wb;

    for (;;) {
    nb = read(sd, buf, sizeof buf);
    if (nb < 0)
    perror("read");
    if (nb <= 0)
    return;
    p = buf;
    while (nb > 0) {
    wb = write(sd, p, nb);
    if (wb < 0)
    perror("write");
    if (wb <= 0)
    return;
    nb -= wb;
    p += wb;
    }
    }
    }

    void
    worker(int sddispatcher)
    {
    int sd;

    while (recvfd(sddispatcher, &sd) > 0) {
    echo(sd);
    close(sd);
    }
    }

    int
    main(void)
    {
    int sds[2];
    pid_t pid;

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sds) > 0) {
    perror("socketpair");
    exit(EXIT_FAILURE);
    }

    for (int k = 0; k < 3; k++) {
    pid = fork();
    if (pid < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
    }
    if (pid == 0) { // Child
    close(sds[0]);
    worker(sds[1]);
    exit(EXIT_SUCCESS);
    }
    }
    close(sds[1]);
    dispatcher(sds[0], 8200);

    return EXIT_SUCCESS;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Berryman@21:1/5 to Michael S on Mon Oct 7 10:47:48 2024
    On 10/6/24 9:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does. It listens for a connection, then
    creates a process to handle it. See the description of TCPIP$C_AUXS in
    the TCPIP Services programming documentation.

    As Dave has mentioned, setting SO_SHARE on a socket would be another way
    to accomplish this.

    No guesses as to what method the Apache implementation uses.

    Mark Berryman

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to mark@theberrymans.com on Mon Oct 7 18:01:48 2024
    In article <ve13ck$1pl4l$1@dont-email.me>,
    Mark Berryman <mark@theberrymans.com> wrote:
    On 10/6/24 9:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    Troll or not, but the question about ability to pass open TCP socket to
    child process (or, may be, to unrelated process) under VMS is a good
    question.
    As a lurker, I am waiting for the expert answer with interest.

    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does. It listens for a connection, then
    creates a process to handle it. See the description of TCPIP$C_AUXS in
    the TCPIP Services programming documentation.

    As Dave has mentioned, setting SO_SHARE on a socket would be another way
    to accomplish this.

    Neither of these sounds the same as descriptor passing over Unix
    domain sockets on Unix/Linux; the auxiliary server sounds more
    like `inetd`, in that there's some service that's listening and
    accepting connections on some TCP/IP port, and then creating a
    server to handle each incoming connection.

    SO_SHARE is different again; it appears that the shared socket
    must be created before the subprocesses that use it are created.
    The Unix analogy would be a process that creates a listening
    socket, and then fork's several processes that all `accept` on
    that same socket (they will race one another as to which gets
    to answer complete the `accept` for the next connection). See
    some example code at the bottom of this post; note this is
    different from the earlier socket passing example I posted.

    - Dan C.

    // Demonstration of a multiple processes accepting
    // connections on the same bound listening socket.
    //
    // Dan Cross <cross@gajendra.net>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/wait.h>
    #include <netinet/in.h>

    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    int
    main(void)
    {
    int sd, nsd;
    struct sockaddr_in sa;
    struct sockaddr_in client;
    socklen_t clientlen;
    pid_t pid;

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0) {
    perror("socket");
    exit(EXIT_FAILURE);
    }
    memset(&sa, 0, sizeof sa);
    sa.sin_family = AF_INET;
    sa.sin_port = htons((unsigned short)8200);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sd, (struct sockaddr *)&sa, sizeof sa) < 0) {
    perror("bind");
    close(sd);
    exit(EXIT_FAILURE);
    }
    if (listen(sd, 255) < 0) {
    perror("listen");
    close(sd);
    exit(EXIT_FAILURE);
    }

    for (int k = 0; k < 3; k++) {
    pid = fork();
    if (pid < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
    }
    if (pid > 0) // Parent
    continue;
    // Child.
    pid = getpid();
    for (;;) {
    memset(&client, 0, sizeof client);
    clientlen = sizeof client;
    nsd = accept(sd, (struct sockaddr *)&client, &clientlen);
    if (nsd < 0) {
    perror("accept");
    close(sd);
    exit(EXIT_FAILURE);
    }
    printf("pid %d accepted a connection\n", pid);
    close(nsd);
    }
    }
    close(sd);
    for (int k = 0; k < 3; k++)
    wait(NULL);

    return EXIT_SUCCESS;
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Mark Berryman on Mon Oct 7 13:49:23 2024
    On 10/7/2024 12:47 PM, Mark Berryman wrote:
    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does.  It listens for a connection, then
    creates a process to handle it.  See the description of TCPIP$C_AUXS in
    the TCPIP Services programming documentation.

    SYS$COMMON:[SYSHLP.EXAMPLES.TCPIP]TCPIP$TCP_SERVER_SOCK_AUXS.C has:

    /*
    * create socket
    */

    if ( (sockfd = socket(TCPIP$C_AUXS, SOCK_STREAM, 0)) < 0 )
    {
    perror( "Failed to create socket" );
    exit( EXIT_FAILURE );
    }

    but the equivalent SYS$COMMON:[SYSHLP.EXAMPLES.TCPIP]TCPIP$TCP_SERVER_QIO_AUXS.C
    gives some hints about what it is doing:

    struct sockchar conn_sockchar; /* connect socket char buffer */
    ...
    $DESCRIPTOR( inet_device, /* string descriptor with logical */
    "SYS$NET:" ); /* name of internet pseudodevice */
    ...
    /*
    * init connection socket characteristics buffer
    */

    conn_sockchar.prot = TCPIP$C_TCP;
    conn_sockchar.type = TCPIP$C_STREAM;
    conn_sockchar.af = TCPIP$C_AUXS;
    ...
    /*
    * assign device socket
    */

    status = sys$assign( &inet_device, /* device name */
    &conn_channel, /* i/o channel */
    0, /* access mode */
    0 /* not used */
    );

    if ( !(status & STS$M_SUCCESS) )
    {
    printf( "Failed to assign i/o channel to TCPIP device\n" );
    exit( status );
    }
    ...
    /*
    * create connection socket
    */

    status = sys$qiow( EFN$C_ENF, /* event flag
    */
    conn_channel, /* i/o channel
    */
    IO$_SETMODE, /* i/o function code
    */
    &iosb, /* i/o status block
    */
    0, /* ast service routine
    */
    0, /* ast parameter
    */
    &conn_sockchar, /* p1 - socket char buffer
    */
    0, /* p2
    */
    0, /* p3
    */
    0, /* p4
    */
    0, /* p5
    */
    0 /* p6
    */
    );

    if ( status & STS$M_SUCCESS )
    status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
    {
    printf( "Failed to create socket\n" );
    exit( status );
    }

    But it is not clear (at least not to me) whether:
    - the original TCP/IP device was made shareable and SYS$NET just points
    to it
    or:
    - the original TCP/IP device is connected to a new pseudodevice that
    SYS$NET points to

    The first seems by far the simplest, but the comment indicate
    the second.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Daniel@21:1/5 to Mark Berryman on Tue Oct 8 05:35:49 2024
    On 8/10/2024 03:17, Mark Berryman wrote:
    On 10/6/24 9:12 AM, Michael S wrote:
    8< snip 8<
    As a lurker, I am waiting for the expert answer with interest.


    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does.  It listens for a connection, then
    creates a process to handle it.  See the description of TCPIP$C_AUXS in
    the TCPIP Services programming documentation.
    8< snip 8<

    The auxiliary is something special. Passing socket devices between
    processes requires SHARE privilege.

    X86VMS$ type bg_example.c /*****************************************************************************/ /*

    Quick and dirty demonstrator of passing BSD socket using BG device name
    to another process and using that to QIO and write(). IPC is simple
    system(). Cobbled together from various project fragments.

    $ cc bg_example
    $ link bg_example
    $ mcr []bg_example

    $ telnet loalhost 8765

    accept()
    chan: 304
    BgDevice: |BG12433:|
    sys$setprv() %X00000001
    sys$assign() %X00000001
    sys$qiow() 14 %X00000001 %X00000001
    write() 14 %X00000001
    dcl: |mcr dka100:[kits]bg_example.exe;14 BG12433:| %X00000001
    accept()

    Comment out the initial $setprv(PRV$M_SHARE) and the channel is not
    allocated.

    accept()
    chan: 304
    BgDevice: |BG12677:|
    write() -1 %X0000013C
    dcl: |mcr dka100:[kits]bg_example.exe;17 BG12677:| %X00000001
    accept()

    */ /*****************************************************************************/

    #include <ctype.h>
    #include <descrip.h>
    #include <stdarg.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <time.h>
    #include <types.h>
    #include <unixlib.h>
    #include <unistd.h>

    #include <dvidef.h>
    #include <efndef.h>
    #include <iodef.h>
    #include <lnmdef.h>
    #include <prvdef.h>
    #include <ssdef.h>
    #include <starlet.h>

    #include <sys/socket.h>
    #include <resolv.h>
    #include <netdb.h>

    typedef struct iosb_t
    {
    ushort iosb$w_status;
    ushort iosb$w_bcnt;
    ulong iosb$l_reserved;
    }
    iosb;

    static ulong ShareMask [2] = { PRV$M_SHARE, 0 };

    static int EfnWait = EFN$C_ENF;

    int ListenBegin ();
    int OpenBG (char*);
    char* GetBgDevice (ushort);

    /*****************************************************************************/ /*
    */

    int main (int argc, char *argv[])

    {
    if (argc > 1)
    OpenBG (argv[1]);
    else
    ListenBegin (argv[0]);
    }

    /*****************************************************************************/ /*
    Set up a socket listening to port 8765.
    */

    int ListenBegin (char *argv0)

    {
    static int one = 1;

    int csock, lsock, status;
    uint clen;
    ushort chan;
    struct sockaddr_in caddr;
    struct sockaddr_in laddr;
    char *cptr;
    char dcl [256];

    /*********/
    /* begin */
    /*********/

    memset (&laddr, 0, sizeof(laddr));
    laddr.sin_family = AF_INET;
    laddr.sin_addr.s_addr = INADDR_ANY;

    laddr.sin_port = htons(8765);

    if ((lsock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
    return (vaxc$errno);

    if (setsockopt (lsock, SOL_SOCKET, SO_REUSEADDR,
    &one, sizeof(one)) < 0)
    {
    close (lsock);
    return (vaxc$errno);
    }

    if (bind (lsock, (struct sockaddr*)&laddr, sizeof(laddr)) < 0)
    {
    close (lsock);
    return (vaxc$errno);
    }

    if (listen (lsock, 5) < 0)
    {
    close (lsock);
    return (vaxc$errno);
    }

    for (;;)
    {
    clen = sizeof(caddr);

    printf ("accept()\n");
    csock = accept (lsock, (struct sockaddr*)&caddr, &clen);
    if (csock < 0)
    {
    status = vaxc$errno;
    if (status == SS$_CANCEL || SS$_IVCHAN) break;
    continue;
    }

    chan = decc$get_sdc (csock);
    printf ("chan: %d\n", chan);
    if (!chan) return (vaxc$errno);

    cptr = GetBgDevice (chan);
    printf ("BgDevice: |%s|\n", cptr);

    sprintf (dcl, "mcr %s %s", argv0, cptr);
    status = system (dcl);
    printf ("dcl: |%s| %%X%08.08X\n", dcl, status);
    if (!(status & 1)) break;

    close (csock);
    }

    close (lsock);
    return (status);
    }

    /*****************************************************************************/ /*
    Open shared the supplied BG device name.
    */

    int OpenBG (char *BgDevName)

    {
    int count, csock, status;
    ushort chan;
    iosb IOsb;
    $DESCRIPTOR (BgDevNameDsc, BgDevName);

    BgDevNameDsc.dsc$w_length = strlen(BgDevName);

    status = sys$setprv (1, &ShareMask, 0, 0);
    printf ("sys$setprv() %%X%08.08X\n", status);

    if (status & 1)
    {
    BgDevNameDsc.dsc$w_length = strlen(BgDevName);
    status = sys$assign (&BgDevNameDsc, &chan, 0, 0);
    printf ("sys$assign() %%X%08.08X\n", status);
    }

    if (status & 1)
    {
    status = sys$qiow (EfnWait, chan, IO$_WRITEVBLK, &IOsb, 0, 0,
    "\r\nabcdefghij\r\n", 14, 0, 0, 0, 0);
    printf ("sys$qiow() %d %%X%08.08X %%X%08.08X\n",
    IOsb.iosb$w_bcnt, status, IOsb.iosb$w_status);
    if (status & 1)
    status = IOsb.iosb$w_status;
    }

    csock = decc$socket_fd (chan);
    if (csock == -1) status = vaxc$errno;
    if (csock > 0)
    {
    count = write (csock, "\r\nklmnopqrst\r\n", 14);
    if (count != 14) status = vaxc$errno;
    printf ("write() %d %%X%08.08X\n", count, status);
    }

    sys$setprv (0, &ShareMask, 0, 0);

    sys$dassgn (chan);

    return (status);
    }

    /*****************************************************************************/ /*
    Just get the "BGnnn:" device name associated with the channel.
    */

    char* GetBgDevice (ushort Channel)

    {
    static char DevName [65];
    static ushort slen;
    struct ItemList3Struct
    {
    ushort buf_len;
    ushort item;
    void *buf_addr;
    void *ret_len;
    } DevNamItemList [] =
    {
    { sizeof(DevName)-1, DVI$_DEVNAM, DevName, &slen },
    { 0, 0, 0, 0 }
    };

    int status;
    iosb IOsb;

    /*********/
    /* begin */
    /*********/

    if (!Channel)
    {
    memset (DevName, 0, sizeof(DevName));
    return (DevName);
    }

    status = sys$getdviw (EfnWait, Channel, 0, &DevNamItemList,
    &IOsb, 0, 0, 0);
    if (status & 1) status = IOsb.iosb$w_status;
    if (status & 1)
    DevName[slen] = '\0';
    else
    sprintf (DevName, "%%X%08.08X", status);

    if (DevName[0] == '_') return (DevName+1);
    return (DevName);
    }

    /*****************************************************************************/


    --
    Anyone, who using social-media, forms an opinion regarding anything
    other than the relative cuteness of this or that puppy-dog, needs
    seriously to examine their critical thinking.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Oct 7 19:41:49 2024
    In article <ve16v4$1mvdn$1@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 12:47 PM, Mark Berryman wrote:
    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does.  It listens for a connection, then
    creates a process to handle it.  See the description of TCPIP$C_AUXS in
    the TCPIP Services programming documentation.

    SYS$COMMON:[SYSHLP.EXAMPLES.TCPIP]TCPIP$TCP_SERVER_SOCK_AUXS.C has:

    /*
    * create socket
    */

    if ( (sockfd = socket(TCPIP$C_AUXS, SOCK_STREAM, 0)) < 0 )
    {
    perror( "Failed to create socket" );
    exit( EXIT_FAILURE );
    }

    but the equivalent >SYS$COMMON:[SYSHLP.EXAMPLES.TCPIP]TCPIP$TCP_SERVER_QIO_AUXS.C
    gives some hints about what it is doing:

    struct sockchar conn_sockchar; /* connect socket char buffer */
    ...
    $DESCRIPTOR( inet_device, /* string descriptor with logical */
    "SYS$NET:" ); /* name of internet pseudodevice */
    ...
    /*
    * init connection socket characteristics buffer
    */

    conn_sockchar.prot = TCPIP$C_TCP;
    conn_sockchar.type = TCPIP$C_STREAM;
    conn_sockchar.af = TCPIP$C_AUXS;
    ...
    /*
    * assign device socket
    */

    status = sys$assign( &inet_device, /* device name */
    &conn_channel, /* i/o channel */
    0, /* access mode */
    0 /* not used */
    );

    if ( !(status & STS$M_SUCCESS) )
    {
    printf( "Failed to assign i/o channel to TCPIP device\n" );
    exit( status );
    }
    ...
    /*
    * create connection socket
    */

    status = sys$qiow( EFN$C_ENF, /* event flag
    */
    conn_channel, /* i/o channel
    */
    IO$_SETMODE, /* i/o function code
    */
    &iosb, /* i/o status block
    */
    0, /* ast service routine
    */
    0, /* ast parameter
    */
    &conn_sockchar, /* p1 - socket char buffer
    */
    0, /* p2
    */
    0, /* p3
    */
    0, /* p4
    */
    0, /* p5
    */
    0 /* p6
    */
    );

    if ( status & STS$M_SUCCESS )
    status = iosb.status;

    if ( !(status & STS$M_SUCCESS) )
    {
    printf( "Failed to create socket\n" );
    exit( status );
    }

    But it is not clear (at least not to me) whether:
    - the original TCP/IP device was made shareable and SYS$NET just points
    to it
    or:
    - the original TCP/IP device is connected to a new pseudodevice that
    SYS$NET points to

    The first seems by far the simplest, but the comment indicate
    the second.

    It is almost certainly the second.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Mon Oct 7 16:07:25 2024
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    // Demonstration of a listener process that accepts
    // incoming TCP connections and passes them to a
    // worker process over Unix domain sockets.
    //
    // Dan Cross <cross@gajendra.net>

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/uio.h>
    #include <netinet/in.h>

    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <string.h>

    // Sends a file descripter, `fd`, over a Unix domain socket `sd`
    // via the 4.4BSD access rights passing mechanism.
    //
    // Returns 1 on success, -1 on failure.
    int
    sendfd(int sd, int fd)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    // Construct the control message header. Note this is
    // malloc'ed to ensure proper alignment.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;
    memset(ptr, 0, len);
    ptr->cmsg_len = len;
    ptr->cmsg_level = SOL_SOCKET;
    ptr->cmsg_type = SCM_RIGHTS;
    memcpy(CMSG_DATA(ptr), &fd, sizeof(int));

    // We send a single byte of dummy data in case the
    // implementation does not pass control data with an
    // otherwise empty data transfer.
    dummy = 0;
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Construct the message header. Points to the dummy
    // data and the control message header.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = (caddr_t)ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    // Loop in case there's no room in the kernel buffer
    // to send. Cf.Stevens et al.
    do {
    ret = sendmsg(sd, &mh, 0);
    } while (ret == 0);
    free(ptr);

    return ret;
    }

    // Receives a file descriptor over the Unix domain socket `sd`
    // and store it into `*fdp` on success.
    //
    // Returns 1 on success, 0 on EOF, -1 on error.
    int
    recvfd(int sd, int *fdp)
    {
    struct msghdr mh;
    struct iovec iv;
    struct cmsghdr *ptr;
    size_t len;
    int ret;
    char dummy;

    if (fdp == NULL)
    return -1;

    // Allocate space for the control message.
    len = CMSG_SPACE(sizeof(int));
    ptr = malloc(len);
    if (ptr == NULL)
    return -1;

    // Fill in an iovec to receive one byte of dummy data.
    // Required on some systems that do not pass control
    // messages on empty data transfers.
    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    // Fill in the msghdr structure. `recvmsg(2)` will
    // update it.
    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_control = ptr;
    mh.msg_controllen = len;
    mh.msg_flags = 0;

    ret = recvmsg(sd, &mh, 0);
    if (ret <= 0) {
    free(ptr);
    return ret;
    }
    if (mh.msg_flags != 0) {
    free(ptr);
    return -1;
    }
    memcpy(fdp, CMSG_DATA(ptr), sizeof(int));
    free(ptr);

    return 1;
    }

    void
    dispatcher(int sdworker, int port)
    {
    int sd, nsd;
    struct sockaddr_in sa;
    struct sockaddr_in client;
    socklen_t clientlen;

    sd = socket(AF_INET, SOCK_STREAM, 0);
    if (sd < 0) {
    perror("socket");
    close(sdworker);
    exit(EXIT_FAILURE);
    }
    memset(&sa, 0, sizeof sa);
    sa.sin_family = AF_INET;
    sa.sin_port = htons((unsigned short)port);
    sa.sin_addr.s_addr = htonl(INADDR_ANY);
    if (bind(sd, (struct sockaddr *)&sa, sizeof sa) < 0) {
    perror("bind");
    close(sdworker);
    close(sd);
    exit(EXIT_FAILURE);
    }
    if (listen(sd, 255) < 0) {
    perror("listen");
    close(sdworker);
    close(sd);
    exit(EXIT_FAILURE);
    }

    memset(&client, 0, sizeof client);
    clientlen = sizeof client;
    while ((nsd = accept(sd, (struct sockaddr *)&client, &clientlen)) >= 0) {
    if (sendfd(sdworker, nsd) < 0) {
    perror("sendfd");
    close(sdworker);
    close(nsd);
    close(sd);
    exit(EXIT_FAILURE);
    }
    close(nsd);
    }
    }

    static void
    echo(int sd)
    {
    char *p;
    char buf[1024];
    ssize_t nb, wb;

    for (;;) {
    nb = read(sd, buf, sizeof buf);
    if (nb < 0)
    perror("read");
    if (nb <= 0)
    return;
    p = buf;
    while (nb > 0) {
    wb = write(sd, p, nb);
    if (wb < 0)
    perror("write");
    if (wb <= 0)
    return;
    nb -= wb;
    p += wb;
    }
    }
    }

    void
    worker(int sddispatcher)
    {
    int sd;

    while (recvfd(sddispatcher, &sd) > 0) {
    echo(sd);
    close(sd);
    }
    }

    int
    main(void)
    {
    int sds[2];
    pid_t pid;

    if (socketpair(AF_UNIX, SOCK_STREAM, 0, sds) > 0) {
    perror("socketpair");
    exit(EXIT_FAILURE);
    }

    for (int k = 0; k < 3; k++) {
    pid = fork();
    if (pid < 0) {
    perror("fork");
    exit(EXIT_FAILURE);
    }
    if (pid == 0) { // Child
    close(sds[0]);
    worker(sds[1]);
    exit(EXIT_SUCCESS);
    }
    }
    close(sds[1]);
    dispatcher(sds[0], 8200);

    return EXIT_SUCCESS;
    }

    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1

    mh.msg_control = (caddr_t)ptr;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_control" is not a member of "mh".
    at line number 56 in file DKA0:[arne]zz.c;1

    mh.msg_controllen = len;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_controllen" is not a member of
    "mh".
    at line number 57 in file DKA0:[arne]zz.c;1

    mh.msg_flags = 0;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
    at line number 58 in file DKA0:[arne]zz.c;1

    mh.msg_control = ptr;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_control" is not a member of "mh".
    at line number 100 in file DKA0:[arne]zz.c;1

    mh.msg_controllen = len;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_controllen" is not a member of
    "mh".
    at line number 101 in file DKA0:[arne]zz.c;1

    mh.msg_flags = 0;
    ...^
    %CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
    at line number 102 in file DKA0:[arne]zz.c;1

    if (mh.msg_flags != 0) {
    .......^
    %CC-E-NEEDMEMBER, In this statement, "msg_flags" is not a member of "mh".
    at line number 108 in file DKA0:[arne]zz.c;1

    pid = fork();
    ............^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "fork" is
    implicitly declared as a function.
    at line number 201 in file DKA0:[arne]zz.c;1

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Dan Cross on Mon Oct 7 16:26:34 2024
    On 10/7/2024 4:17 PM, Dan Cross wrote:
    In article <ve1f1t$1mvdn$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is
    implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1
    [snip]

    Why would you try to build that under VMS? It obviously would
    not build or work there.

    The question whether a socket descriptor could be transferred
    between processes on VMS similar to on *nix was raised.

    And it was noted that VMS had Unix socket support

    But compiling shows that some of the structs are missing
    relevant fields.

    So conclusion must be that VMS can't do that.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Oct 7 20:38:47 2024
    In article <670443fb$0$705$14726298@news.sunsite.dk>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 4:17 PM, Dan Cross wrote:
    In article <ve1f1t$1mvdn$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is
    implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1
    [snip]

    Why would you try to build that under VMS? It obviously would
    not build or work there.

    The question whether a socket descriptor could be transferred
    between processes on VMS similar to on *nix was raised.

    And it was noted that VMS had Unix socket support

    But compiling shows that some of the structs are missing
    relevant fields.

    So conclusion must be that VMS can't do that.

    You should be more explicit when writing. Quoting the entire
    program and then spewing compiler error messages into the group
    isn't very polite, and is utterly ambiguous as to what you might
    mean. Basic netiquette would suggest you should at least
    attempt to explain yourself, and trim your reply accordingly.

    Moreover, your message ignored context. Looking back, one can
    see that Dave Froble asked (in <vdvoeq$1jerg$1@dont-email.me>):
    |Well, some of the issue is in the text of the question. What does one mean be |"pass socket"?

    The program I posted was in response to that. Quoting from the
    part of the message that you cut out:

    |Perhaps an example will be illuminating. See the program at the
    |bottom of this post; it is self-contained and, I claim, fairly
    |representative of the technique. I wrote and tested it on
    |OpenBSD 7.5, on a RISC-V devbox.

    In other words, the example program was meant to answer the
    question, "what does one mean by 'pass socket'?", as asked by
    Dave.

    It is clear (enough) that VMS does not support the mechanism for
    passing open IO descriptors between process that Unix does. But
    that does not mean that VMS does not support a similar way to do
    more or less the same thing; if folks understand what one means
    when discussing "socket passing" or "file descriptor passing" or
    whatever from the Unix side, then it makes it easier to look for
    the corresponding mechanism on the VMS side (if such exists).

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to arne@vajhoej.dk on Mon Oct 7 20:17:11 2024
    In article <ve1f1t$1mvdn$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is >implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1
    [snip]

    Why would you try to build that under VMS? It obviously would
    not build or work there.

    Did you read the message the program was attached to?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Berryman@21:1/5 to Mark Daniel on Tue Oct 8 09:43:11 2024
    On 10/7/24 1:05 PM, Mark Daniel wrote:
    On 8/10/2024 03:17, Mark Berryman wrote:
    On 10/6/24 9:12 AM, Michael S wrote:
    8< snip 8<
    As a lurker, I am waiting for the expert answer with interest.


    It is most definitely possible as that is precisely what the auxiliary
    server in TCPIP Services does.  It listens for a connection, then
    creates a process to handle it.  See the description of TCPIP$C_AUXS
    in the TCPIP Services programming documentation.
    8< snip 8<

    The auxiliary is something special.  Passing socket devices between processes requires SHARE privilege.

    [ program example deleted ]

    This is one way to do it since the SHARE privilege will allow you to
    open a device that is already open by another process. However, since I
    can find no evidence that processes started by the auxiliary server
    require the SHARE privilege, that would indicate to me that the server
    uses a different method.

    Mark Berryman

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Daniel@21:1/5 to Mark Berryman on Wed Oct 9 03:52:26 2024
    On 9/10/2024 02:13, Mark Berryman wrote:
    On 10/7/24 1:05 PM, Mark Daniel wrote:
    On 8/10/2024 03:17, Mark Berryman wrote:
    On 10/6/24 9:12 AM, Michael S wrote:
    8< snip 8<
    As a lurker, I am waiting for the expert answer with interest.


    It is most definitely possible as that is precisely what the
    auxiliary server in TCPIP Services does.  It listens for a
    connection, then creates a process to handle it.  See the description
    of TCPIP$C_AUXS in the TCPIP Services programming documentation.
    8< snip 8<

    The auxiliary is something special.  Passing socket devices between
    processes requires SHARE privilege.

    [ program example deleted ]

    This is one way to do it since the SHARE privilege will allow you to
    open a device that is already open by another process.  However, since I
    can find no evidence that processes started by the auxiliary server
    require the SHARE privilege, that would indicate to me that the server
    uses a different method.

    Absolutely they do not but with these

    ACNT ALLSPOOL ALTPRI AUDIT BUGCHK BYPASS
    CMEXEC CMKRNL DIAGNOSE DOWNGRADE EXQUOTA GROUP
    GRPNAM GRPPRV IMPERSONATE IMPORT LOG_IO MOUNT
    NETMBX OPER PFNMAP PHY_IO PRMCEB PRMGBL
    PRMMBX PSWAPM READALL SECURITY SETPRV SHARE
    SHMEM SYSGBL SYSLCK SYSNAM SYSPRV TMPMBX
    UPGRADE VOLPRO WORLD

    plus all the facility available to TCPIP$BGDRIVER.EXE why would they?

    The example showed a mechanism available to pass established sockets
    between unrelated processes provided IPC is available; can be simple as
    logical name+value, or doorbell lock name+value, etc.

    Mark Berryman

    --
    Anyone, who using social-media, forms an opinion regarding anything
    other than the relative cuteness of this or that puppy-dog, needs
    seriously to examine their critical thinking.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Mark Daniel on Tue Oct 8 15:31:15 2024
    On 10/8/2024 1:22 PM, Mark Daniel wrote:
    On 9/10/2024 02:13, Mark Berryman wrote:
    On 10/7/24 1:05 PM, Mark Daniel wrote:
    On 8/10/2024 03:17, Mark Berryman wrote:
    It is most definitely possible as that is precisely what the
    auxiliary server in TCPIP Services does.  It listens for a
    connection, then creates a process to handle it.  See the
    description of TCPIP$C_AUXS in the TCPIP Services programming
    documentation.
    8< snip 8<

    The auxiliary is something special.  Passing socket devices between
    processes requires SHARE privilege.

    [ program example deleted ]

    This is one way to do it since the SHARE privilege will allow you to
    open a device that is already open by another process.  However, since
    I can find no evidence that processes started by the auxiliary server
    require the SHARE privilege, that would indicate to me that the server
    uses a different method.

    Absolutely they do not but with these

     ACNT         ALLSPOOL     ALTPRI       AUDIT        BUGCHK       BYPASS
     CMEXEC       CMKRNL       DIAGNOSE     DOWNGRADE    EXQUOTA      GROUP
     GRPNAM       GRPPRV       IMPERSONATE  IMPORT       LOG_IO       MOUNT
     NETMBX       OPER         PFNMAP       PHY_IO       PRMCEB       PRMGBL
     PRMMBX       PSWAPM       READALL      SECURITY     SETPRV       SHARE
     SHMEM        SYSGBL       SYSLCK       SYSNAM       SYSPRV       TMPMBX
     UPGRADE      VOLPRO       WORLD

    plus all the facility available to TCPIP$BGDRIVER.EXE why would they?

    You think the auxiliary server set a few fields (like UIC and PID) for
    the BG device?

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Daniel@21:1/5 to All on Wed Oct 9 07:54:41 2024
    On 9/10/2024 06:01, Arne Vajhøj wrote:
    On 10/8/2024 1:22 PM, Mark Daniel wrote:
    On 9/10/2024 02:13, Mark Berryman wrote:
    On 10/7/24 1:05 PM, Mark Daniel wrote:
    On 8/10/2024 03:17, Mark Berryman wrote:
    It is most definitely possible as that is precisely what the
    auxiliary server in TCPIP Services does.  It listens for a
    connection, then creates a process to handle it.  See the
    description of TCPIP$C_AUXS in the TCPIP Services programming
    documentation.
    8< snip 8<

    The auxiliary is something special.  Passing socket devices between
    processes requires SHARE privilege.

    [ program example deleted ]

    This is one way to do it since the SHARE privilege will allow you to
    open a device that is already open by another process.  However,
    since I can find no evidence that processes started by the auxiliary
    server require the SHARE privilege, that would indicate to me that
    the server uses a different method.

    Absolutely they do not but with these

      ACNT         ALLSPOOL     ALTPRI       AUDIT        BUGCHK       BYPASS
      CMEXEC       CMKRNL       DIAGNOSE     DOWNGRADE    EXQUOTA      GROUP
      GRPNAM       GRPPRV       IMPERSONATE  IMPORT       LOG_IO       MOUNT
      NETMBX       OPER         PFNMAP       PHY_IO       PRMCEB       PRMGBL
      PRMMBX       PSWAPM       READALL      SECURITY     SETPRV       SHARE
      SHMEM        SYSGBL       SYSLCK       SYSNAM       SYSPRV       TMPMBX
      UPGRADE      VOLPRO       WORLD

    plus all the facility available to TCPIP$BGDRIVER.EXE why would they?

    You think the auxiliary server set a few fields (like UIC and PID) for
    the BG device?

    More likely the driver itself but with an integrated suite of
    functionality the distinction is somewhat moot.

    Arne

    --
    Anyone, who using social-media, forms an opinion regarding anything
    other than the relative cuteness of this or that puppy-dog, needs
    seriously to examine their critical thinking.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Michael S on Thu Oct 10 23:01:13 2024
    On 10/7/2024 4:07 AM, Michael S wrote:
    On Mon, 7 Oct 2024 00:35:36 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave! ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP
    socket to child process (or, may be, to unrelated process) under
    VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Well, some of the issue is in the text of the question. What does
    one mean be "pass socket"?

    When creating a socket, one can specify it to be shared. What I was
    doing was passing the information to a worker process, then letting
    the worker process open the existing socket.

    So, would that be considered "passing an open socket"?


    Yes, it would be.

    On Windows one has to go through similar 3-stage procedure:
    - [in parent process] acquire magic record from the open socket by
    means of WSADuplicateSocket()
    - pass the record to child by any of available IPC mechanisms
    - [in child process] use magic record to re-open socket with
    WSASocket()

    I never had a need of for it in practice. Looking at docs it seems
    that the procedure above has at least one inconvenient aspect - the
    target process has to exist at the moment of WSADuplicateSocket() call. Still, I suppose that it's better than nothing.

    I can post some of the development code is anyone is interested. I
    was working on the inter-process communications when I dropped the
    project. I believe I did open the shared socket in the worker
    process.


    May be, others are interested in the code.
    For me, I'd rather read textual description of the procedure and war
    story of making it work.


    Actually, simple.

    1) Create the socket in listener process
    2) Pass device name to worker process
    3) Assign a channel to the device in worker process
    4) deassign the channel in listener process (if desired)

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Thu Oct 10 23:33:34 2024
    On 10/7/2024 4:17 PM, Dan Cross wrote:
    In article <ve1f1t$1mvdn$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is
    implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1
    [snip]

    Why would you try to build that under VMS? It obviously would
    not build or work there.

    Yeah, also wondered ...

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Thu Oct 10 23:46:54 2024
    On 10/7/2024 2:01 PM, Dan Cross wrote:
    As Dave has mentioned, setting SO_SHARE on a socket would be another way
    to accomplish this.

    Neither of these sounds the same as descriptor passing over Unix
    domain sockets on Unix/Linux; the auxiliary server sounds more
    like `inetd`, in that there's some service that's listening and
    accepting connections on some TCP/IP port, and then creating a
    server to handle each incoming connection.

    I would claim that what I did is NOT passing a descriptor, or whatever, to another process. Not really sure what that means. All I passed was the device name, and let the second process assign a channel to the "existing" device (socket).

    SO_SHARE is different again; it appears that the shared socket
    must be created before the subprocesses that use it are created.

    I don't know why you would say that. A process must exist before it can do anything, but, a socket can exist in a process, and then connected to in another
    process, regardless of when the second process is created. For example, if a bank of worker processes exist, and a task comes in, the connection socket could
    be opened by the existing selected worker process.


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to Dave Froble on Fri Oct 11 13:11:51 2024
    On Thu, 10 Oct 2024 23:01:13 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/7/2024 4:07 AM, Michael S wrote:
    On Mon, 7 Oct 2024 00:35:36 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave!
    ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP
    socket to child process (or, may be, to unrelated process) under
    VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Well, some of the issue is in the text of the question. What does
    one mean be "pass socket"?

    When creating a socket, one can specify it to be shared. What I
    was doing was passing the information to a worker process, then
    letting the worker process open the existing socket.

    So, would that be considered "passing an open socket"?


    Yes, it would be.

    On Windows one has to go through similar 3-stage procedure:
    - [in parent process] acquire magic record from the open socket by
    means of WSADuplicateSocket()
    - pass the record to child by any of available IPC mechanisms
    - [in child process] use magic record to re-open socket with
    WSASocket()

    I never had a need of for it in practice. Looking at docs it seems
    that the procedure above has at least one inconvenient aspect - the
    target process has to exist at the moment of WSADuplicateSocket()
    call. Still, I suppose that it's better than nothing.

    I can post some of the development code is anyone is interested. I
    was working on the inter-process communications when I dropped the
    project. I believe I did open the shared socket in the worker
    process.


    May be, others are interested in the code.
    For me, I'd rather read textual description of the procedure and war
    story of making it work.


    Actually, simple.

    1) Create the socket in listener process
    2) Pass device name to worker process
    3) Assign a channel to the device in worker process
    4) deassign the channel in listener process (if desired)


    There are few pieces in your simple explanation that I don't understand:
    - How does listener get a device name?
    - What is "channel"? Is it the same as 'socket'?
    - How one "assigns" channel to device? I would guess that device has to
    be open before that?
    - Is device name of the socket system-global?
    If yes, does it mean that any process in the system that happens to
    know a name can open a device and assign it to channel?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Michael S on Fri Oct 11 08:00:42 2024
    On 10/11/2024 6:11 AM, Michael S wrote:
    On Thu, 10 Oct 2024 23:01:13 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:
    Actually, simple.

    1) Create the socket in listener process
    2) Pass device name to worker process
    3) Assign a channel to the device in worker process
    4) deassign the channel in listener process (if desired)


    There are few pieces in your simple explanation that I don't understand:
    - How does listener get a device name?

    There may be multiple ways, but if using the SYS$QIO(W)
    interface then the code has a channel and SYS$GETDVI(W)
    can get the device name from that.

    - What is "channel"? Is it the same as 'socket'?

    I assume a VMS channel as one get from SYS$ASSIGN.

    - How one "assigns" channel to device? I would guess that device has to
    be open before that?

    Call SYS$ASSIGN.

    - Is device name of the socket system-global?
    If yes, does it mean that any process in the system that happens to
    know a name can open a device and assign it to channel?

    Device names are system wide.

    But there are access controls in place.

    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to already5chosen@yahoo.com on Fri Oct 11 12:35:48 2024
    In article <20241011131151.00003a02@yahoo.com>,
    Michael S <already5chosen@yahoo.com> wrote:
    On Thu, 10 Oct 2024 23:01:13 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:
    [snip]
    Actually, simple.

    1) Create the socket in listener process
    2) Pass device name to worker process
    3) Assign a channel to the device in worker process
    4) deassign the channel in listener process (if desired)


    There are few pieces in your simple explanation that I don't understand:
    - How does listener get a device name?

    There's a system service (system call) that let's you do that;
    it is called `$GETDVI` ("GET Device/Volume Information"). There
    is a wrapper in the standard library that makes it a little
    easier to work with, `LIB$GETDVI`.

    - What is "channel"? Is it the same as 'socket'?

    A channel is a process-unique identifier for some resource you
    want to interact with, such as a device or mailbox. A rough
    analogue from the Unix/Linux world is a file descriptor. On VMS
    a socket is a "device", so to interact with it, you must
    associate a channel with it.

    - How one "assigns" channel to device? I would guess that device has to
    be open before that?

    There's a system service for that. Section 7.5 of the "VMS
    Programming Concepts (volume 2)" manual on the VSI web site goes
    into detail about exactly how to do it, but `$ASSIGN` takes a
    devine name and allocates and assigns a channel to it.

    - Is device name of the socket system-global?

    Yes.

    If yes, does it mean that any process in the system that happens to
    know a name can open a device and assign it to channel?

    No, there are authorization checks and so forth that the system
    makes before assignment completes successfully; there's also the
    matter that, if a device is already assigned exclusively, by
    default it can't be assigned to another process at the same
    time. That's what all of this business about the SHARE
    privilege is about; section 7.2.8 of the programming concepts
    manual talks about this, but basically, if a process has the
    `SHARE` privilege, it can `$ASSIGN` another device accessed
    "exclusively" by another process's device. A subprocess of a
    process can also assign a channel to a device that's assigned
    to the parent (I dunno if that last bit is always true; it was
    in section 18.3 of the "VAX/VMS Internals and Data Structures"
    book for VMS 4.4, which is pretty old).

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Michael S@21:1/5 to All on Fri Oct 11 16:11:05 2024
    On Fri, 11 Oct 2024 12:35:48 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    Thank you.
    I am more that a little out of my VMS knowledge depth, but after your explanations I certainly understand more.

    Thank you to Arne too.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Fri Oct 11 14:14:53 2024
    In article <vea6ak$3h25s$2@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/7/2024 4:17 PM, Dan Cross wrote:
    In article <ve1f1t$1mvdn$2@dont-email.me>,
    Arne Vajhøj <arne@vajhoej.dk> wrote:
    On 10/7/2024 11:52 AM, Dan Cross wrote:
    $ cc zz

    len = CMSG_SPACE(sizeof(int));
    .........^
    %CC-I-IMPLICITFUNC, In this statement, the identifier "CMSG_SPACE" is
    implicitly declared as a function.
    at line number 33 in file DKA0:[arne]zz.c;1
    [snip]

    Why would you try to build that under VMS? It obviously would
    not build or work there.

    Yeah, also wondered ...

    I think he was confused. His justification that VMS must not
    support descriptor passing because of the errors he saw, and he
    was just saying that, doesn't hold much water, either.

    As I mentioned back in <vdk7fi$jdm$1@reader1.panix.com>, the
    descriptor passing mechanism was added in 4.2BSD, back in 1983,
    but it was _updated_ in 4.4BSD, in 1994. The code I posted
    used the 4.4BSD mechansim. Clearly, that isn't supported on VMS
    as he showed, but that's not the only way to do it.

    In particular, the 4.3BSD mechanism uses different fields in the
    `struct msghdr` to move descriptors around, and those are at
    least in the struct definitions on VMS. Do they do anything? I
    kind of tend to doubt it, but for example the code below does
    compile on Eisner, though I haven't written a driver to see if
    it actually _works_.

    - Dan C.

    /*
    * Example code to demonstrate file descriptor passing
    * over Berkeley sockets.
    *
    * Dan Cross <cross@gajendra.net>
    */
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <sys/uio.h>
    #include <sys/un.h>
    #include <sys/wait.h>

    #include <fcntl.h>
    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>

    int
    unix_server(char *path)
    {
    int nsd, sd;
    socklen_t clen;
    struct sockaddr_un sock;

    sd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sd < 0) {
    perror("socket");
    exit(EXIT_FAILURE);
    }
    memset(&sock, 0, sizeof(sock));
    sock.sun_family = AF_UNIX;
    strncpy(sock.sun_path, path, sizeof(sock.sun_path));
    if (bind(sd, (struct sockaddr *)&sock, sizeof(sock)) < 0) {
    perror("bind");
    exit(EXIT_FAILURE);
    }
    if (listen(sd, 5) < 0) {
    perror("listen");
    exit(EXIT_FAILURE);
    }
    clen = sizeof(sock);
    nsd = accept(sd, (struct sockaddr *)&sock, &clen);
    if (nsd < 0) {
    perror("accept");
    exit(EXIT_FAILURE);
    }
    close(sd);

    return(nsd);
    }

    int
    unix_client(char *path)
    {
    int sd;
    struct sockaddr_un sock;

    sd = socket(AF_UNIX, SOCK_STREAM, 0);
    if (sd < 0) {
    perror("socket");
    exit(EXIT_FAILURE);
    }
    memset(&sock, 0, sizeof(sock));
    sock.sun_family = AF_UNIX;
    strncpy(sock.sun_path, path, sizeof(sock.sun_path));
    if (connect(sd, (struct sockaddr *)&sock, sizeof(sock)) < 0) {
    perror("connect");
    exit(EXIT_FAILURE);
    }

    return(sd);
    }

    /* Send a file descriptor; returns 1 on success, -1 on error */
    int
    send_fd(int sd, int fd)
    {
    struct msghdr mh;
    struct iovec iv;
    char dummy;

    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = sizeof(char);

    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;

    /* Now we copy in the file descriptor. */
    mh.msg_accrights = (caddr_t)&fd;
    mh.msg_accrightslen = sizeof(int);

    return(sendmsg(sd, &mh, 0));
    }

    /* Returns 1 on success, 0 on EOF, -1 on error. */
    int
    recv_fd(int sd, int *fdp)
    {
    struct msghdr mh;
    struct iovec iv;
    int ret;
    char dummy;

    if (fdp == NULL)
    return(-1);

    memset(&iv, 0, sizeof(iv));
    iv.iov_base = &dummy;
    iv.iov_len = 1;

    memset(&mh, 0, sizeof(mh));
    mh.msg_name = NULL;
    mh.msg_namelen = 0;
    mh.msg_iov = &iv;
    mh.msg_iovlen = 1;
    mh.msg_accrights = (caddr_t)fdp;
    mh.msg_accrightslen = sizeof(int);

    if ((ret = recvmsg(sd, &mh, 0)) < 0)
    return(ret);

    if (mh.msg_accrightslen != sizeof(int))
    return(-1);

    return(1);
    }

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Fri Oct 11 13:30:51 2024
    In article <vea73n$3h7jt$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/7/2024 2:01 PM, Dan Cross wrote:
    As Dave has mentioned, setting SO_SHARE on a socket would be another way >>> to accomplish this.

    Neither of these sounds the same as descriptor passing over Unix
    domain sockets on Unix/Linux; the auxiliary server sounds more
    like `inetd`, in that there's some service that's listening and
    accepting connections on some TCP/IP port, and then creating a
    server to handle each incoming connection.

    I would claim that what I did is NOT passing a descriptor, or whatever, to >another process. Not really sure what that means. All I passed was the device
    name, and let the second process assign a channel to the "existing" device (socket).

    Ok. Conceptually, this is pretty much the same thing, then, at
    least as far as sockets are concerned.

    SO_SHARE is different again; it appears that the shared socket
    must be created before the subprocesses that use it are created.

    I don't know why you would say that.

    I was just wrong.

    A process must exist before it can do
    anything, but, a socket can exist in a process, and then connected to in another
    process, regardless of when the second process is created. For example, if a >bank of worker processes exist, and a task comes in, the connection socket could
    be opened by the existing selected worker process.

    The mechanism on Unix remains a little bit different, maybe, in
    that there's no need to set the socket to be sharable at all;
    indeed, Unix has no analogue of the `SO_SHARE` socket option on
    VMS.

    Vis process creation time, a scenario that could happen on Unix
    is that two processes, A and B, are started; they can run for
    indefinitely long, but at some point well after creation/start,
    A could create a (named) Unix domain socket that is then opened
    by B. A could then create a listening socket and begin
    accepting incoming connections on it, and pass those over the
    Unix domain socket to B. The two processes needn't share any
    kind of parent/child relationship, nor do they have to run as
    the same user, etc; as long as B has appropriate permissions to
    open the socket created by A, this will all work as expected.
    Indeed, this is desireable, as it provides a mechanism for
    privilege separation across a process boundary.

    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to Dan Cross on Fri Oct 11 14:28:35 2024
    In article <vebbst$6qv$1@reader1.panix.com>,
    Dan Cross <cross@spitfire.i.gajendra.net> wrote:
    In particular, the 4.3BSD mechanism uses different fields in the
    `struct msghdr` to move descriptors around, and those are at
    least in the struct definitions on VMS. Do they do anything? I
    kind of tend to doubt it, but for example the code below does
    compile on Eisner, though I haven't written a driver to see if
    it actually _works_.
    [snip]

    PS: I've added this code, along with a driver I tested on
    illumos and the other programs that I've written and posted
    lately (with some bug fixes; ahem) to a repository on github,
    for anyone who's interested in this stuff.

    https://github.com/dancrossnyc/socket-examples

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Fri Oct 11 12:31:03 2024
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    In article <vea73n$3h7jt$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/7/2024 2:01 PM, Dan Cross wrote:
    As Dave has mentioned, setting SO_SHARE on a socket would be another way >>>> to accomplish this.

    Neither of these sounds the same as descriptor passing over Unix
    domain sockets on Unix/Linux; the auxiliary server sounds more
    like `inetd`, in that there's some service that's listening and
    accepting connections on some TCP/IP port, and then creating a
    server to handle each incoming connection.

    I would claim that what I did is NOT passing a descriptor, or whatever, to >> another process. Not really sure what that means. All I passed was the device
    name, and let the second process assign a channel to the "existing" device (socket).

    Ok. Conceptually, this is pretty much the same thing, then, at
    least as far as sockets are concerned.

    SO_SHARE is different again; it appears that the shared socket
    must be created before the subprocesses that use it are created.

    I don't know why you would say that.

    I was just wrong.

    A process must exist before it can do
    anything, but, a socket can exist in a process, and then connected to in another
    process, regardless of when the second process is created. For example, if a
    bank of worker processes exist, and a task comes in, the connection socket could
    be opened by the existing selected worker process.

    The mechanism on Unix remains a little bit different, maybe, in
    that there's no need to set the socket to be sharable at all;
    indeed, Unix has no analogue of the `SO_SHARE` socket option on
    VMS.

    Vis process creation time, a scenario that could happen on Unix
    is that two processes, A and B, are started; they can run for
    indefinitely long, but at some point well after creation/start,
    A could create a (named) Unix domain socket that is then opened
    by B. A could then create a listening socket and begin
    accepting incoming connections on it, and pass those over the
    Unix domain socket to B. The two processes needn't share any
    kind of parent/child relationship, nor do they have to run as
    the same user, etc; as long as B has appropriate permissions to
    open the socket created by A, this will all work as expected.
    Indeed, this is desireable, as it provides a mechanism for
    privilege separation across a process boundary.

    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    - Dan C.


    The share flag is for the device.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Michael S on Fri Oct 11 12:20:36 2024
    On 10/11/2024 6:11 AM, Michael S wrote:
    On Thu, 10 Oct 2024 23:01:13 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/7/2024 4:07 AM, Michael S wrote:
    On Mon, 7 Oct 2024 00:35:36 -0400
    Dave Froble <davef@tsoft-inc.com> wrote:

    On 10/6/2024 11:12 AM, Michael S wrote:
    On Fri, 4 Oct 2024 17:43:02 -0000 (UTC)
    cross@spitfire.i.gajendra.net (Dan Cross) wrote:

    In article <vdp8kn$a67s$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/3/2024 7:00 PM, Chris Townley wrote:
    [snip]
    I don't remember George, but we have certainly woken up Dave!
    ;)

    and I am sure the troll is happy...

    I'm not sure whether I've been insulted?

    I suspect the "troll" reference is to Lawrence. Sadly, Arne can
    not help himself when it comes to resisting arguing with that
    clown.

    - Dan C.


    Troll or not, but the question about ability to pass open TCP
    socket to child process (or, may be, to unrelated process) under
    VMS is a good question.
    As a lurker, I am waiting for the expert answer with interest.


    Well, some of the issue is in the text of the question. What does
    one mean be "pass socket"?

    When creating a socket, one can specify it to be shared. What I
    was doing was passing the information to a worker process, then
    letting the worker process open the existing socket.

    So, would that be considered "passing an open socket"?


    Yes, it would be.

    On Windows one has to go through similar 3-stage procedure:
    - [in parent process] acquire magic record from the open socket by
    means of WSADuplicateSocket()
    - pass the record to child by any of available IPC mechanisms
    - [in child process] use magic record to re-open socket with
    WSASocket()

    I never had a need of for it in practice. Looking at docs it seems
    that the procedure above has at least one inconvenient aspect - the
    target process has to exist at the moment of WSADuplicateSocket()
    call. Still, I suppose that it's better than nothing.

    I can post some of the development code is anyone is interested. I
    was working on the inter-process communications when I dropped the
    project. I believe I did open the shared socket in the worker
    process.


    May be, others are interested in the code.
    For me, I'd rather read textual description of the procedure and war
    story of making it work.


    Actually, simple.

    1) Create the socket in listener process
    2) Pass device name to worker process
    3) Assign a channel to the device in worker process
    4) deassign the channel in listener process (if desired)


    There are few pieces in your simple explanation that I don't understand:

    I posted the sample code.

    Understand, I used the QIO interface, not CRTL.

    - How does listener get a device name?

    Note that we're discussing BG devices.

    - What is "channel"? Is it the same as 'socket'?

    Channel is VMS channel

    - How one "assigns" channel to device? I would guess that device has to
    be open before that?

    If one has a device name, then one can assign a channel to that device.

    - Is device name of the socket system-global?

    Yes, I think so.

    If yes, does it mean that any process in the system that happens to
    know a name can open a device and assign it to channel?

    If shared access is specified, then yes.


    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Fri Oct 11 17:45:30 2024
    In article <vebjse$3nq13$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    [snip]
    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    The share flag is for the device.

    Ok, sure. But does that mean that there's _no_ authorization
    checking of any kind to access the device? For example, no
    checking UICs or ACLs or something? If I set SO_SHARE on a
    socket, can _any_ process on the system, regardless of who it is
    running as, access that socket?

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Dan Cross on Fri Oct 11 13:26:04 2024
    On 10/11/24 12:45 PM, Dan Cross wrote:
    In article <vebjse$3nq13$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    [snip]
    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    The share flag is for the device.

    Ok, sure. But does that mean that there's _no_ authorization
    checking of any kind to access the device? For example, no
    checking UICs or ACLs or something? If I set SO_SHARE on a
    socket, can _any_ process on the system, regardless of who it is
    running as, access that socket?

    $ show device/full

    on any BG device shows normal-looking device protections just as you
    would see on any other device, e.g.:

    Dev Prot S:RWPL,O:RWPL,G:RWPL,W:RWPL

    I don't think socket sharing is a privilege any more than file sharing
    is; more likely it's just a hint to the driver that it needs to do extra
    work to keep its internal state consistent when two processes are
    accessing it.

    There is an old Ask-the-Wizard article about socket sharing that uses a
    mailbox to send the BG device name to the child process:

    https://forum.vmssoftware.com/viewtopic.php?f=35&t=3511&p=7513

    The example code sends UCX$C_SHARE using the QIO interface rather than
    SO_SHARE and setsockopt(); I'm guessing it amounts to the same thing but
    I can't find current relevant documentation for either.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to Craig A. Berry on Fri Oct 11 18:56:53 2024
    In article <vebqjs$3oaus$1@dont-email.me>,
    Craig A. Berry <craigberry@nospam.mac.com> wrote:

    On 10/11/24 12:45 PM, Dan Cross wrote:
    In article <vebjse$3nq13$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    [snip]
    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    Just to be clear, because I think there may be some confusion,
    but nowhere above was I suggesting that the `SHARE` _privilege_
    is the same as the `SO_SHARE` _option_ on a socket.

    The share flag is for the device.

    Ok, sure. But does that mean that there's _no_ authorization
    checking of any kind to access the device? For example, no
    checking UICs or ACLs or something? If I set SO_SHARE on a
    socket, can _any_ process on the system, regardless of who it is
    running as, access that socket?

    $ show device/full

    on any BG device shows normal-looking device protections just as you
    would see on any other device, e.g.:

    Dev Prot S:RWPL,O:RWPL,G:RWPL,W:RWPL

    Interestingly, for BG devies, they're _all_ the same, with the R
    bit set for everyone, which, if they just used the default
    scheme, would mean that any socket device was ASSIGNable to
    anyone, right? That does not sound correct. For example, here
    is an `ssh` socket on Eisner:

    |Device BG8729:, device type unknown, is online, record-oriented device, network
    | device, mailbox device.
    |
    | Error count 0 Operations completed 210
    | Owner process "SSHD 0012" Owner UIC [SYSTEM]
    | Owner process ID 00003C50 Dev Prot S:RWPL,O:RWPL,G:RWPL,W:RWPL
    | Reference count 2 Default buffer size 256

    Surely the device protection field here is misleading, at best?

    I don't think socket sharing is a privilege any more than file sharing
    is; more likely it's just a hint to the driver that it needs to do extra
    work to keep its internal state consistent when two processes are
    accessing it.

    That seems right, given what we've seen. Anyway, I think this
    put's to rest Arne's assertion that there's no way to give some
    process access to a socket created by another process.

    There is an old Ask-the-Wizard article about socket sharing that uses a >mailbox to send the BG device name to the child process:

    https://forum.vmssoftware.com/viewtopic.php?f=35&t=3511&p=7513

    The example code sends UCX$C_SHARE using the QIO interface rather than >SO_SHARE and setsockopt(); I'm guessing it amounts to the same thing but
    I can't find current relevant documentation for either.

    I saw that; most of the solutions in this space look more or
    less the same. I confess I remain mystified by the seeming lack
    of an authorizaton mechanism, however.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to Craig A. Berry on Fri Oct 11 21:07:18 2024
    On Fri, 11 Oct 2024 13:26:04 -0500, Craig A. Berry wrote:

    I don't think socket sharing is a privilege any more than file sharing
    is; more likely it's just a hint to the driver that it needs to do extra
    work to keep its internal state consistent when two processes are
    accessing it.

    Surely having channels from two processes assigned to the same device is
    no different, as far as the device is concerned, from having two channels assigned to it in the same process. In VMS, process scheduling is
    completely decoupled from I/O management; once an I/O is queued, nothing further happens to affect the process until the completed request gets
    back to the I/O post-processing system, at which point it no longer
    concerns the device driver any more.

    At least, that’s how it used to work in the VMS of old.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to davef@tsoft-inc.com on Fri Oct 11 21:29:34 2024
    In article <vec4sb$3qc1e$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 1:45 PM, Dan Cross wrote:
    In article <vebjse$3nq13$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    [snip]
    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    The share flag is for the device.

    Ok, sure. But does that mean that there's _no_ authorization
    checking of any kind to access the device? For example, no
    checking UICs or ACLs or something? If I set SO_SHARE on a
    socket, can _any_ process on the system, regardless of who it is
    running as, access that socket?

    Dan, it's been quite a while, so I'd have to research that question.

    If I had to guess, I'd expect all VMS protections and such to be respected. I >doubt one could just go out and access any BG device without having access.

    I should hope so, Dave, but as it is, it looks under
    documented at best.

    - Dan C.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dave Froble@21:1/5 to Dan Cross on Fri Oct 11 17:21:06 2024
    On 10/11/2024 1:45 PM, Dan Cross wrote:
    In article <vebjse$3nq13$1@dont-email.me>,
    Dave Froble <davef@tsoft-inc.com> wrote:
    On 10/11/2024 9:30 AM, Dan Cross wrote:
    [snip]
    As I gather, on VMS the analogous mechanism works since a) every
    socket on the system is associated with a unique device name in
    some global namespace, and b) once known, an unrelated process
    can $ASSIGN that device name, subject to authorization checking
    enforced by the system. The authorization checks seem to be
    either, a) a process/subprocess relationship, or b) the
    assigning process has the SHARE privilege; it's not clear to me
    what else could go into those checks and how that interacts with
    e.g. SO_SHARE; presumably at least UIC checks or something must
    be completed?

    The share flag is for the device.

    Ok, sure. But does that mean that there's _no_ authorization
    checking of any kind to access the device? For example, no
    checking UICs or ACLs or something? If I set SO_SHARE on a
    socket, can _any_ process on the system, regardless of who it is
    running as, access that socket?

    - Dan C.


    Dan, it's been quite a while, so I'd have to research that question.

    If I had to guess, I'd expect all VMS protections and such to be respected. I doubt one could just go out and access any BG device without having access.

    --
    David Froble Tel: 724-529-0450
    Dave Froble Enterprises, Inc. E-Mail: davef@tsoft-inc.com
    DFE Ultralights, Inc.
    170 Grimplin Road
    Vanderbilt, PA 15486

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Craig A. Berry@21:1/5 to Dan Cross on Fri Oct 11 16:43:26 2024
    On 10/11/24 1:56 PM, Dan Cross wrote:
    In article <vebqjs$3oaus$1@dont-email.me>,
    Craig A. Berry <craigberry@nospam.mac.com> wrote:

    $ show device/full

    on any BG device shows normal-looking device protections just as you
    would see on any other device, e.g.:

    Dev Prot S:RWPL,O:RWPL,G:RWPL,W:RWPL

    Interestingly, for BG devies, they're _all_ the same, with the R
    bit set for everyone, which, if they just used the default
    scheme, would mean that any socket device was ASSIGNable to
    anyone, right? That does not sound correct. For example, here
    is an `ssh` socket on Eisner:

    |Device BG8729:, device type unknown, is online, record-oriented device, network
    | device, mailbox device.
    |
    | Error count 0 Operations completed 210
    | Owner process "SSHD 0012" Owner UIC [SYSTEM]
    | Owner process ID 00003C50 Dev Prot S:RWPL,O:RWPL,G:RWPL,W:RWPL
    | Reference count 2 Default buffer size 256

    Surely the device protection field here is misleading, at best?

    Well, you _can_ change the values:

    $ show security/class=device bg111

    _BG111: object of class DEVICE
    Owner: [SYSTEM]
    Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: RWPL)
    Access Control List: <empty>

    $ set security/class=device/protection=(w:r) bg111
    $ show security/class=device bg111

    _BG111: object of class DEVICE
    Owner: [SYSTEM]
    Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: R)
    Access Control List: <empty>

    Note that World is now read, but write, physical, and logical have been removed. But I don't really know if that accomplished anything. It
    seems unlikely that BGDRIVER would just fill in values in a template
    that don't mean anything, but testing out exactly what the protections
    get you sounds like work.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From =?UTF-8?Q?Arne_Vajh=C3=B8j?=@21:1/5 to Craig A. Berry on Fri Oct 11 18:52:01 2024
    On 10/11/2024 5:43 PM, Craig A. Berry wrote:
    Well, you _can_ change the values:

    $ show security/class=device bg111

    _BG111: object of class DEVICE
         Owner: [SYSTEM]
         Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: RWPL)
         Access Control List: <empty>

    $ set security/class=device/protection=(w:r) bg111
    $ show security/class=device bg111

    _BG111: object of class DEVICE
         Owner: [SYSTEM]
         Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: R)
         Access Control List: <empty>

    Note that World is now read, but write, physical, and logical have been removed.  But I don't really know if that accomplished anything.  It
    seems unlikely that BGDRIVER would just fill in values in a template
    that don't mean anything, but testing out exactly what the protections
    get you sounds like work.

    The names give strong associations.

    So I would expect:

    IO$_READVBLK - need R
    IO$_READLBLK - need R and L
    IO$_READPBLK - need R and P
    IO$_WRITEVBLK - need W
    IO$_WRITELBLK - need W and L
    IO$_WRITEPBLK - need W and P

    And the guide to system security says:

    <quote>
    5.3.2. Types of Access
    Devices can be shared and thus have concurrent users or be unshared and
    have a single user.
    Shared devices support the following types of access:
    Read Gives you the right to read data from the device
    Write Gives you the right to write data to the device
    Physical Gives you the right to perform physical I/O operations to the
    device
    Logical Gives you the right to perform logical I/O operations to the device Control Gives you the right to change the protection elements and owner
    of the device
    Unshared devices support only read, write, and control access. The
    device driver rather than the
    operating system's security policy defines the access requirements for
    other types of operations.
    ...
    $QIO to file-oriented devices: disks and tapes
    With file-oriented devices, logical I/O and physical I/O functions have
    common elements. Any
    logical I/O function requires physical or logical access plus read
    access to read a block (READLBLK)
    or write access to write a block (WRITELBLK). Any physical I/O function requires physical
    access plus either read access to read a block (READPBLK) or write
    access to write a block
    (WRITEPBLK). Logical and physical I/O also require LOG_IO and PHY_IO privileges, respectively.
    ...
    $QIO to devices that are not file-oriented
    With non-file-oriented devices, OpenVMS converts virtual read and write
    I/O requests to logical I/O
    before processing them. Other kinds of access requests are not processed
    by OpenVMS; instead, the
    request is passed to the device driver for processing.
    In general, access requirements for devices that are not file oriented
    depend on whether the device is
    shareable or nonshareable:
    • Shareable device
    With shareable devices, such as mailboxes, any virtual I/O function
    other than READVBLK/
    WRITEVBLK is handled by the system I/O driver program. Any logical I/O
    function requires
    privilege or logical access to the device. Any physical I/O function
    requires privilege or physical
    access to the device.
    • Unshareable devices
    With unshareable devices, such as terminals or printers, the operating
    system checks only for read
    or write access to perform virtual and logical I/O functions. Any
    physical I/O function requires
    privilege.
    </quote>

    Which I read as confirmation. It works like expected for
    file oriented devices and for shareable non file oriented
    devices, but non shareable non file oriented devices ignore
    L and P. BG devices are shareable non file oriented
    devices.

    Arne




    Arne

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Mark Daniel@21:1/5 to Craig A. Berry on Sat Oct 12 09:38:52 2024
    On 12/10/2024 08:13, Craig A. Berry wrote:

    On 10/11/24 1:56 PM, Dan Cross wrote:
    8< snip 8<
    Surely the device protection field here is misleading, at best?

    Well, you _can_ change the values:

    $ show security/class=device bg111

    _BG111: object of class DEVICE
         Owner: [SYSTEM]
         Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: RWPL)
         Access Control List: <empty>

    $ set security/class=device/protection=(w:r) bg111
    $ show security/class=device bg111

    _BG111: object of class DEVICE
         Owner: [SYSTEM]
         Protection: (System: RWPL, Owner: RWPL, Group: RWPL, World: R)
         Access Control List: <empty>

    Note that World is now read, but write, physical, and logical have been removed.  But I don't really know if that accomplished anything.  It
    seems unlikely that BGDRIVER would just fill in values in a template
    that don't mean anything, but testing out exactly what the protections
    get you sounds like work.

    Bit fiddly but to show the protections apply the original BG_EXAMPLE.C
    was modified to wait for a read from the telnet connection

    chan = decc$get_sdc (csock);
    printf ("chan: %d\n", chan);
    if (!chan) return (vaxc$errno);

    cptr = GetBgDevice (chan);
    printf ("BgDevice: |%s|\n", cptr);

    memset (buf, 0, sizeof(buf));
    count = recv (csock, buf, sizeof(buf), 0);
    printf ("count: %d |%s|\n", count, buf);
    if (count <= 0) return (vaxc$errno);

    and the executable installed to provide the SHARE privilege for an
    otherwise unprivileged account

    X86VMS$ install replace DKA100:[SCRATCH]bg2_example.exe /priv=share

    The listener output then became

    X86VMS$ mcr []bg2_example
    accept()
    chan: 304
    BgDevice: |BG11402:|

    The SYSTEM account (fully privileged) could write to the socket

    X86VMS$ mcr []bg2_example BG11402:
    sys$setprv() %X00000001
    sys$assign() %X00000001
    sys$qiow() 14 %X00000001 %X00000001
    write() 14 %X00000001

    %TELNET-I-SESSION, Session 01, host localhost, port 8765
    -TELNET-I-ESCAPE, Escape character is ^]
    abcdefghij

    klmnopqrst

    As could the unprivileged account (using the INSTALLed SHARE privilege)

    12-OCT-2024 09:26:08.36 User: MGD Process ID: 000045A3
    Node: X86VMS Process name: "MGD"

    Authorized privileges:
    NETMBX TMPMBX

    Process privileges:
    NETMBX may create network device
    TMPMBX may create temporary mailbox

    X86VMS$ mcr []bg2_example BG11402:
    sys$setprv() %X00000001
    sys$assign() %X00000001
    sys$qiow() 14 %X00000001 %X00000001
    write() 14 %X00000001

    but after modifying the BG device security (pasted as quotation to
    circumvent wrapping)

    X86VMS$ set sec BG11402: /class=device /prot=(world)
    X86VMS$ show dev /full BG11402:

    Device BG11402:, device type unknown, is online, mounted, record-oriented
    device, network device, mailbox device.

    Error count 0 Operations completed 2
    Owner process "FTA10_SYSTEM" Owner UIC [SYSTEM]
    Owner process ID 00001599 Dev Prot S:RWPL,O:RWPL,G:RWPL,W
    Reference count 1 Default buffer size 256

    X86VMS$ mcr []bg2_example BG11402:
    sys$setprv() %X00000001
    sys$assign() %X00000024
    write() -1 %X0000013C
    X86VMS$ exit %X00000024
    %SYSTEM-F-NOPRIV, insufficient privilege or object protection violation
    X86VMS$ exit %X00000024

    while the owner (SYSTEM) continued to have access

    X86VMS$ mcr []bg2_example BG11402:
    sys$setprv() %X00000001
    sys$assign() %X00000001
    sys$qiow() 14 %X00000001 %X00000001
    write() 14 %X00000001

    --
    Anyone, who using social-media, forms an opinion regarding anything
    other than the relative cuteness of this or that puppy-dog, needs
    seriously to examine their critical thinking.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dan Cross@21:1/5 to mark.daniel@wasd.vsm.com.au on Sat Oct 12 00:29:59 2024
    In article <aeiOO.1076078$jVLc.666165@fx15.ams4>,
    Mark Daniel <mark.daniel@wasd.vsm.com.au> wrote:
    [snip]
    Bit fiddly but to show the protections apply the original BG_EXAMPLE.C
    was modified to wait for a read from the telnet connection

    [snip]
    but after modifying the BG device security (pasted as quotation to
    circumvent wrapping)

    X86VMS$ set sec BG11402: /class=device /prot=(world)
    X86VMS$ show dev /full BG11402:

    Device BG11402:, device type unknown, is online, mounted, record-oriented
    device, network device, mailbox device.

    Error count 0 Operations completed 2
    Owner process "FTA10_SYSTEM" Owner UIC [SYSTEM]
    Owner process ID 00001599 Dev Prot S:RWPL,O:RWPL,G:RWPL,W
    Reference count 1 Default buffer size 256

    X86VMS$ mcr []bg2_example BG11402:
    sys$setprv() %X00000001
    sys$assign() %X00000024
    write() -1 %X0000013C
    X86VMS$ exit %X00000024
    %SYSTEM-F-NOPRIV, insufficient privilege or object protection violation >X86VMS$ exit %X00000024

    while the owner (SYSTEM) continued to have access

    [snip]

    Perfect; thanks. I think this shows definitely how the access
    mechanism applies to BG devices. I wonder why the default is to
    be W:R....

    - Dan C.

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