76 lines
6 KiB
HTML
76 lines
6 KiB
HTML
<HTML>
|
|
<HEAD>
|
|
<META name=vsisbn content="1576101746">
|
|
<META name=vstitle content="Michael Abrash's Graphics Programming Black Book, Special Edition">
|
|
<META name=vsauthor content="Michael Abrash">
|
|
<META name=vspublisher content="The Coriolis Group">
|
|
<META name=vspubdate content="07/01/97">
|
|
<META name=vscategory content="Web and Software Development: Game Development,Web and Software Development: Graphics and Multimedia Development">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<TITLE>Michael Abrash's Graphics Programming Black Book Special Edition: Crossing the Border</TITLE>
|
|
|
|
<!-- HEADER -->
|
|
<!-- Empty Reference Subhead -->
|
|
|
|
<!--ISBN=1576101746//-->
|
|
<!--TITLE=Michael Abrash's Graphics Programming Black Book Special Edition//-->
|
|
<!--AUTHOR=Michael Abrash//-->
|
|
<!--PUBLISHER=The Coriolis Group, Inc.//-->
|
|
<!--CHAPTER=05//-->
|
|
<!--PAGES=121-122//-->
|
|
<!--UNASSIGNED1//-->
|
|
<!--UNASSIGNED2//--></HEAD><BODY LINK=#0000FF ALINK=#000099 VLINK=#0000FF BGCOLOR=#FFFFFF>
|
|
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="05-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="05-05.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
<P><BR></P>
|
|
<H3><A NAME="Heading8"></A><FONT COLOR="#000077">Interpreting Where the Cycles Go</FONT></H3>
|
|
<P>To boost the overall performance of Listing 5.1, I would normally convert <B>SearchForString()</B> to assembly language at this point. However, I’m not going to do that, and the reason is as important a lesson as any discussion of optimized assembly code is likely to be. Take a moment to examine some interesting performance aspects of the C implementation, and all should become much clearer.</P>
|
|
<P>As you’ll recall from Chapter 1, one of the important rules for optimization involves knowing when optimization is worth bothering with at all. Another rule involves understanding where most of a program’s execution time is going. That’s more true for Listing 5.1 than you might think.</P>
|
|
<P>When Listing 5.1 is run on a 1 MB assembly source file, it takes about three seconds to find the string “xxxend” (which is at the end of the file) on a 20 MHz 386 machine, with the entire file in a disk cache. If <B>BLOCK_SIZE</B> is trimmed from 16K to 4K, <I>execution time does not increase perceptibly!</I> At 2K, the program slows slightly; it’s not until the block size shrinks to 64 bytes that execution time becomes approximately double that of the 16K buffer.</P>
|
|
<P>So the first thing we’ve discovered is that, while bigger blocks do make for the best performance, the increment in performance may not be very large, and might not justify the extra memory required for those larger blocks. Our next discovery is that, even though we read the file in large chunks, most of the execution time of Listing 5.1 is nonetheless spent in executing the <B>read()</B> function.</P>
|
|
<P>When I replaced the <B>read()</B> function call in Listing 5.1 with code that simply fools the program into thinking that a 1 MB file is being read, the program ran almost instantaneously—in less than 1/2 second, even when the searched-for string wasn’t anywhere to be found. By contrast, Listing 5.1 requires three seconds to run even when searching for a single character that isn’t found anywhere in the file, the case in which a single call to <B>memchr()</B> (and thus a single <B>REPNZ SCASB</B>) can eliminate an entire block at a time.</P>
|
|
<P>All in all, the time required for DOS disk access calls is taking up at least 80 percent of execution time, and search time is less than 20 percent of overall execution time. In fact, search time is probably a good deal less than 20 percent of the total, given that the overhead of loading the program, running through the C startup code, opening the file, executing <B>printf()</B>, and exiting the program and returning to the DOS shell are also included in my timings. Given which, it should be apparent why converting to assembly language isn’t worth the trouble—the best we could do by speeding up the search is a 10 percent or so improvement, and that would require more than doubling the performance of code that already uses repeated string instructions to do most of the work.</P>
|
|
<P>Not likely.</P>
|
|
<H4 ALIGN="LEFT"><A NAME="Heading9"></A><FONT COLOR="#000077">Knowing When Assembly Is Pointless</FONT></H4>
|
|
<P>So that’s why we’re not going to go to assembly language in this example—which is not to say it would never be worth converting the search engine in Listing 5.1 to assembly.
|
|
</P>
|
|
<P>If, for example, your application will typically search buffers in which the first character of the search string occurs frequently as might be the case when searching a text buffer for a string starting with the space character an assembly implementation might be several times faster. Why? Because assembly code can switch from <B>REPNZ SCASB</B> to match the first character to <B>REPZ CMPS</B> to check the remaining characters in just a few instructions.</P>
|
|
<P>In contrast, Listing 5.1 must return from <B>memchr()</B>, set up parameters, and call <B>memcmp()</B> in order to do the same thing. Likewise, assembly can switch back to <B>REPNZ SCASB</B> after a non-match much more quickly than Listing 5.1. The switching overhead is high; when searching a file completely filled with the character z for the string “zy,” Listing 5.1 takes almost 1/2 minute, or nearly an order of magnitude longer than when searching a file filled with normal text.</P><P><BR></P>
|
|
<CENTER>
|
|
<TABLE BORDER>
|
|
<TR>
|
|
<TD><A HREF="05-03.html">Previous</A></TD>
|
|
<TD><A HREF="index.html">Table of Contents</A></TD>
|
|
<TD><A HREF="05-05.html">Next</A></TD>
|
|
</TR>
|
|
</TABLE>
|
|
</CENTER>
|
|
|
|
<hr width="90%" size="1" noshade>
|
|
<div align="center">
|
|
<font face="Verdana,sans-serif" size="1">Graphics Programming Black Book © 2001 Michael Abrash</font>
|
|
</div>
|
|
<!-- all of the reference materials (books) have the footer and subfoot reveresed -->
|
|
<!-- reference_subfoot = footer -->
|
|
<!-- reference_footer = subfoot -->
|
|
|
|
<!-- BEGIN SUB FOOTER -->
|
|
</BODY>
|
|
</HTML>
|
|
|
|
<!-- END FOOTER -->
|
|
|
|
|