Why setting a Label's text by using String.Format() runs 20 times faster with some Int32 variables than with other Int32 variables?

Viewed 54

I found a very weird problem by accident, and did some tests. Did I discover some hidden Framework bug?

(Note: I use Visual Studio 2010 and my target is .Net Framework 3.5 Client Profile, but I don't see how that could be the reason).

I have a Windows Forms project, with a form, label and button that starts a Timer component (added to the form in Visual Studio's designer).

Hitting a button starts the timer, and then it ticks after 500 ms and stops itself, after running some code that also sets a label's text based on some int variable.

        private void buttonTest_Click(object sender, EventArgs e)
        {
            if (!timer1.Enabled)
            {
                timer1.Start();
            }
        }

I'm really confused, why the following two codes don't run almost the same fast (and why the difference is so huge).

What is going on? Please, help me to find the reason.

Code 1 results with the message, showing: "00:00:00.050" on average. So it takes about 50 ms every time I hit a button that restarts the form's timer.

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;

            for (int i = 0; i < 10000; i++)
            {
                labelTest.Text = String.Format("Text {0}", DateTime.Now.Millisecond);
            }

            timer1.Stop();

            MessageBox.Show((DateTime.Now - dt).ToString());
        }

Code 2 results with the message, showing: "00:00:00.900" on average. So it takes about 900 ms every time I hit a button that restarts the form's timer.

        private void timer1_Tick(object sender, EventArgs e)
        {
            DateTime dt = DateTime.Now;

            for (int i = 0; i < 10000; i++)
            {
                labelTest.Text = String.Format("Text {0}", i);
            }

            timer1.Stop();

            MessageBox.Show((DateTime.Now - dt).ToString());
        }

I supply to String.Format Int32 values in both cases, and I actually expected the first code to run slightly slower than the second one, because of accessing DataTime's properties...

But the first code runs for 50 ms, and the second code runs for 900 ms.

Also, I tried commenting the timer1.Stop(); and the MessageBox code, to make sure that the codes are really that much different in their execution speed.

And as a result I noticed that when I try to move the form around with a mouse cursor, with the first code it's being moved smoothly and the program barely takes any processing time in my Task Manager. But the second code makes the form freeze every half a second (as expected) and also the processor load was very noticeable in my Task Manager.

What kind of magic is this?...

1 Answers

DateTime.Now usually has a limited granularity of ~16ms, so if you repeatedly access DateTime.Now in a short period, most of the values returned will be exactly the same. As a result in your first code snippet, many of the loop iterations will in fact be setting the label's text to the value it is already set to. If you check the .NET source for the Control.Text property, you can see that if you set the Text to the current value, it returns immediately since it doesn't need to do anything.

On the other hand, the loop in the second code snippet sets the label's text to a different value on every iteration, so the label runs the full text-setting code every time. It's therefore doing much more work than the loop in the first code snippet, so naturally takes longer.

Related