Back in my VAX days (VMS-4.0 to VMS-6.2) doing any kind of I/O was very expensive so it was always better to concatenate data
before doing any serial I/O (like BASIC's PRINT statement). We proved this using system accounting to measure run-time stats. (not
the best development tool but better than nothing)
When we moved from VAX to Alpha in 1999-2001 we only used OpenVMS-7.x and noticed everything was less costly (I/Os, spawns,
queuing, etc.) but accounting tests proved it was still better to concatenate string data before doing an I/O in BASIC. (caveat:
this was never true in C/C++)
My recent tests with HP-BASIC-1.7 on OpenVMS-8.4 indicate that something has changed (probably for the better) over the past ten-years which now make pre-i/o concatenations unnecessary. This is also the first time I've seen the smallest binary also consume the least amount of system resources on this RISC system.
I do not have an explanation for this (because HP's solution is hidden behind BASIC RTL routines) but can imagine:
Program | DBASIC$ calls | STR$CONCAT calls | Total Calls | Size of $CODE$ section |
---|---|---|---|---|
Neil1.bas | 33 | 0 | 33 | 1004 |
Neil2.bas | 23 | 10 | 33 | 1084 |
Neil3.bas | 5 | 15 | 20 | 844 |
Neil4.bas | 21 | 0 | 21 | 732 |
Neil5.bas | 15 | 0 | 15 | 552 |
1000 ! neil1.bas (individual PRINT statements) ! Compiled Routine Size: 1156 (optim=level=0) ! Compiled Routine Size: 1004 (optim=level=4) option type=explicit declare string abc$ abc$ = "abc" print '<tr>'; print '<td>'; abc$ ;'</td>'; print '<td>'; abc$ ;'</td>'; print '<td>'; abc$ ;'</td>'; print '<td>'; abc$ ;'</td>'; print '<td>'; abc$ ;'</td>'; print '</tr>' 1040 end
1000 ! neil2.bas (individual PRINT statements; some plus signs) ! Compiled Routine Size: 1236 (optim=level=0) ! Compiled Routine Size: 1084 (optim=level=4) option type=explicit declare string abc$ abc$ = "abc" print '<tr>'; print '<td>'+ abc$ +'</td>'; print '<td>'+ abc$ +'</td>'; print '<td>'+ abc$ +'</td>'; print '<td>'+ abc$ +'</td>'; print '<td>'+ abc$ +'</td>'; print '</tr>' 1040 end
1000 ! neil3.bas (one PRINT, all plus signs) ! Compiled Routine Size: 948 (optim=level=0) ! Compiled Routine Size: 844 (optim=level=4) option type=explicit declare string abc$ abc$ = "abc" print '<tr>'+ & '<td>'+ abc$ +'</td>'+ & '<td>'+ abc$ +'</td>'+ & '<td>'+ abc$ +'</td>'+ & '<td>'+ abc$ +'</td>'+ & '<td>'+ abc$ +'</td>'+ & '</tr>' 1040 end
1000 ! neil4.bas (one PRINT, all semicolons) ! Compiled Routine Size: 868 (optim=level=0) ! Compiled Routine Size: 732 (optim=level=4) option type=explicit declare string abc$ abc$ = "abc" print '<tr>'; & '<td>'; abc$ ;'</td>'; & '<td>'; abc$ ;'</td>'; & '<td>'; abc$ ;'</td>'; & '<td>'; abc$ ;'</td>'; & '<td>'; abc$ ;'</td>'; & '</tr>' 1040 end
1000 ! neil5.bas (one PRINT; mixture of semicolons and plus signs) ! Compiled Routine Size: 580 (optim=level=0) ! Compiled Routine Size: 552 (optim=level=4) option type=explicit declare string abc$ abc$ = "abc" print '<tr>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '</tr>' 1040 end
NEIL5$MAIN Source Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 1 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 1 1000 ! neil5.bas (one PRINT; mixture of semicolons and plus signs) 2 ! Compiled Routine Size: 580 (optim=level=0) 3 ! Compiled Routine Size: 552 (optim=level=4) 4 option type=explicit 5 declare string abc$ 6 abc$ = "abc" 7 print '<tr>'+ & 8 '<td>'; abc$ ;'</td>'+ & 9 '<td>'; abc$ ;'</td>'+ & 10 '<td>'; abc$ ;'</td>'+ & 11 '<td>'; abc$ ;'</td>'+ & 12 '<td>'; abc$ ;'</td>'+ & 13 '</tr>' 14 1040 end NEIL5$MAIN Source Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 2 Allocation Map 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 Allocation information for main program NEIL5$MAIN Offset based on (FP) Name Offset Size Type ABC$ -8 8 Dynamic string PROGRAM SECTIONS Name Bytes Attributes 0 $READ_ONLY$ 132 PIC CON REL LCL SHR NOEXE RD NOWRT OCTA 1 $CODE$ 552 PIC CON REL LCL SHR EXE NORD NOWRT OCTA 2 $LINK$ 216 NOPIC CON REL LCL NOSHR NOEXE RD NOWRT OCTA 3 $LITERAL$ PIC CON REL LCL SHR NOEXE RD NOWRT OCTA 4 $ARRAY 0 NOPIC CON REL LCL NOSHR NOEXE RD WRT OCTA 5 $DESC 0 NOPIC CON REL LCL NOSHR NOEXE RD WRT OCTA NEIL5$MAIN Source Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 3 Qualifier Summary 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 BASIC/REAL_SIZE=DOUBLE/INTEGER_SIZE=LONG/OPTIM=LEVEL=4/LIST/MACHINE NEIL5.BAS DEFAULT DATA TYPE INFORMATION: LISTING FILE INFORMATION INCLUDES: Data type : EXPLICIT List Real size : DOUBLE NO Cross reference Integer size : LONG CDD Definitions Decimal size : (15,2) Environment Scale factor : 0 NO Override of %NOLIST NO Round decimal numbers Machine code Map COMPILATION QUALIFIERS IN EFFECT: INCLUDE files Object file NO Separate_compilation FLAGGERS: NO Line NO Declining features Variant : 0 Warnings DEBUG INFORMATION: Informationals Traceback records NO Alignment warnings NO Debug symbol records NO Diagnostics NO Audit OPTIMIZE SETTINGS: NO Analysis data Level : 4 NO Placeholders Tune : GENERIC NO Comments Architecture : GENERIC Old Version : NO CDD Arrays Overflow check integers NO Dependency data Overflow check decimal numbers NO TIE Bounds checking NO Synchronous exceptions NEIL5$MAIN Machine Code Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 4 NEIL5$MAIN 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 .PSECT $CODE$, OCTA, PIC, CON, REL, LCL, SHR,- EXE, NORD, NOWRT 0000 NEIL5$MAIN:: 23DEFF00 0000 LDA SP, -256(SP) A63B0050 0004 LDQ R17, 80(R27) 47E05419 0008 MOV 2, R25 B75E00E0 000C STQ R26, 224(SP) B77E0000 0010 STQ R27, (SP) A75BFFD0 0014 LDQ R26, -48(R27) B7FE0008 0018 STQ R31, 8(SP) B45E00E8 001C STQ R2, 232(SP) B47E00F0 0020 STQ R3, 240(SP) B7BE00F8 0024 STQ FP, 248(SP) 63FF0000 0028 TRAPB 47FE041D 002C MOV SP, FP 23DEFFF0 0030 LDA SP, -16(SP) 47FB0402 0034 MOV R27, R2 221D0008 0038 LDA R16, 8(FP) A762FFD8 003C LDQ R27, -40(R2) 6B5A4000 0040 JSR R26, DBASIC$INIT ; R26, R26 A7420040 0044 LDQ R26, 64(R2) ; 000006 261F010E 0048 LDAH R16, 270(R31) 404B1000 004C ADDL R2, 88, R0 223D00A8 0050 LDA R17, 168(FP) B01D00AC 0054 STL R0, 172(FP) 47E05419 0058 MOV 2, R25 22100003 005C LDA R16, 3(R16) B21D00A8 0060 STL R16, 168(FP) 221DFFF8 0064 LDA R16, ABC$ ; R16, -8(FP) A7620048 0068 LDQ R27, 72(R2) 2FFE0000 006C UNOP 6B5A4000 0070 JSR R26, STR$COPY_DX ; R26, R26 A742FFE0 0074 LDQ R26, -32(R2) ; 000007 47FF0411 0078 CLR R17 221D0008 007C LDA R16, 8(FP) 47E05419 0080 MOV 2, R25 A762FFE8 0084 LDQ R27, -24(R2) 6B5A4000 0088 JSR R26, DBASIC$PRINT ; R26, R26 A7420030 008C LDQ R26, 48(R2) ; 000008 261F010E 0090 LDAH R16, 270(R31) 404E1000 0094 ADDL R2, 112, R0 47E03419 0098 MOV 1, R25 22100008 009C LDA R16, 8(R16) B01D00B4 00A0 STL R0, 180(FP) B21D00B0 00A4 STL R16, 176(FP) 221D00B0 00A8 LDA R16, 176(FP) A7620038 00AC LDQ R27, 56(R2) 6B5A4000 00B0 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 00B4 LDQ R26, 48(R2) 47E03419 00B8 MOV 1, R25 221DFFF8 00BC LDA R16, ABC$ ; R16, -8(FP) A7620038 00C0 LDQ R27, 56(R2) 6B5A4000 00C4 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 00C8 LDQ R26, 48(R2) ; 000009 247F010E 00CC LDAH R3, 270(R31) 40421120 00D0 SUBL R2, 16, R0 221D00B8 00D4 LDA R16, 184(FP) NEIL5$MAIN Machine Code Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 5 NEIL5$MAIN 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 B01D00BC 00D8 STL R0, 188(FP) 20630009 00DC LDA R3, 9(R3) 47E03419 00E0 MOV 1, R25 B07D00B8 00E4 STL R3, 184(FP) A7620038 00E8 LDQ R27, 56(R2) 2FFE0000 00EC UNOP 6B5A4000 00F0 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 00F4 LDQ R26, 48(R2) 47E03419 00F8 MOV 1, R25 221DFFF8 00FC LDA R16, ABC$ ; R16, -8(FP) A7620038 0100 LDQ R27, 56(R2) 6B5A4000 0104 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 0108 LDQ R26, 48(R2) ; 000010 40421120 010C SUBL R2, 16, R0 47E03419 0110 MOV 1, R25 221D00C0 0114 LDA R16, 192(FP) B01D00C4 0118 STL R0, 196(FP) B07D00C0 011C STL R3, 192(FP) A7620038 0120 LDQ R27, 56(R2) 6B5A4000 0124 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 0128 LDQ R26, 48(R2) 221DFFF8 012C LDA R16, ABC$ ; R16, -8(FP) 47E03419 0130 MOV 1, R25 A7620038 0134 LDQ R27, 56(R2) 6B5A4000 0138 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 013C LDQ R26, 48(R2) ; 000011 40421120 0140 SUBL R2, 16, R0 47E03419 0144 MOV 1, R25 221D00C8 0148 LDA R16, 200(FP) B01D00CC 014C STL R0, 204(FP) B07D00C8 0150 STL R3, 200(FP) A7620038 0154 LDQ R27, 56(R2) 6B5A4000 0158 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 015C LDQ R26, 48(R2) 47E03419 0160 MOV 1, R25 A7620038 0164 LDQ R27, 56(R2) 221DFFF8 0168 LDA R16, ABC$ ; R16, -8(FP) 2FFE0000 016C UNOP 6B5A4000 0170 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 0174 LDQ R26, 48(R2) ; 000012 40421120 0178 SUBL R2, 16, R0 221D00D0 017C LDA R16, 208(FP) 47E03419 0180 MOV 1, R25 B01D00D4 0184 STL R0, 212(FP) B07D00D0 0188 STL R3, 208(FP) A7620038 018C LDQ R27, 56(R2) 6B5A4000 0190 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A7420030 0194 LDQ R26, 48(R2) 47E03419 0198 MOV 1, R25 221DFFF8 019C LDA R16, ABC$ ; R16, -8(FP) A7620038 01A0 LDQ R27, 56(R2) 6B5A4000 01A4 JSR R26, DBASIC$OUT_T_DX_S ; R26, R26 A742FFC0 01A8 LDQ R26, -64(R2) ; 000013 243F010E 01AC LDAH R1, 270(R31) 404A1123 01B0 SUBL R2, 80, R3 221D00D8 01B4 LDA R16, 216(FP) B07D00DC 01B8 STL R3, 220(FP) NEIL5$MAIN Machine Code Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 6 NEIL5$MAIN 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 2021000A 01BC LDA R1, 10(R1) 47E03419 01C0 MOV 1, R25 B03D00D8 01C4 STL R1, 216(FP) A762FFC8 01C8 LDQ R27, -56(R2) 2FFE0000 01CC UNOP 6B5A4000 01D0 JSR R26, DBASIC$OUT_T_DX_B ; R26, R26 A7420060 01D4 LDQ R26, 96(R2) 47E03419 01D8 MOV 1, R25 221D0008 01DC LDA R16, 8(FP) A7620068 01E0 LDQ R27, 104(R2) 6B5A4000 01E4 JSR R26, DBASIC$IO_END ; R26, R26 01E8 L$2: ; 000014 A742FFA0 01E8 LDQ R26, -96(R2) 221D0008 01EC LDA R16, 8(FP) 63FF0000 01F0 TRAPB 47E03419 01F4 MOV 1, R25 A762FFA8 01F8 LDQ R27, -88(R2) 2FFE0000 01FC UNOP 6B5A4000 0200 JSR R26, DBASIC$END ; R26, R26 63FF0000 0204 TRAPB ; 000001 47FD041E 0208 MOV FP, SP A75D00E0 020C LDQ R26, 224(FP) A45D00E8 0210 LDQ R2, 232(FP) 47E03400 0214 MOV 1, R0 ; 000014 A47D00F0 0218 LDQ R3, 240(FP) ; 000001 A7BD00F8 021C LDQ FP, 248(FP) 23DE0100 0220 LDA SP, 256(SP) 6BFA8001 0224 RET R26 Routine Size: 552 bytes, Routine Base: $CODE$ + 0000 .PSECT $LINK$, OCTA, NOPIC, CON, REL, LCL,- NOSHR, NOEXE, RD, NOWRT 0000 .LINKAGE DBASIC$END 64742F3C 0010 .ASCII \</td></tr>\ 742F3C3E 0014 3E72 0018 0020 .LINKAGE DBASIC$OUT_T_DX_B 0030 .LINKAGE DBASIC$INIT 0040 .LINKAGE DBASIC$PRINT 64742F3C 0050 .ASCII \</td><td>\ 64743C3E 0054 3E 0058 0060 ; Stack-Frame invocation descriptor Entry point: NEIL5$MAIN Entry Length: 48 Static Handler: DBASIC$HANDLER Registers used: R0-R3, R16-R17, R25-R26, R28-FP Registers saved: R2-R3, FP Fixed Stack Size: 256 00000000 ; Handler data for DBASIC$HANDLER 00000000 00000000 NEIL5$MAIN Machine Code Listing 27-OCT-2013 10:12:01 Alpha BASIC V1.7-001 Page 7 NEIL5$MAIN 27-OCT-2013 09:37:13 CSMIS$USER3:[ADMCSM.NEIL]NEIL5.BAS;2 00000000 0090 .LINKAGE DBASIC$OUT_T_DX_S 00A0 .LINKAGE STR$COPY_DX 00000000 00B0 .ADDRESS $READ_ONLY$ 636261 00B8 .ASCII \abc\ 00C0 .LINKAGE DBASIC$IO_END 3E72743C 00D0 .ASCII \<tr><td>\ 3E64743C 00D4 .PSECT $READ_ONLY$, OCTA, PIC, CON, REL, LCL,- SHR, NOEXE, RD, NOWRT $$1: 00000008 0000 .LONG X^8 , - ; .LONG 8 00000001 0004 .LONG X^1 , - ; .LONG 1 00000000 0008 .LONG X^0 , - ; .LONG 0 00000000 000C .LONG X^0 , - ; .LONG 0 000000B8 0010 .LONG X^B8 , - ; .LONG 184 00000000 0014 .LONG X^0 , - ; .LONG 0 0000007C 0018 .LONG X^7C , - ; .LONG 124 00000084 001C .LONG X^84 , - ; .LONG 132 00000084 0020 .LONG X^84 , - ; .LONG 132 00000084 0024 .LONG X^84 , - ; .LONG 132 00000000 0028 .LONG X^0 , - ; .LONG 0 00000000 002C .LONG X^0 , - ; .LONG 0 00000084 0030 .LONG X^84 , - ; .LONG 132 00000000 0034 .LONG X^0 , - ; .LONG 0 00000000 0038 .LONG X^0 , - ; .LONG 0 00000000 003C .LONG X^0 , - ; .LONG 0 00000000 0040 .LONG X^0 , - ; .LONG 0 FFFFFFF8 0044 .LONG X^FFFFFFF8 , - ; .LONG -8 00000000 0048 .LONG X^0 , - ; .LONG 0 FFFFFFF0 004C .LONG X^FFFFFFF0 , - ; .LONG -16 00000001 0050 .LONG X^1 , - ; .LONG 1 00000000 0054 .LONG X^0 , - ; .LONG 0 00000000 0058 .LONG X^0 , - ; .LONG 0 00000000 005C .LONG X^0 , - ; .LONG 0 00000000 0060 .LONG X^0 , - ; .LONG 0 00004080 0064 .LONG X^4080 , - ; .LONG 16512 00000000 0068 .LONG X^0 , - ; .LONG 0 00000000 006C .LONG X^0 , - ; .LONG 0 00000000 0070 .LONG X^0 , - ; .LONG 0 00000000 0074 .LONG X^0 , - ; .LONG 0 00000000 0078 .LONG X^0 ; .LONG 0 $$2: 05 007C .SIGNED_BYTE X^5 ; .SIGNED_BYTE 5 4C49454E 007D .ASCII \NEIL5\ 35 0081
Note: The resulting executable can be run directly by Apache. Just drop it in [.scripts] or [.cgi-bin]
1000 ! Neil Rieck declare string constant k_program = "neil5_www.bas" declare string abc$ ,& long i% abc$ = "abc" margin #0, 1999888777 ! print 'status: 200' ! http status code print 'content-type: text/html' ! print ! end of http block print '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"' print ' "http://www.w3.org/TR/html4/strict.dtd">' print '<html>' print '<head><title>'+ k_program +'</title></head>' print '<meta content="text/html; charset=windows-1252" http-equiv="Content-Type">' print '<body>' print '<p>'+ k_program +'</p>' print '<table>' for i% = 1 to 2000 print '<tr>' + & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '<td>'; abc$ ;'</td>'+ & '</tr>' next i% print '</table>' print '</body>' print '</html>' end