Replace invalid characters with HTML entities

— with —
’ with ’
+ with +
× with x
ç with ç
“ with “
” with ”
‘ with ‘
• with •
– with -
µ with µ
† with †
Fix C++
θ with θ
Yen symbol instead of times
Fix broken apos
Bullet again
E-circumflex
This commit is contained in:
James Gregory 2013-12-30 12:50:32 +11:00
commit 500e7f5654
353 changed files with 5091 additions and 5091 deletions

View file

@ -36,8 +36,8 @@
</TABLE>
</CENTER>
<P><BR></P>
<P>The third reason is often fallacious. C library functions are not always written in assembly, nor are they always particularly well-optimized. (In fact, they&#146;re often written for <I>portability</I>, which has nothing to do with optimization.) What&#146;s more, they&#146;re general-purpose functions, and often can be outperformed by well-but-not- brilliantly-written code that is well-matched to a specific task. As an example, consider Listing 1.5, which uses internal buffering to handle blocks of bytes at a time. Table 1.1 shows that Listing 1.5 is 2.5 to 4 times faster than Listing 1.4 (and as much as 49 times faster than Listing 1.1!), even though it uses no assembly at all.</P>
<TABLE WIDTH="100%"><TD WIDTH="5%" VALIGN="TOP"><IMG SRC="images/i.jpg"><TD WIDTH="95%"><SMALL><I>Clearly, you can do well by using special-purpose C code in place of a C library function&#151;if you have a thorough understanding of how the C library function operates and exactly what your application needs done. Otherwise, you&#146;ll end up rewriting C library functions in C, which makes no sense at all.</I></SMALL>
<P>The third reason is often fallacious. C library functions are not always written in assembly, nor are they always particularly well-optimized. (In fact, they&rsquo;re often written for <I>portability</I>, which has nothing to do with optimization.) What&rsquo;s more, they&rsquo;re general-purpose functions, and often can be outperformed by well-but-not- brilliantly-written code that is well-matched to a specific task. As an example, consider Listing 1.5, which uses internal buffering to handle blocks of bytes at a time. Table 1.1 shows that Listing 1.5 is 2.5 to 4 times faster than Listing 1.4 (and as much as 49 times faster than Listing 1.1!), even though it uses no assembly at all.</P>
<TABLE WIDTH="100%"><TD WIDTH="5%" VALIGN="TOP"><IMG SRC="images/i.jpg"><TD WIDTH="95%"><SMALL><I>Clearly, you can do well by using special-purpose C code in place of a C library function&mdash;if you have a thorough understanding of how the C library function operates and exactly what your application needs done. Otherwise, you&rsquo;ll end up rewriting C library functions in C, which makes no sense at all.</I></SMALL>
</TABLE>
<P><B>LISTING 1.5 L1-5.C</B></P>
<!-- CODE //-->
@ -61,17 +61,17 @@ main(int argc, char *argv[]) {
int WorkingLength, LengthCount;
if ( argc != 2 ) {
printf(&#147;usage: checksum filename\n&#148;);
printf(&ldquo;usage: checksum filename\n&rdquo;);
exit(1);
}
if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
printf(&#147;Can&#146;t open file: %s\n&#148;, argv[1]);
printf(&ldquo;Can&rsquo;t open file: %s\n&rdquo;, argv[1]);
exit(1);
}
/* Get memory in which to buffer the data */
if ( (WorkingBuffer = malloc(BUFFER_SIZE)) == NULL ) {
printf(&#147;Can&#146;t get enough memory\n&#148;);
printf(&ldquo;Can&rsquo;t get enough memory\n&rdquo;);
exit(1);
}
@ -82,29 +82,29 @@ main(int argc, char *argv[]) {
do {
if ( (WorkingLength = read(Handle, WorkingBuffer,
BUFFER_SIZE)) == -1 ) {
printf(&#147;Error reading file %s\n&#148;, argv[1]);
printf(&ldquo;Error reading file %s\n&rdquo;, argv[1]);
exit(1);
}
/* Checksum this chunk */
WorkingPtr = WorkingBuffer;
LengthCount = WorkingLength;
while ( LengthCount&#150;&#150; ) {
while ( LengthCount-- ) {
/* Add each byte in turn into the checksum accumulator */
Checksum &#43;= (unsigned int) *WorkingPtr&#43;&#43;;
Checksum += (unsigned int) *WorkingPtr++;
}
} while ( WorkingLength );
/* Report the result */
printf(&#147;The checksum is: %u\n&#148;, Checksum);
printf(&ldquo;The checksum is: %u\n&rdquo;, Checksum);
exit(0);
}
</PRE>
<!-- END CODE //-->
<P>That brings us to the fourth reason: avoiding an internal-buffered implementation like Listing 1.5 because of the difficulty of coding such an approach. True, it is easier to let a C library function do the work, but it&#146;s not all that hard to do the buffering internally. The key is the concept of handling data in <I>restartable blocks;</I> that is, reading a chunk of data, operating on the data until it runs out, suspending the operation while more data is read in, and then continuing as though nothing had happened.</P>
<P>In Listing 1.5 the restartable block implementation is pretty simple because checksumming works with one byte at a time, forgetting about each byte immediately after adding it into the total. Listing 1.5 reads in a block of bytes from the file, checksums the bytes in the block, and gets another block, repeating the process until the entire file has been processed. In Chapter 5, we&#146;ll see a more complex restartable block implementation, involving searching for text strings.</P>
<P>At any rate, Listing 1.5 isn&#146;t much more complicated than Listing 1.4&#151;and it&#146;s a <I>lot</I> faster. Always consider the alternatives; a bit of clever thinking and program redesign can go a long way.</P>
<P>That brings us to the fourth reason: avoiding an internal-buffered implementation like Listing 1.5 because of the difficulty of coding such an approach. True, it is easier to let a C library function do the work, but it&rsquo;s not all that hard to do the buffering internally. The key is the concept of handling data in <I>restartable blocks;</I> that is, reading a chunk of data, operating on the data until it runs out, suspending the operation while more data is read in, and then continuing as though nothing had happened.</P>
<P>In Listing 1.5 the restartable block implementation is pretty simple because checksumming works with one byte at a time, forgetting about each byte immediately after adding it into the total. Listing 1.5 reads in a block of bytes from the file, checksums the bytes in the block, and gets another block, repeating the process until the entire file has been processed. In Chapter 5, we&rsquo;ll see a more complex restartable block implementation, involving searching for text strings.</P>
<P>At any rate, Listing 1.5 isn&rsquo;t much more complicated than Listing 1.4&mdash;and it&rsquo;s a <I>lot</I> faster. Always consider the alternatives; a bit of clever thinking and program redesign can go a long way.</P>
<H4 ALIGN="LEFT"><A NAME="Heading12"></A><FONT COLOR="#000077">Know How to Turn On the Juice</FONT></H4>
<P>I have said time and again that optimization is pointless until the design is settled. When that time comes, however, optimization can indeed make a significant difference. Table 1.1 indicates that the optimized version of Listing 1.5 produced by Microsoft C outperforms an unoptimized version of the same code by more than 60 percent. What&#146;s more, a mostly-assembly version of Listing 1.5, shown in Listings 1.6 and 1.7, outperforms even the best-optimized C version of List1.5 by 26 percent. These are considerable improvements, well worth pursuing&#151;once the design has been maxed out.
<P>I have said time and again that optimization is pointless until the design is settled. When that time comes, however, optimization can indeed make a significant difference. Table 1.1 indicates that the optimized version of Listing 1.5 produced by Microsoft C outperforms an unoptimized version of the same code by more than 60 percent. What&rsquo;s more, a mostly-assembly version of Listing 1.5, shown in Listings 1.6 and 1.7, outperforms even the best-optimized C version of List1.5 by 26 percent. These are considerable improvements, well worth pursuing&mdash;once the design has been maxed out.
</P>
<P><B>LISTING 1.6 L1-6.C</B></P>
<!-- CODE //-->
@ -129,17 +129,17 @@ main(int argc, char *argv[]) {
int WorkingLength;
if ( argc != 2 ) {
printf(&#147;usage: checksum filename\n&#148;);
printf(&ldquo;usage: checksum filename\n&rdquo;);
exit(1);
}
if ( (Handle = open(argv[1], O_RDONLY | O_BINARY)) == -1 ) {
printf(&#147;Can&#146;t open file: %s\n&#148;, argv[1]);
printf(&ldquo;Can&rsquo;t open file: %s\n&rdquo;, argv[1]);
exit(1);
}
/* Get memory in which to buffer the data */
if ( (WorkingBuffer = malloc(BUFFER_SIZE)) == NULL ) {
printf(&#147;Can&#146;t get enough memory\n&#148;);
printf(&ldquo;Can&rsquo;t get enough memory\n&rdquo;);
exit(1);
}
@ -150,16 +150,16 @@ main(int argc, char *argv[]) {
do {
if ( (WorkingLength = read(Handle, WorkingBuffer,
BUFFER_SIZE)) == -1 ) {
printf(&#147;Error reading file %s\n&#148;, argv[1]);
printf(&ldquo;Error reading file %s\n&rdquo;, argv[1]);
exit(1);
}
/* Checksum this chunk if there&#146;s anything in it */
/* Checksum this chunk if there&rsquo;s anything in it */
if ( WorkingLength )
ChecksumChunk(WorkingBuffer, WorkingLength, &Checksum);
} while ( WorkingLength );
/* Report the result */
printf(&#147;The checksum is: %u\n&#148;, Checksum);
printf(&ldquo;The checksum is: %u\n&rdquo;, Checksum);
exit(0);
}
</PRE>