Use markdown style lists

This commit is contained in:
James Gregory 2013-12-31 07:31:51 +11:00
commit 307b59584f
17 changed files with 120 additions and 120 deletions

View file

@ -14,20 +14,20 @@ pages: 007-009
We've got the following rules for creating high-performance software: We've got the following rules for creating high-performance software:
- Know where you're going (understand the objective of the software). * Know where you're going (understand the objective of the software).
- Make a big map (have an overall program design firmly in mind, so * Make a big map (have an overall program design firmly in mind, so
the various parts of the program and the data structures work well the various parts of the program and the data structures work well
together). together).
- Make lots of little maps (design an algorithm for each separate part * Make lots of little maps (design an algorithm for each separate part
of the overall design). of the overall design).
- Know the territory (understand exactly how the computer carries out * Know the territory (understand exactly how the computer carries out
each task). each task).
- Know when it matters (identify the portions of your programs where * Know when it matters (identify the portions of your programs where
performance matters, and don't waste your time optimizing the rest). performance matters, and don't waste your time optimizing the rest).
- Always consider the alternatives (don't get stuck on a single * Always consider the alternatives (don't get stuck on a single
approach; odds are there's a better way, if you're clever and approach; odds are there's a better way, if you're clever and
inventive enough). inventive enough).
- Know how to turn on the juice (optimize the code as best you know * Know how to turn on the juice (optimize the code as best you know
how when it *does* matter). how when it *does* matter).
Making rules is easy; the hard part is figuring out how to apply them in Making rules is easy; the hard part is figuring out how to apply them in

View file

@ -105,17 +105,17 @@ whizzing through the data in the buffer inside a single loop.
There are four reasons that many programmers would give for not trying There are four reasons that many programmers would give for not trying
to improve on Listing 1.4: to improve on Listing 1.4:
**1.**  The code is already fast enough. 1. The code is already fast enough.
**2.**  The code works, and some people are content with code that 2. The code works, and some people are content with code that
works, even when it's slow enough to be annoying. works, even when it's slow enough to be annoying.
**3.**  The C library is written in optimized assembly, and it's likely 3. The C library is written in optimized assembly, and it's likely
to be faster than any code that the average programmer could write to to be faster than any code that the average programmer could write to
perform essentially the same function. perform essentially the same function.
**4.**  The C library conveniently handles the buffering of file data, 4. The C library conveniently handles the buffering of file data,
and it would be a nuisance to have to implement that capability. and it would be a nuisance to have to implement that capability.
I'll ignore the first reason, both because performance is no longer an I'll ignore the first reason, both because performance is no longer an
issue if the code is fast enough and because the current application issue if the code is fast enough and because the current application

View file

@ -115,10 +115,10 @@ indeed.
The major cycle-eaters are: The major cycle-eaters are:
- The 8088's 8-bit external data bus. * The 8088's 8-bit external data bus.
- The prefetch queue. * The prefetch queue.
- Dynamic RAM refresh. * Dynamic RAM refresh.
- Wait states, notably display memory wait states and, in the AT and * Wait states, notably display memory wait states and, in the AT and
80386 computers, system memory wait states. 80386 computers, system memory wait states.
The locations of these cycle-eaters in the primordial 8088-based PC are The locations of these cycle-eaters in the primordial 8088-based PC are

View file

@ -94,15 +94,15 @@ all become clear from further reading, especially once you study, time,
and tune code that you have written yourself. What's really important is and tune code that you have written yourself. What's really important is
that you come away from this chapter understanding that on the 8088: that you come away from this chapter understanding that on the 8088:
- The 8-bit bus cycle-eater causes each access to a word-sized operand * The 8-bit bus cycle-eater causes each access to a word-sized operand
to be 4 cycles longer than an equivalent access to a byte-sized to be 4 cycles longer than an equivalent access to a byte-sized
operand. operand.
- The prefetch queue cycle-eater can cause instruction execution times * The prefetch queue cycle-eater can cause instruction execution times
to be as much as four times longer than the officially documented to be as much as four times longer than the officially documented
cycle times. cycle times.
- The DRAM refresh cycle-eater slows most PC code, with performance * The DRAM refresh cycle-eater slows most PC code, with performance
reductions ranging as high as 8.33 percent. reductions ranging as high as 8.33 percent.
- The display adapter cycle-eater typically doubles and can more than * The display adapter cycle-eater typically doubles and can more than
triple the length of the standard 4-cycle access to display memory, triple the length of the standard 4-cycle access to display memory,
with intensive display memory access suffering most. with intensive display memory access suffering most.

View file

@ -119,14 +119,14 @@ More on this shortly.
To recap, here are some things to look for when striving to convert C To recap, here are some things to look for when striving to convert C
code into optimized assembly language: code into optimized assembly language:
- Move the entire performance-critical section into a single assembly * Move the entire performance-critical section into a single assembly
language function. language function.
- Don't use calls or stack frame accesses inside the critical code, if * Don't use calls or stack frame accesses inside the critical code, if
possible, and avoid unnecessary memory accesses of any kind. possible, and avoid unnecessary memory accesses of any kind.
- Change segments as infrequently as possible. * Change segments as infrequently as possible.
- Optimize in terms of what assembly does well, *not* in terms of * Optimize in terms of what assembly does well, *not* in terms of
fine-tuning compiled C code. fine-tuning compiled C code.
- Change the rules to the benefit of assembly, if necessary; for * Change the rules to the benefit of assembly, if necessary; for
example, reorganize data structto allow efficient assembly language example, reorganize data structto allow efficient assembly language
processing. processing.

View file

@ -29,22 +29,22 @@ outrun even zero—5 cycles longer than the official execution time.)
To summarize: To summarize:
- Memory-accessing instructions don't run at their official speeds on * Memory-accessing instructions don't run at their official speeds on
non-zero-wait-state 286/386 computers. non-zero-wait-state 286/386 computers.
- The prefetch queue cycle-eater reduces performance on 286/386 * The prefetch queue cycle-eater reduces performance on 286/386
computers, particularly when non-zero-wait-state memory is used. computers, particularly when non-zero-wait-state memory is used.
- Branches often execute at less than their rated speeds on the 286 * Branches often execute at less than their rated speeds on the 286
and 386 since the prefetch queue is emptied. and 386 since the prefetch queue is emptied.
- The extent to which the prefetch queue and wait states affect * The extent to which the prefetch queue and wait states affect
performance varies from one 286/386 computer to another, making performance varies from one 286/386 computer to another, making
precise optimization impossible. precise optimization impossible.
What's to be learned from all this? Several things: What's to be learned from all this? Several things:
- Keep your instructions short. * Keep your instructions short.
- Keep it in the registers; avoid memory, since memory generally can't * Keep it in the registers; avoid memory, since memory generally can't
keep up with the processor. keep up with the processor.
- Don't jump. * Don't jump.
Of course, those are exactly the rules that apply to 8088 optimization Of course, those are exactly the rules that apply to 8088 optimization
as well. Isn't it convenient that the same general rules apply across as well. Isn't it convenient that the same general rules apply across

View file

@ -21,25 +21,25 @@ listing the 10 leading concerns of corporate buyers when it comes to
C++. Boiled down, the list looked like this, in order of descending C++. Boiled down, the list looked like this, in order of descending
importance to buyers: importance to buyers:
**1.**  Debugging 1. Debugging
**2.**  Documentation 2. Documentation
**3.**  Windows development tools 3. Windows development tools
**4.**  High-level Windows support 4. High-level Windows support
**5.**  Class library 5. Class library
**6.**  Development cycle efficiency 6. Development cycle efficiency
**7.**  Object-oriented development aids 7. Object-oriented development aids
**8.**  Programming management aids 8. Programming management aids
**9.**  Online help 9. Online help
**10.**  Windows development cycle automation 10. Windows development cycle automation
Is something missing here? You bet your maximum *gluteus* something's Is something missing here? You bet your maximum *gluteus* something's
missing—nowhere on that list is there so much as one word about how fast missing—nowhere on that list is there so much as one word about how fast

View file

@ -73,9 +73,9 @@ vertically, and four diagonally. For each succeeding generation of
cells, the game logic determines whether each cell will be on or off cells, the game logic determines whether each cell will be on or off
according to the following rules: according to the following rules:
- If a cell is on and has either two or three neighbors that are on in * If a cell is on and has either two or three neighbors that are on in
the current generation, it stays on; otherwise, the cell turns off. the current generation, it stays on; otherwise, the cell turns off.
- If a cell is off and has exactly three "on" neighbors in the current * If a cell is off and has exactly three "on" neighbors in the current
generation, it turns on; otherwise, it stays off. That's all the generation, it turns on; otherwise, it stays off. That's all the
rules there are—but they give rise to an astonishing variety of rules there are—but they give rise to an astonishing variety of
forms, including patterns that spin, march across the screen, and forms, including patterns that spin, march across the screen, and

View file

@ -17,11 +17,11 @@ Listing 17.4—and it's still in C++.
How is this possible? Here are some hints: How is this possible? Here are some hints:
- After a few dozen generations, most of the cellmap consists of cells * After a few dozen generations, most of the cellmap consists of cells
in the off state. in the off state.
- There are many possible cellmap representations other than one * There are many possible cellmap representations other than one
bit-per-pixel. bit-per-pixel.
- Cells change state relatively infrequently. * Cells change state relatively infrequently.
### Bringing In the Right Brain {#Heading8} ### Bringing In the Right Brain {#Heading8}

View file

@ -59,20 +59,20 @@ updating the cellmap was what I wanted people to concentrate on.
Here are the rules I laid down for the challenge: Here are the rules I laid down for the challenge:
- Readers could modify any code in Listing 17.5, except the main loop, * Readers could modify any code in Listing 17.5, except the main loop,
as well as change the cell map representation any way they liked. as well as change the cell map representation any way they liked.
However, the code had to produce exactly the same output as Listing However, the code had to produce exactly the same output as Listing
17.5 under all circumstances in order to be eligible to win. 17.5 under all circumstances in order to be eligible to win.
- Engine code had to be less than 400 lines long *in total,* excluding * Engine code had to be less than 400 lines long *in total,* excluding
the video-related code shown in Listing 17.2. the video-related code shown in Listing 17.2.
- Submissions had to compile/assemble with Borland C++ (in either C++ * Submissions had to compile/assemble with Borland C++ (in either C++
or C mode, as desired) and/or TASM. or C mode, as desired) and/or TASM.
- All submissions had to handle cellmaps at least 200x200 in size. * All submissions had to handle cellmaps at least 200x200 in size.
- Assembly language could of course be used to speed up any part of * Assembly language could of course be used to speed up any part of
the program. C rather than C++ was legal as well, so long as entered the program. C rather than C++ was legal as well, so long as entered
implementations produced the same results as Listing 17.5 and 17.2 implementations produced the same results as Listing 17.5 and 17.2
together and were less than 400 lines long. together and were less than 400 lines long.
- All entries would be timed on the same 33 MHz 486 with a 256K * All entries would be timed on the same 33 MHz 486 with a 256K
external cache. external cache.
That was the challenge I put to the readers. Little did I realize the That was the challenge I put to the readers. Little did I realize the

View file

@ -21,17 +21,17 @@ to handle points that are exactly on the boundary, and points that lie
at vertices, so that those points are drawn once and only once. To deal at vertices, so that those points are drawn once and only once. To deal
with that, we're going to adopt the following rules: with that, we're going to adopt the following rules:
- Points located exactly on nonhorizontal edges are drawn only if the * Points located exactly on nonhorizontal edges are drawn only if the
interior of the polygon is directly to the right (left edges are interior of the polygon is directly to the right (left edges are
drawn, right edges aren't). drawn, right edges aren't).
![](images/38-03.jpg)\ ![](images/38-03.jpg)\
**Figure 38.3**  *The adjacent polygons problem.* **Figure 38.3**  *The adjacent polygons problem.*
- Points located exactly on horizontal edges are drawn only if the * Points located exactly on horizontal edges are drawn only if the
interior of the polygon is directly below them (horizontal top edges interior of the polygon is directly below them (horizontal top edges
are drawn, horizontal bottom edges aren't). are drawn, horizontal bottom edges aren't).
- A vertex is drawn only if all lines ending at that point meet the * A vertex is drawn only if all lines ending at that point meet the
above conditions (no right or bottom edges end at that point). above conditions (no right or bottom edges end at that point).
All edges of a polygon except those that are flat tops or flat bottoms All edges of a polygon except those that are flat tops or flat bottoms

View file

@ -105,11 +105,11 @@ polygon-filling code that's fast enough to be truly usable.
Our original polygon filling code involved three major tasks, each Our original polygon filling code involved three major tasks, each
performed by a separate function: performed by a separate function:
- Tracing each polygon edge to generate a coordinate list (performed * Tracing each polygon edge to generate a coordinate list (performed
by the function **ScanEdge);** by the function **ScanEdge);**
- Drawing the scanned-out horizontal lines that constitute the filled * Drawing the scanned-out horizontal lines that constitute the filled
polygon (**DrawHorizontalLineList** ); and polygon (**DrawHorizontalLineList** ); and
- Characterizing the polygon and coordinating the tracing and drawing * Characterizing the polygon and coordinating the tracing and drawing
(**FillConvexPolygon** ). (**FillConvexPolygon** ).
The amount of time that the previous chapter's sample program spent in The amount of time that the previous chapter's sample program spent in

View file

@ -41,25 +41,25 @@ Y coordinates, error terms and error term adjustments, lengths, and
directions of X movement for each edge. Once the GET is built, we'll do directions of X movement for each edge. Once the GET is built, we'll do
the following: the following:
**1.**  Set the current Y coordinate to the Y coordinate of the first 1. Set the current Y coordinate to the Y coordinate of the first
edge in the GET. edge in the GET.
**2.**  Move all edges with the current Y coordinate from the GET to the 2. Move all edges with the current Y coordinate from the GET to the
AET, removing them from the GET and maintaining the X-sorted order of AET, removing them from the GET and maintaining the X-sorted order of
the AET. the AET.
**3.**  Draw all odd-to-even spans in the AET at the current Y 3. Draw all odd-to-even spans in the AET at the current Y
coordinate. coordinate.
**4.**  Count down the lengths of all edges in the AET, removing any 4. Count down the lengths of all edges in the AET, removing any
edges that are done, and advancing the X coordinates of all remaining edges that are done, and advancing the X coordinates of all remaining
edges in the AET by one scan line. edges in the AET by one scan line.
**5.**  Sort the AET in order of ascending X coordinate. 5. Sort the AET in order of ascending X coordinate.
**6.**  Advance the current Y coordinate by one scan line. 6. Advance the current Y coordinate by one scan line.
**7.**  If either the AET or GET isn't empty, go to step 2. 7. If either the AET or GET isn't empty, go to step 2.
![](images/40-03.jpg)\ ![](images/40-03.jpg)\
**Figure 40.3**  *The global and active edge tables as linked lists.* **Figure 40.3**  *The global and active edge tables as linked lists.*

View file

@ -40,22 +40,22 @@ Serge didn't care to do all that bookkeeping in his animation
applications, so he came up with the following approach, which I've applications, so he came up with the following approach, which I've
reworded, amplified, and slightly modified in the summary here: reworded, amplified, and slightly modified in the summary here:
**1.**  Set the start address to display page 0. 1. Set the start address to display page 0.
**2.**  Draw to page 1. 2. Draw to page 1.
**3.**  Set the start address to display page 1 (the newly drawn page), 3. Set the start address to display page 1 (the newly drawn page),
then wait for the leading edge of vertical sync, at which point the page then wait for the leading edge of vertical sync, at which point the page
has flipped and it's safe to modify page 0. has flipped and it's safe to modify page 0.
**4.**  Copy, via the latches, from page 1 to page 0 the areas that 4. Copy, via the latches, from page 1 to page 0 the areas that
changed from the previous screen to the current one. changed from the previous screen to the current one.
**5.**  Set the start address to display page 0, which is now identical 5. Set the start address to display page 0, which is now identical
to page 1, then wait for the leading edge of vertical sync, at which to page 1, then wait for the leading edge of vertical sync, at which
point the page has flipped and it's safe to modify page 1. point the page has flipped and it's safe to modify page 1.
**6.**  Go to step 2. 6. Go to step 2.
The great benefit of Serge's approach is that the only page that is ever The great benefit of Serge's approach is that the only page that is ever
actually drawn to (as opposed to being block-copied to) is page 1. Only actually drawn to (as opposed to being block-copied to) is page 1. Only
@ -74,14 +74,14 @@ less-experienced animation programmers.
An interesting variation on Serge's approach doesn't page flip nor wait An interesting variation on Serge's approach doesn't page flip nor wait
for vertical sync: for vertical sync:
**1.**  Set the start address to display page 0. 1. Set the start address to display page 0.
**2.**  Draw to page 1. 2. Draw to page 1.
**3.**  Copy, via the latches, the areas that changed from the last 3. Copy, via the latches, the areas that changed from the last
screen to the current one from page 1 to page 0. screen to the current one from page 1 to page 0.
**4.**  Go to step 2. 4. Go to step 2.
This approach totally eliminates page flipping, which can consume a This approach totally eliminates page flipping, which can consume a
great deal of time. The downside is that images may shear for one frame great deal of time. The downside is that images may shear for one frame

View file

@ -79,12 +79,12 @@ code builds on the code from no fewer than five previous chapters. The
code that's required in order to link this chapter's animation demo code that's required in order to link this chapter's animation demo
program is the following: program is the following:
- Listing 50.1 from Chapter 50 (draw clipped line list); * Listing 50.1 from Chapter 50 (draw clipped line list);
- Listings 47.1 and 47.6 from Chapter 47 (Mode X mode set, rectangle * Listings 47.1 and 47.6 from Chapter 47 (Mode X mode set, rectangle
fill); fill);
- Listing 49.6 from Chapter 49; * Listing 49.6 from Chapter 49;
- Listing 39.4 from Chapter 39 (polygon edge scan); and * Listing 39.4 from Chapter 39 (polygon edge scan); and
- The **FillConvexPolygon( )** function from Listing 38.1 from Chapter * The **FillConvexPolygon( )** function from Listing 38.1 from Chapter
38. Note that the **struct** keywords in **FillConvexPolygon( )** 38. Note that the **struct** keywords in **FillConvexPolygon( )**
must be removed to reflect the switch to typedefs in the animation must be removed to reflect the switch to typedefs in the animation
header file. header file.

View file

@ -40,17 +40,17 @@ measurably faster than Listing 59.2, but not even close to being
The moral of this story (apart from it being a good idea to enable The moral of this story (apart from it being a good idea to enable
compiler optimization) is: compiler optimization) is:
**1.**  Understand what you're doing, through and through. 1. Understand what you're doing, through and through.
**2.**  Build a complete and consistent model in your head. 2. Build a complete and consistent model in your head.
**3.**  Design from the principles that the model provides. 3. Design from the principles that the model provides.
**4.**  Implement the design. 4. Implement the design.
**5.**  Measure to learn what you've wrought. 5. Measure to learn what you've wrought.
**6.**  Go back to step 1 and apply what you've just learned. 6. Go back to step 1 and apply what you've just learned.
With each iteration you'll dig deeper, learn more, and improve your With each iteration you'll dig deeper, learn more, and improve your
ability to know where and how to focus your design and programming ability to know where and how to focus your design and programming

View file

@ -16,12 +16,12 @@ Conceptually rendering from a BSP tree really is that simple, but the
implementation is a bit more complicated. The full rendering pipeline, implementation is a bit more complicated. The full rendering pipeline,
as coordinated by **UpdateWorld()**, is this: as coordinated by **UpdateWorld()**, is this:
- Update the current location. * Update the current location.
- Transform all wall endpoints into viewspace (the world as seen from * Transform all wall endpoints into viewspace (the world as seen from
the current location with the current viewing angle). the current location with the current viewing angle).
- Clip all walls to the view pyramid. * Clip all walls to the view pyramid.
- Project wall vertices to screen coordinates. * Project wall vertices to screen coordinates.
- Walk the walls back to front, and for each wall that lies at least * Walk the walls back to front, and for each wall that lies at least
partially in the view pyramid, perform backface culling (skip walls partially in the view pyramid, perform backface culling (skip walls
facing away from the viewer), and draw the wall if it's not culled. facing away from the viewer), and draw the wall if it's not culled.