8
\$\begingroup\$

I've been writing a simple code just for fun:

This is a simple WinForms application with which you can measure your typing speed. There are three controls on it, doing the following:

  • rtbResults - The one where you need to be as quick as possible.
  • textBox1 - The one where you submit the reference text.
  • tbBestTime - The one storing the best time of a "contestant".

Fields:

Stopwatch sw = new Stopwatch();
long bestTime = long.MaxValue;

One handler:

private void rtbResults_TextChanged(object sender, EventArgs e)
{
    if (rtbResults.Text.Length == 1)
    {
        sw.Restart();
    }
    else
    {
        if (rtbResults.Text == textBox1.Text)
        {
            sw.Stop();
            if (sw.ElapsedMilliseconds < bestTime)
            {
                bestTime = sw.ElapsedMilliseconds;
                tbBestTime.Text = (bestTime / 1000.0).ToString();
            }

            MessageBox.Show("Your time: " + sw.ElapsedMilliseconds / 1000.0 + "s.");
            sw = null;
            rtbResults.Text = "";
        }
    }
}

Another handler:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    bestTime = long.MaxValue;
    tbBestTime.Text = bestTime.ToString();
}

Now I'm looking for techniques to optimize the performance to get more precise results. The point is not the memory consumption, but the length of the source code and the performance, and of course it must result the same as it does now (I mean the mentioned code).

I would like you to consider the following issues:

Is the...

  • Stopwatch
  • TextChanged event
  • type long
  • if/else (instead of if/return)

... the best way to do this?

\$\endgroup\$
6
\$\begingroup\$

Your code seems to me to be as efficient as reasonable for the application you are writing...

... but what you want/intend to do with it is unreasonable.... but first:

  • The method resetting the time is not very practical

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        bestTime = long.MaxValue;
        tbBestTime.Text = bestTime.ToString();
    }
    

    This method is setting the text to a value that the typical user will have no frame of reference for.... why is that 'big' number meaningful. Why not just set the tbBestTime.Text to be 'None yet' or something? This is especially significant since all other times the tbBestTime is set, you set it to a floating-point time/1000.0 value.

  • In your messageBox you do a simple /1000.0 for your time display. This is not going to always be 'pretty' since not all floating point values have a neat representation in binary. You should be using a Number formatter to ensure that the presentation of the value is consistent.... consider Custom Numeric Format Strings.

Finally, lets talk about accuracy and precision....

  • precision is reporting values to a large number of significant figures. In your case, reporting the time to (an intended) millisecond precision seems like a good idea, but, is that accurate?

Your intention with this question is to improve the accuracy of the results by reducing the overhead of the code when compared to the typing.

Unfortunately there is so much happening between your code and the keyboard that any attempt to increase the code performance will be outweighed by the simple operations happening on the system.... The following are things that may/will affect the accuracy of your timing:

  1. Key debouncing
  2. Interrupt handling
  3. OS event notification
  4. OS Thread scheduling
  5. Clock granularity
  6. TextBox listener notification

I would wager that each of these will be significantly more time than the per-cycle cost of your code.

Optimizing your code will make no difference to the accuracy of your timing, and, as it is, your reported precision is probably far more than the actual accuracy. In fact, I would suggest that anything within 1/10th of a second (instead of 1/1000th) is a 'tie'.

\$\endgroup\$
  • \$\begingroup\$ Thank you rolfl for your detailed answer. It is very helpful for me! \$\endgroup\$ – Mitulát báti Dec 23 '13 at 19:01
3
\$\begingroup\$

One way to get around system events interfering with the recording of the elapsed time, is to take a snapshot of the current time(DateTime.Now) when the typing starts and another when the typed text equals the source text. A timespan of the difference between the two will give you reasonable accuracy on the elapsed time. This way too, your output can easily be formatted as time instead of just a number.

Another thing to consider is typing tests usually use words per minute for grading rather than total time.

\$\endgroup\$
  • \$\begingroup\$ This is a good idea I will implement into my program. Thank you very much! \$\endgroup\$ – Mitulát báti Dec 23 '13 at 19:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.