Skip to main content
Topic: VBScript I/O Test (Read 34606 times) previous topic - next topic

VBScript I/O Test

Quote from: Scripts\ioTest.vbs
Option Explicit ' NWC2 User Tool, Ver 1.0 - Rick G.
'WScript Scripts\iotest.vbs <PROMPT:Test?=#>
Dim a, s,  mark: mark = Timer
Select Case WScript.Arguments(0)
   Case 1
      Do Until WScript.StdIn.AtEndOfStream
         s = WScript.StdIn.ReadLine
         WScript.StdOut.WriteLine s
      Loop
   Case 2
      a = Split(WScript.StdIn.ReadAll, vbCrLf)
      WScript.StdOut.Write Join(a, vbCrLf)
End Select
WScript.StdErr.WriteLine Round(Timer - mark, 2) & " seconds"
WScript.Quit(1)
Copy the above into NotePad and save it to you Scripts folder as: ioTest.vbs
&Command: is WScript Scripts\ioTest.vbs <PROMPT:Test?=#>

Open the sample file: consecration.nwc and click on the Violins II staff.
I think this staff has the most objects of any in the Samples folder.

My times for the various tests are:
  • Test 0: 0.00 - 0.02 seconds.
  • Test 1: 0.35 - 0.50 seconds.
  • Test 2: 0.05 - 0.08 seconds.
It takes NWC2 a half-second or so more to display this.

Win98 is about 10% faster than XP. I have an AMD 500mHz processor.
I am curious if this is the same for multi-core processors. I would seem to me that Test 1 might allow the script to get started before all its STDIN was created.

Results from others appreciated.
Registered user since 1996

Re: VBScript I/O Test

Reply #1
G'day Rick,

My times for the various tests are:
  • Test 0: 0.00 - 0.02 seconds.
  • Test 1: 0.08 - 0.1 seconds.
  • Test 2: 0.00 - 0.02 seconds.

PC is 3 GHz P4 with 1 GB RAM running XP Media Center Edition with SP2 installed (completely up to date with m$ patches)
I plays 'Bones, crumpets, coronets, floosgals, youfonymums 'n tubies.

Re: VBScript I/O Test

Reply #2
Thanks Lawrie.
I guess size does matter :)  It looks like nothing is going thru the disk subsystem. You seem to get a 5x improvement with a 6x faster processor.

Your differences are nearly imperceptable to the user. I'm hoping that in the future, a User Tool will be able to request nwctxt, selection start/end and/or cursor position (~10x the size of a staff clip). The difference would be noticeable.
Registered user since 1996

Re: VBScript I/O Test

Reply #3
NWC2 handles the user script request in a serial fashion. Any optimizations done at the low level will likely not depend on the content of the script.

As your script name suggests, this test should primarily be a test of the IO subsystem (the hard disk). Your "Split" and "Join" calls will slow things down (at the micro-time level), but the WScript.StdIn.ReadLine/WScript.StdOut.WriteLine and WScript.StdIn.ReadAll/WScript.StdOut.Write calls should be the slowest points by far (improved by Windows or the hard disk caching the I/O in memory). You should gain a little by using WScript.StdIn.ReadAll, since script processing is not returned until the entire StdIn is read (improving memory and script throughput). However,  you should lose some using Split and Join. Repeated invocations of any script should be optimized by various Windows and hardware optimizations, thus finishing a little faster. The reported real world results implies that the memory management required for Split and Join require significantly less resources compared to the IO. However, the absence of a "Do" loop in case 2 means that no real work is done, thus further reducing the CPU load.

My tests confirm prior posted results. Case 1 is slower than Case 2.

Re: VBScript I/O Test

Reply #4
Thanks for the response.
Ver 1.1 presented as an exercise in "fairness". Output is the same as Ver 1.0
Quote
Option Explicit ' NWC2 User Tool, Ver 1.1 - Rick G.
'WScript Scripts\iotest.vbs <PROMPT:Test?=#>
Dim a, s,  mark: mark = Timer
Select Case WScript.Arguments(0)
   Case 1
      Do Until WScript.StdIn.AtEndOfStream
         s = WScript.StdIn.ReadLine
         WScript.StdOut.WriteLine s
      Loop
   Case 2
      Do Until WScript.StdIn.AtEndOfStream
         a = Split(WScript.StdIn.ReadAll, vbCrLf)
         WScript.StdOut.Write Join(a, vbCrLf)
      Loop
End Select
WScript.StdErr.WriteLine Round(Timer - mark, 2) & " seconds"
WScript.Quit(1)
Attached is a VBScript version of nwswStatisticsReport.php
It may help someone trying to translate PHP<=>VBScript. I wouldn't mind seeing a JavaScript version using regular expressions to do the parsing.
Registered user since 1996

Re: VBScript I/O Test

Reply #5
I am not sure what this Ver 1.1 is intended to do. Your case 2 do loop won't actually do anything, since the ReadAll will automatically move the file pointer to EOF. If a staff has 2000 objects, your case 1 will have to loop over itself for 2000 iterations, while case 2 will only iterate once, thus making it faster.

Re: VBScript I/O Test

Reply #6
I am not sure what this Ver 1.1 is intended to do. Your case 2 do loop won't actually do anything ...
Your claim was that Case 2 in Ver 1.0 did no real work when in fact it provides everything that Case 1 does, is faster and allows non-sequential processing. I wanted some tests to see if it was faster in a multi-processor environment. I was trying to be diplomatic, hence the quotes around fairness. Looks like I failed.
Registered user since 1996

Re: VBScript I/O Test

Reply #7
My point was that case 1 iterates through each line of input, thus creating the opportunity to act on each line. In order to achieve the same possibility with case 2, the script could end up iterating through a, which could very well consume the saved cycles. Case 1 could likely be made faster by simply storing the output in a variable, then dumping it with a single Write after the loop completes, eliminating the alternating disk read/write cycle for each line. This would be at the cost of additional memory demands.

In any case, the results returned back to NWC2 could very well be the largest contributor to response delays. In addition to reading the actual output, the reconstruction of the selection takes considerable memory churn and CPU cycles.

Re: VBScript I/O Test

Reply #8
Case 1 could likely be made faster by simply storing the output in a variable, then dumping it with a single Write after the loop completes, eliminating the alternating disk read/write cycle for each line. This would be at the cost of additional memory demands.
Alternation doesn't seem to use any time. The new Case 2 in the attached ver 1.2 is faster than Case 1 since it does only 1 write, but slower than Case 3 & 4 where I actually do some trivial work on each line.
My point was that case 1 iterates through each line of input, thus creating the opportunity to act on each line. In order to achieve the same possibility with case 2, the script could end up iterating through a, which could very well consume the saved cycles.
Not many. Case 3 & 4 show this.
In any case, the results returned back to NWC2 could very well be the largest contributor to response delays. In addition to reading the actual output, the reconstruction of the selection takes considerable memory churn and CPU cycles.
I can live with the response delays. That was not my purpose here. I was just trying to find the best way to handle StdIn/Out/Err. I think it is now clear that ReadAll and one StdOut write has the best performance.
Registered user since 1996

Re: VBScript I/O Test

Reply #9
I wouldn't mind seeing a JavaScript version using regular expressions to do the parsing.
Here's a JScript version. Didn't need regular expressions.
Copy everything below the line and save it to your Scripts folder as: Stats.js

[php]
/*
   NWC2 User Tool, Ver 1.0 - Rick G.
   JScript version of nwswStatisticsReport.php
   &Command: WScript Scripts\Stats.js
*/
var i, mark = new Date(), s;
// convert notation clip text to an array of lines
var stdin = WScript.StdIn.ReadAll().split("\r\n");
// init these so they will always report
var d = {"Total Items":0, "Clef":0, "Key":0,
   "TimeSig":0, "Bar":0, "Note":0, "Chord":0};

// count objects. non-objects are counted as 'undefined'
for (i in stdin){ // i = array index (integer)
   s = stdin.split("|")[1]; // objType or undefined
   d = (0 | d) + 1; // increment, create keys as needed
}
delete d.undefined; s = ""; // cleanup
for (i in d) d["Total Items"] += d;
for (i in d) s += ("    " + d + " ").slice(-6) + i + "\n";

// report to STDOUT, elapsed time to STDERR
WScript.StdOut.Write("Statistics Report:\n\n" + s);
WScript.StdErr.Write("The STDOUT file contains the report.\n" +
   ((new Date() - mark) / 1000).toFixed(2) + " seconds\n");
WScript.Quit(99); // show STDOUT page to user
[/php]
Registered user since 1996