/*****************************************************************************/ /* 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. ?+[b|m]++ 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 #include #include #include #include #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); } /*****************************************************************************/