Techical Tips
Mike Robinson
As soon as Win95 and the like came out, programmers said, "ohboy! Threads!"
Well, sometimes they are really really good. But sometimes multithreaded apps
actually seem to run slower, and have more overhead, than their equivalent
Win31 implementation.
TIP: MULTIPLE THREADS DON'T MULTIPLY THE CPU.
If you've got more than one CPU in there, terrific. Otherwise, having
multiple "concurrent" threads won't make things faster because by definition
only one of them is executing at a time. Furthermore, the more threads you
have, the more overhead is being spent switching between them. If you have
more than one or two "always busy" threads in your design, multithreading
won't make the program faster. The opposite will be true!
TIP: USE THREADS TO OVERLAP COMPUTING WITH I/O.
In a sense that is what threads are -for.- A thread that does computing can
ignore the need of the system to respond rapidly to I/O requests. It can
ignore everything but itself, relying upon the operating system to pre-empt it
to handle input/output. Threading allows a program to remain responsive to
users and devices while maximizing use of the CPU as well. Threading also
allows the computer to respond to many devices expediently, AS LONG AS the
amount of computing-time required to service the device is minimal.
TIP: ALSO USE THREADS TO PRIORITIZE THINGS.
Threads can be given relative priorities so that less-urgent tasks can be
completed in the background. This is a way of fair-sharing the CPU resource.
Just remember that you have only one CPU, and some of those tasks are gonna
"take it in the shorts." If your program's overall function relies upon the
product of one of those low-priority tasks, then the program itself will
appear erratic.
TIP: WATCH FOR CONTENTION.
Threads work great when they are independent. They start to boggle down
(becoming no better than, and maybe worse than a message queue) when they have
to synchronize around some shared resource. Locking and critical-section
overhead is expensive.
TIP: DON'T FORGET THE USER INTERFACE IS A CONTENTION TOO!
One of the most hotly-contested resources in the system is the user interface.
After all, Windows itself is its own set of high-priority tasks that are
competing with yours. And if several threads are trying to update the same
window at the same time, visual chaos results.
TIP: MANAGE THE WORKLOAD... THERE ARE TOOLS TO DO THAT.
Too many threads, and Windows starts flopping like a dying fish. It's called
"thrashing" and it's not pretty. You can't simply create "one thread per user
request" and hope that Windows sorts it all out. It won't. You have to
manage the incoming workload so that it gets processed efficiently,
production-line style, and so that you can monitor and control it like a
machine.
It turns out, by the way, that this is a process that gets done so
much (MVS and DOS/VS were doing it before you were born, maybe...) that you
can buy "transaction monitors," and other pieces of software that can snap
into your applications, to queue and regulate the flow of work through a
multi-user or server-style application.
Remember also that "a process that can't really be completed in a concurrent
fashion ... doesn't need separate threads, it needs a message queue."
TIP: REMEMBER THAT MEMORY IS VIRTUAL.
The virtual-memory mechanism survives by guessing what pieces of 'memory' need
to be in RAM and what parts can be swapped out to disk. Threads complicate
the situation if they are working on different areas of the virtual-memory
space at the same time. They increase the "working-set size" of the program
significantly. Remember always that memory is not really "free." Think of
access to memory as being synonymous with access to a disk file, and build the
application accordingly.
TIP: SERIALIZE EVERYTHING EXPLICITLY.
Each time any one of your threads accesses a shared resource, be it memory or
a file or what-have-you, you must serialize that activity in some way.
Critical sections, semaphores, and good ol' message-queues are good ways to do
that. The pitfall is that you can test your application and not run into
these timing bugs, but the first time your users or customers run it, they
WILL! X-(
TIP: DELEGATE RESPONSIBILITIES, NOT JUST TIME.
So you must serialize everything that is shared, but serializing interferes
with concurrency which is, of course, the reason for having the multiple
threads in the first place. This is why it is often a good idea to delegate
specific responsibilities to the threads, and to use "loose coupling" (such as
message queueing) between them. It's better to have well-defined units of
work flowing in queues between a relatively small number of tasks with
discrete, independent responsibilities... than to have a large number of
supposedly-autonomous tasks locked up in a slugfest.
Please email me and tell me if you liked this page.
This page has been created with |
![HomeSite 2.5b](/file/23366/Chip_1998-03_cd.bin/zkuste/delphi/DELINFO/Uddf/IMAGES/HS25ANI.GIF)
|