Chapter 1
read() VS fopen(), getc()
DOS implementation difference
read() interrupts, slowest instructions of the x86 family CPUs
what goes on when you insert a seemingly-innocuous function
time-critical portion of your code
pre-mature optimization: until design is refined
hallmark of mediocre programmers: the code works. TODO: know when optimization matters
C lib functions are not always written in assembly, nor are they particularly well-optimized. (portability)
handling data in restartable blocks
http://www.delorie.com/djgpp/doc/libc/libc_600.html
OS disk access time (DOS), disk cache
Chapter 2
optimization is by no means always a matter of "dropping into assembly"
a nibble = 4 bits
Bit Rotation: A rotation (or circular shift) is an operation similar to shift except that the bits that fall off at one end are put back to the other end.
decidedly quirky nature of the x86 family
assembly is simply a human-orientated representation of machine language
assembly language optimization
- self-reliance, lowest practical level, OS, BIOS, hardware
- knowledge, hard to gain advanced knowledge, x86 complex, irregular instructions
- the flexible mind
- write non-time critical portions in a high-level language
- user-facing: performance must be your paramount
- good assembly code is better than good compiled code; bad... is worse than..
Chapter 3: assume nothing
optimize: to make as perfect, effective, or functional as possible
bushel
cardinal sin: assume information available is correct and complete
instruction fetch time
save a few cycles, juggled registers, blurry-fast register-to-register shifts and adds
Chapter 4:
cycle-eaters, gremlins
esoteric things that lie on the shadowy edge of hardware-land
instruction prefetching, dynamic RAM refresh, wait states
cycle-eaters, outside of execution, Bus access (IO, memory R/W)
(only on 486 and Pentium CPUs will you find cycle-eaters inside the chip)
8088 perform like a 8-bit processor
8088 is internally a full 16-bit processor, half-sized bus
16-bit instruction set
external bus 8 bit
limited width of external data bus that constricts data flow into and out of 8088
each bus access takes 4 clock cycles, 0.838 microseconds in the 4.77 MHz PC, transfer 1 byte
string instructions can suffer greatly
doesn't mean you should use 2 byte-sized memory access in preference to 1 word-sized access
actually slower (instruction fetching, address calculation, etc.)
registers are inside, so should use 16-bit operations within
prefetch queue (ugliest)
execution unit burns up instruction bytes much faster than the Bus Interface Unit
know the bottle neck : EU or prefetch instruction
time measured in a certain context
execution times are only meaningful in context
keep your instructions short
less time is required to fetch instructions that are 1 or 2 bytes long..
rule of thumb,
dynamic RAM refresh, wait states - lowest level at which hardware of the PC affects code performance
external to CPU
you code cannot directly control
adapters (video and memory cards) can insert wait states on any bus access, won't complete unless the access is stretched out
Dynamic RAM (DRAM) refresh is sort of an act of God- invisibly and inexorably steals a certain fraction of all available memory
accessed regularly, so the chip's stored data is kept refreshed and valid... still indefinitely
refreshed once every 4 milliseconds to ensure the integrity of data
Bus gives control to 8237 DMA controller
DRAM can slow code performance 0-5.56% (in reality more, 8.33%)
DRAM refresh only affects code performance when a DRAM refresh forces the Execution Unit of the 8088 to wait for a memory access.
Wait states
lowest level of code performance
the display adapter cycle-eater
master #1 circuitry that drives the display screen
master #2 cpu
only one can read or write display memory at any one time
486s and pentium, write-caching write mem faster than read
Chapter 5
strstr() must spend time either checking for the end of the string being searched or determining the length of that string- wasted effort given that we already know exactly how long our search buffer is
Why you shouldn't think of C/C++ lib functions as black boxes; understand what they do and try to figure out how they do it, and relate taht to their performance in the context you are interested in.
never assumes
memcmp()
http://www.cplusplus.com/reference/cstring/memcmp/
memchr()
http://www.cplusplus.com/reference/cstring/memchr/
DOS disk access calls is taking up 80% of execution time
knowing when assembly is pointless
always look where execution is going
chapter 23 VGA
chapter 59 The idea of BSP trees
chapter 64 Quake's visible-surface determination
transcending limits
culling discarding non-visible polygons
Quake levels stored as BSP
https://en.wikipedia.org/wiki/Binary_space_partitioning