66 lines
No EOL
4.5 KiB
Markdown
66 lines
No EOL
4.5 KiB
Markdown
It might also be worth converting the search engine to assembly for
|
|
searches performed entirely in memory; with the overhead of file access
|
|
eliminated, improvements in search-engine performance would translate
|
|
directly into significantly faster overall performance. One such
|
|
application that would have much the same structure as Listing 5.1 would
|
|
be searching through expanded memory buffers, and another would be
|
|
searching through huge (segment-spanning) buffers.
|
|
|
|
And so we find, as we so often will, that optimization is definitely not
|
|
a cut-and-dried matter, and that there is no such thing as a single
|
|
"best" approach.
|
|
|
|
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
 *You must know what your application will typically do, and you must know whether you're more concerned with average or worst-case performance before you can decide how best to speed up your program—and, indeed, whether speeding it up is worth doing at all.*
|
|
------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
By the way, don't think that just because very large block sizes don't
|
|
much improve performance, it wasn't worth using restartable blocks in
|
|
Listing 5.1. Listing 5.1 runs more than three times more slowly with a
|
|
block size of 32 bytes than with a block size of 4K, and any
|
|
byte-by-byte approach would surely be slower still, due to the overhead
|
|
of repeated calls to DOS and/or the C stream I/O library.
|
|
|
|
Restartable blocks do minimize the overhead of DOS file-access calls in
|
|
Listing 5.1; it's just that there's no way to reduce that overhead to
|
|
the point where it becomes worth attempting to further improve the
|
|
performance of our relatively efficient search engine. Although the
|
|
search engine is by no means fully optimized, it's nonetheless as fast
|
|
as there's any reason for it to be, given the balance of performance
|
|
among the components of this program.
|
|
|
|
### Always Look Where Execution Is Going {#Heading10}
|
|
|
|
I've explained two important lessons: Know when it's worth optimizing
|
|
further, and use restartable blocks to process large data sets as a
|
|
series of blocks, with each block handled at high speed. The first
|
|
lesson is less obvious than it seems.
|
|
|
|
When I set out to write this chapter, I fully intended to write an
|
|
assembly language version of Listing 5.1, and I expected the assembly
|
|
version to be much faster. When I actually looked at where execution
|
|
time was going (which I did by modifying the program to remove the calls
|
|
to the **read()** function, but a code profiler could be used to do the
|
|
same thing much more easily), I found that the best code in the world
|
|
wouldn't make much difference.
|
|
|
|
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
 *When you try to speed up code, take a moment to identify the hot spots in your program so that you know where optimization is needed and whether it will make a significant difference before you invest your time.*
|
|
------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
As for restartable blocks: Here we tackled a considerably more complex
|
|
application of restartable blocks than we did in Chapter 1—which turned
|
|
out not to be so difficult after all. Don't let irregularities in the
|
|
programming tasks you tackle, such as strings that span blocks, fluster
|
|
you into settling for easy, general—and slow—solutions. Focus on making
|
|
the inner loop—the code that handles each block—as efficient as
|
|
possible, then structure the rest of your code to support the inner
|
|
loop.
|
|
|
|
Programming with restartable blocks isn't easy, but when speed is an
|
|
issue, using restartable blocks in the right places more than pays for
|
|
itself with greatly improved performance. And when speed is *not* an
|
|
issue, of course, or in code that's not time-critical, you wouldn't
|
|
dream of wasting your time on optimization.
|
|
|
|
Would you? |