Note that there are some explanatory texts on larger screens.

plurals
  1. POStrange performance issues reading from stdout
    text
    copied!<p>I'm working on some code that will be used to test other executables. For convenience I'll refer to my code as the tester and the code being tested as the client. The tester will spawn the client and send commands to the client's stdin and receive results from the client's stdout.</p> <p>I wanted to do some performance testing first so I wrote a very simple example tester and client. The tester waits for the client to write "READY" to its stdout and in response it sends "GO" to the client's stdin. The client then writes some number of bytes to stdout, configured via a command line flag, and then writes "\nREADY\n" at which point the tester will again write "GO". This repeats 10,000 times after which I calculate the time it took to complete the test and the "throughput", the 10,000 divided by the time to complete.</p> <p>I ran the above test having the client send 0, 10, 100, 1000, 10000, and 100000 bytes of data before it sends "READY". For each byte size I repeated the test 10 times and took the average. When run on my laptop in an Ubuntu VMWare instance I got a throughput of about 100k GO/READY pairs per second. The performance was fairly stable and had virtually no dependence on the number of binary bytes the client sends to the tester. I then repeated the test on a very fast, 24 core server running CentOS. With a 0 byte payload I observed only about 55k GO/READY pairs per second and the performance degraded noticably as the number of bytes the client sent increased. When the client sends 100k bytes between "GO" and "READY" the throughput was only about 6k operations per second.</p> <p>So I have three questions</p> <ol> <li>Why would the same code run much more slowly on a faster machine</li> <li>Why would the performance in the virtual machine be independent of payload size but the performance on the fast server be heavily dependent on payload size?</li> <li>Is there anything I can do to make things faster on the server</li> </ol> <p>One possible explanation is that I recompiled the code on the fast server and it is using a different version of the C++ libraries. The VMWare machine is running Ubuntu 11.10 and the fast sever is running CentOS 6. Both are 64 bit machines.</p> <p>The relevant tester code is as follows:</p> <pre><code>ios_base::sync_with_stdio(false); const int BUFFER_SIZE = 2 &lt;&lt; 20; char buffer[BUFFER_SIZE]; process_stdout-&gt;rdbuf()-&gt;pubsetbuf(buffer, BUFFER_SIZE); Timer timer; // Wait until the process is ready string line; line.reserve(2 &lt;&lt; 20); getline(*process_stdout, line); CHECK(line == "READY"); timer.Start(); for (int i = 0; i &lt; num_trials; ++i) { *process_stdin &lt;&lt; "GO\n"; process_stdin-&gt;flush(); line = ""; while (line != "READY") { getline(*process_stdout, line); } } double elapsed = timer.Elapsed(); cout &lt;&lt; "Done. Did " &lt;&lt; num_trials &lt;&lt; " iterations in " &lt;&lt; elapsed &lt;&lt; " seconds. Throughput: " &lt;&lt; double(num_trials) / elapsed &lt;&lt; " per second." &lt;&lt; endl; </code></pre> <p>I also tried versions using read() calls (from unistd.h) into a 1MB buffer and calls to memchr to find the "\n" characters and look for READY but got the same performance results.</p> <p>The relevant client code is as follows:</p> <pre><code>// Create a vector of binary data. Some portion of the data will be sent // to stdout each time a "GO" is received before sending "READY" vector&lt;char&gt; byte_source; const int MAX_BYTES = 1 &lt;&lt; 20; for (int i = 0; i &lt; MAX_BYTES; ++i) { byte_source.push_back(i % 256); } cout &lt;&lt; "READY" &lt;&lt; endl; while (cin.good()) { string line; getline(cin, line); if (line == "GO") { // The value of response_bytes comes from a command line flag OutputData(response_bytes, byte_source); cout &lt;&lt; "READY" &lt;&lt; endl; } } // write bytes worth of data from byte_source to stdout void OutputData(unsigned int bytes, const vector&lt;char&gt;&amp; byte_source) { if (bytes == 0) { return; } cout.write(&amp;byte_source[0], bytes); cout &lt;&lt; "\n"; } </code></pre> <p>Any help would be greatly appreciated!</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload