Is there any reason to avoid a busy while loop?

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I have a real-time simulation where the logic flows most easily with a busy
while loop...

while (continueFlagSet)
{
if (EventDue)
ProcessNextEvent
}

Now, is there any thing to be concerned about here? With older versions of
Windows, I wouldn't have trusted the operating system to share the processor,
so I would have put an "else Sleep(0)" at the bottom of the loop, but this is
2005, and shouldn't I leave it to the operating system to manage processes,
and threads, without any hints from me?

When i'm running the application, there isn't any obvious impact on my other
Windows apps, or other threads in the same app, but I haven't tested this
thoroughly.

I am mindful of an excellent essay I read where the author listed "Sleep" as
one of the common sources of problems in windows apps, and which is almost
never needed. http://www.flounder.com/badprogram.htm
 
wait on event, then I don't see an issue. continueFlagSet should be a
another event (i.e. reset event) or syncd when set and tested if set from
another thread.
 
Thanks...

A sloppy example on my part. "if (EventDue)" is referring to a logical
event, not a system event which I can wait on. eg, in a movie playing system,
it would be "if (next frame due)". I'm processing up to 200 events per
second. I don't think I can afford the overhead of creating system events,
and waitng on them.

Yes, continueFlagSet is handled with Interlocked, which I think does the job
of synchronization.

Javaman
 
Yes, continueFlagSet is handled with Interlocked, which I think does the
job
of synchronization.

Yes it does. As to locking (side issue), on my 1.86GH PMobil laptop, I can
get about 27 Million locks per second including an increment operation (per
test below). In most cases, the lock overhead is not going to be a
bottleneck for your app. It is too bad that the documentation seems to make
a big deal out of lock overhead, because if done right, is not really an
issue in most cases. So in terms of your 200 work items per second
requirement, locking overhead is almost nothing. Naturally, you could have
locking bugs, but that is another issue. Interlocked should be fine for
your int however.

object sync = new object();
Stopwatch sw = new Stopwatch();
sw.Start();
for ( int i = 0; i < 27000000; )
{
lock ( sync )
{
i++;
}
}
sw.Stop();
Console.WriteLine("Sec:{0} ms:{1}", sw.Elapsed.Seconds,
sw.Elapsed.Milliseconds);
 
Thanks William, that's very interesting. I'll never worry about the time for
getting a lock again.
 
William Stacey said:
Yes it does. As to locking (side issue), on my 1.86GH PMobil laptop, I
can get about 27 Million locks per second including an increment operation
(per test below). In most cases, the lock overhead is not going to be a
bottleneck for your app. It is too bad that the documentation seems to
make a big deal out of lock overhead, because if done right, is not really
an issue in most cases. So in terms of your 200 work items per second
requirement, locking overhead is almost nothing. Naturally, you could
have locking bugs, but that is another issue. Interlocked should be fine
for your int however.

object sync = new object();
Stopwatch sw = new Stopwatch();
sw.Start();
for ( int i = 0; i < 27000000; )
{
lock ( sync )
{
i++;
}
}
sw.Stop();
Console.WriteLine("Sec:{0} ms:{1}", sw.Elapsed.Seconds,
sw.Elapsed.Milliseconds);

While I agree that taking a lock is not that expensive when there is no
contention, it's still not the right thing to do when all you need is
perform an atomic thread-safe operation like incrementing or decrementing a
variable.
Taking a lock is still 20 times slower than a Interlocked.Increment(ref i);

Willy.
 
Back
Top