[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
/*****************************************************************************/
/*
                                MemBufDemo.c

This script is intended to demonstrate the use of the MemBufLib..() functions,
as well as allowing a direct comparison of the throughputs of the mailbox
(default) and memory-buffer IPCs for script output.  Testing indicates transfer
bandwidth in excess of 500% of the standard mailbox IPC, along with notable
improvements in resource utilisation.  YMMV with platform, O/S version and
TCP/IP stack (i.e. as the relative bottlenecks shuffle about).

The memoy-buffer IPC is intended for bulk data transfer from a script to the
server and then on to the client.  In this case, "bulk" means megabytes, tens
of megabytes, hundreds of megabytes, and so forth.  For kilobytes, tens,
hundreds of kilobytes the mailbox IPC is suitable for most applications.

To compare the throughputs of the actual IPC, it is best to eliminate as much
storage access as possible (often the slowest element in a VMS system).  This
script ganerates a block of data comprising a repeating byte value.  The value
is incremented with each block and ranges from 0x00 thru to 0xff before
repeating.  The memset() used to populate the block is very efficient.

It is recommended to use a command-line tool such as cURL or wget with output
directed to the NL: device.  Output can also be directed to storage for the
purposes of comparing the content of both IPCs while building confidence in the
memory-buffer IPC.

The behaviour of the script is controlled by keys in the query string.

  ?<transfer-Mbytes>+[b|m]+<MRS-kbytes>+<memory-buffer-size-Mbytes>

No query string the default behaviour is a 10MB transfer via mailbox IPC.

  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo

The first key can be an integer number of *megabytes* to transfer.  For 5MB and
100MB respectively:

  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?5
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?100

The second key is a character indicating the IPC; 'm' for mailbox (default) and
'b' for (memory-)buffer.  The first and third examples are mailbox and the
second and fourth memory-buffer.

  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?5
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?5+b
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?250+m
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?250+b

The third key is an integer number of bytes for the record size.  This is the
mailbox maximum record size (MRS) in kilobytes, and so is limited to the WASD
configuration for script SYS$OUTPUT size.  With memory-buffer it can be
specified as any size up to size of the memory-buffer itself.  The default is
the mailbox MRS size. The first example specifies a MRS of 32kB and the second
256kB.

  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?100+m+32
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?100+b+256

The fourth key is an integer number of megabytes for the memory-buffer.  The
default is 1MB.  Any value may be provided here with the server memory-buffer
manager either providing that size of an error report back in the callout.  The
first examples request a 2MB memory-buffer and the second 5MB.

  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?100+b+256+2
  $ wget "-O" NL: http://the.host/cgi-bin/membufdemo?100+b+128+5

To compare the data provided by both environments direct output to files and
use the difference UTILITY.

  $ wget "-O" []TEST.DAT http://the.host/cgi-bin/membufdemo?50
  $ wget "-O" []TEST.DAT http://the.host/cgi-bin/membufdemo?50+b
  $ diff TEST.DAT

WATCH may be used to observe the behaviour and data, etc., but beware with such
large datasets many browsers cannot cope with the copious report output,
particularly with [x]network-octets item, and in the case of mailbox IPC, with
the [x]DCL item.  YMMV.


COMPARISON
----------
Actual data generated by this utility comparing standard mailbox IPC with
memory-buffer on a HP rx2660 (1.40GHz/6.0MB) with 4 CPUs and 16383MB running
VMS V8.4-2L1 with Multinet UCX$IPC_SHR V55A-B147, OpenSSL 1.0.2k and WASD
v11.1.1, with [BufferSizeDclOutput] 16384.

|$  wget "-O" nl: http://127.0.0.1/cgi-bin/membufdemo?250
|--2017-10-14 03:19:05--  http://127.0.0.1/cgi-bin/membufdemo?250
|Connecting to 127.0.0.1:80... connected.
|HTTP request sent, awaiting response... 200 OK
|Length: 262144000 (250M) [application/octet-stream]
|Saving to: 'nl:'
|
|nl:                 100%[=====================>] 250.00M  25.6MB/s   in 12s
|
|2017-10-14 03:19:17 (20.5 MB/s) - 'nl:' saved [262144000/262144000]
|
|$  wget "-O" nl: http://127.0.0.1/cgi-bin/membufdemo?250+b
|--2017-10-14 03:19:23--  http://127.0.0.1/cgi-bin/membufdemo?250+b
|Connecting to 127.0.0.1:80... connected.
|HTTP request sent, awaiting response... 200 OK
|Length: 262144000 (250M) [application/octet-stream]
|Saving to: 'nl:'
|
|nl:                 100%[=====================>] 250.00M   105MB/s   in 2.4s
|
|2017-10-14 03:19:26 (105 MB/s) - 'nl:' saved [262144000/262144000]
|
|$  wget "-O" nl: https://127.0.0.1/cgi-bin/membufdemo?250
|--2017-10-14 03:19:50--  https://127.0.0.1/cgi-bin/membufdemo?250
|Connecting to 127.0.0.1:443... connected.
|HTTP request sent, awaiting response... 200 OK
|Length: 262144000 (250M) [application/octet-stream]
|Saving to: 'nl:'
|
|nl:                 100%[=====================>] 250.00M  14.5MB/s   in 17s
|
|2017-10-14 03:20:07 (14.5 MB/s) - 'nl:' saved [262144000/262144000]
|
|$  wget "-O" nl: https://127.0.0.1/cgi-bin/membufdemo?250+b
|--2017-10-14 03:20:12--  https://127.0.0.1/cgi-bin/membufdemo?250+b
|HTTP request sent, awaiting response... 200 OK
|Length: 262144000 (250M) [application/octet-stream]
|Saving to: 'nl:'
|
|nl:                 100%[=====================>] 250.00M  16.6MB/s   in 15s
|
|2017-10-14 03:20:27 (16.6 MB/s) - 'nl:' saved [262144000/262144000]

It is obvious that memory-buffer provides significantly greater throughput than
mailbox (from the http:// test) and that with TLS/SSL network transport the
encryption becomes a significant overhead and choke-point.  Nevertheless, there
is still an approximate 15% dividend, plus the more efficient interface the
script->memory-buffer->server provides.  The VMS TLS/SSL implementation may
improve with time, especially if TLS/SSL hardware engines become available with
the port to x86_64.

POSTSCRIPT: The comparison also illustrates that the WASD environment can
deliver significant bandwidth through its script->server->network pathways.
On the demonstration class of system; ~200Mbps unencrypted and ~120Mbps
encrypted using the standard mailbox IPC; with ~850Mbps unencrypted and
~130Mbps encrypted using the memory-buffer IPC.


LOGICAL NAMES
-------------
None.


BUILD DETAILS
-------------
See BUILD_MEMBUFDEMO.COM procedure.


COPYRIGHT
---------
Copyright (C) 2017-2021 Mark G.Daniel

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


VERSION HISTORY
---------------
12-OCT-2017  MGD  initial
*/
/*****************************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

#include "membuflib.h"

void MemBufDemoAbort (int);

/*****************************************************************************/

main (int argc, char* argv[])

{
   int  bcnt, cnt, gsize, mbfs, mrs, retval, status, total, value;
   char  *bptr, *cptr, *gname, *mbptr, *sptr;

   /*********/
   /* begin */
   /*********/

   gsize = 0;
   gname = mbptr = NULL;

   if (cptr = getenv("WWW_GATEWAY_MRS"))
      mrs = atoi(cptr);
   else
      mrs = 0;
   if (!mrs) mrs = 8192;

   /* first is the total transfer in megabytes */
   if (cptr = getenv ("WWW_KEY_1"))
      total = atoi(cptr);
   else
      total = 0;
   if (total <= 0) total = 100;
   total *= (1024 * 1024);

   /* second is using 'm' mailbox (default) or memory-'b'buffer */
   if (cptr = getenv ("WWW_KEY_2"))
   {
      if (*cptr == 'b')
      {
         /* using memory buffer (otherwise using mailbox) */
         mbptr = "";
      }
   }

   /* third is size of MRS in bytes */
   if (cptr = getenv ("WWW_KEY_3"))
   {
      /* size of internal buffer (maximum record size) in bytes */
      if (atoi(cptr)) mrs = atoi(cptr);
   }

   if (!(bptr = malloc(mrs))) exit (vaxc$errno);

   /* fourth is memory-buffer size is in *megabytes* */
   if (cptr = getenv ("WWW_KEY_4"))
      mbfs = atoi(cptr);
   else
      mbfs = 0;

   if (mbptr)
   {
      /* using memory buffer */
      status = MemBufLibBegin (mbfs, &gname, NULL, &gsize);
      if (!(status & 1)) MemBufDemoAbort (status); 
   }

   /* response header */

   if (!(stdout = freopen ("SYS$OUTPUT", "w", stdout, "ctx=bin")))
      exit (vaxc$errno);

   fprintf (stdout,
"Content-Type: application/octet-stream\r\n\
Content-Length: %d\r\n\
X-mrs: %d\r\n\
X-mbuf: %s %u\r\n\
\r\n",
           total, mrs,
           gname ? gname : "NULL", gsize);
   fflush (stdout);

   /* write data */

   bcnt = value = 0;
   while (bcnt < total)
   {
      memset (bptr, (value++ & 0xff), mrs);
      if (((cnt = mrs) + bcnt) > total) cnt = total - bcnt;
      if (mbptr)
         retval = MemBufLibWrite (bptr, cnt);
      else
         retval = fwrite (bptr, cnt, 1, stdout);
      if (!retval) exit (44);
      bcnt += cnt;
   }

   /* finalise */

   if (mbptr) MemBufLibEnd ();
}

/*****************************************************************************/

void MemBufDemoAbort (int status)

{

   /*********/
   /* begin */
   /*********/

   fprintf (stdout,
"Status: 500\r\n\
Content-Type: text/plain\r\n\
\r\n\
MemBufLib() returned %%X%08.08X\n",
            status);

   exit (status);
}

/*****************************************************************************/