# Know Your Limits

### From WikiContent

m |
Current revision (19:10, 14 June 2012) (edit) (undo)m (Fix dead link.) |
||

(14 intermediate revisions not shown.) | |||

Line 1: | Line 1: | ||

- | + | [[Image:Clearly.jpeg|thumb|right]] | |

- | + | ''"Man's got to know his limitations." — [http://youtu.be/CG2cux_6Rcw Dirty Harry]'' | |

- | Your resources are limited. You only have so much time and money to do your work, including the time and money needed to keep your knowledge, skills, and tools up-to-date. You can only work so hard, so fast, so smart, and so long. Your tools are only so powerful. Your target machines are only so powerful. So you have to | + | Your resources are limited. You only have so much time and money to do your work, including the time and money needed to keep your knowledge, skills, and tools up-to-date. You can only work so hard, so fast, so smart, and so long. Your tools are only so powerful. Your target machines are only so powerful. So you have to respect the limits of your resources. |

- | How to respect those limits? Know yourself, know your budgets, and know your stuff. Especially, know the space and time complexity of your data structures and algorithms, and the architecture and performance characteristics of your systems. | + | How to respect those limits? Know yourself, know your people, know your budgets, and know your stuff. Especially, as a software engineer, know the space and time complexity of your data structures and algorithms, and the architecture and performance characteristics of your systems. Your job is to create an optimal marriage of software and systems. |

- | Space and time complexity are given as the function ''O(f(n))'' which for ''n'' equal the size of the input is the asymptotic space or time required as ''n'' grows to infinity. Important complexity classes include ''f= | + | Space and time complexity are given as the function ''O(f(n))'' which for ''n'' equal the size of the input is the asymptotic space or time required as ''n'' grows to infinity. Important complexity classes include ''f(n)=log(n)'', ''f(n)=n'', ''f(n)=n×log(n)'', ''f(n)=n<sup>e</sup>'', and ''f(n)=e<sup>n</sup>''. Clearly, as ''n'' gets bigger ''O(log(n))'' is ever so much smaller than ''O(e<sup>n</sup>)''. As Sean Parent puts it, for large enough ''n'' all complexity classes amount to near-infinite, near-linear, or near-constant. |

- | Modern computer systems are organized as hierarchies of physical and virtual machines, including language runtimes, operating systems, CPUs, cache memory, random-access memory, disk drives, and networks. Typical limits include: | + | Complexity analysis is in terms of an abstract machine, but software runs on real machines. Modern computer systems are organized as hierarchies of physical and virtual machines, including language runtimes, operating systems, CPUs, cache memory, random-access memory, disk drives, and networks. Typical limits on random access time and storage capacity include: |

- | {| | + | {|align="left" |

+ | !align="left"| | ||

+ | | style="color:#e76700;" | access time | ||

+ | |align="right" style="color:#e76700;" | capacity | ||

|- | |- | ||

!align="left"|register | !align="left"|register | ||

|align="right"| < 1 ns | |align="right"| < 1 ns | ||

|align="right"|64 b | |align="right"|64 b | ||

+ | | | ||

|- | |- | ||

!align="left"|cache line | !align="left"|cache line | ||

Line 22: | Line 26: | ||

|- | |- | ||

!align="right"|L1 cache | !align="right"|L1 cache | ||

- | |align="right"| | + | |align="right"| 1 ns |

|align="right"|64 KB | |align="right"|64 KB | ||

|- | |- | ||

!align="right"|L2 cache | !align="right"|L2 cache | ||

- | |align="right"| | + | |align="right"| 4 ns |

|align="right"|8 MB | |align="right"|8 MB | ||

|- | |- | ||

!align="left"|RAM | !align="left"|RAM | ||

- | |align="right"| | + | |align="right"|20 ns |

|align="right"|32 GB | |align="right"|32 GB | ||

|- | |- | ||

!align="left"|disk | !align="left"|disk | ||

- | |align="right"| | + | |align="right"|10 ms |

|align="right"|10 TB | |align="right"|10 TB | ||

|- | |- | ||

!align="left"|LAN | !align="left"|LAN | ||

- | |align="right"| | + | |align="right"|20 ms |

- | |align="right"|>1 PB | + | |align="right"|> 1 PB |

|- | |- | ||

!align="left"|Internet | !align="left"|Internet | ||

- | |align="right"| | + | |align="right"|100 ms |

- | |align="right"|>1 ZB | + | |align="right"|> 1 ZB |

|- | |- | ||

| | | | ||

- | |style="color:#e76700;" | Random access time | ||

- | |align="right" style="color:#e76700;" | Storage capacity | ||

|} | |} | ||

- | Note that capacity and speed vary by several orders of magnitude. Caching and lookahead are used heavily at every level of our systems to hide this variation, but they only work when access is | + | Note that capacity and speed vary by several orders of magnitude. Caching and lookahead are used heavily at every level of our systems to hide this variation, but they only work when access is predictable. When cache misses are frequent the system will be thrashing. For example, to randomly inspect every byte on a hard drive could take 32 years. Even to randomly inspect every byte in RAM could take 11 minutes. You can learn the limits of your systems from the manufacturers' literature, and can monitor the performance of your systems with tools like ''top'', ''oprofile'', ''gprof'', ''ping'', and ''traceroute''. |

- | {| align="right" | + | {|align="right" |

- | |+ align="bottom" style="color:#e76700;" | Search time (ns) | + | |+ align="bottom" style="color:#e76700;" | Search time (ns) |

|- | |- | ||

!align="right"| n | !align="right"| n | ||

Line 81: | Line 83: | ||

|} | |} | ||

- | Algorithms vary in how effectively they use caches. For instance, linear search makes good use of lookahead, but requires ''O(n)'' comparisons. Binary search of a sorted array requires only ''O(log(n))'' comparisons, but tends to be cache-hostile | + | Algorithms and data structures vary in how effectively they use caches. For instance, linear search makes good use of lookahead, but requires ''O(n)'' comparisons. Binary search of a sorted array requires only ''O(log(n))'' comparisons, but tends to be cache-hostile, whereas searching a B-tree or van Emde Boas tree is ''O(log(n))'' and cache-friendly. Study up on "cache-aware" and "cache-oblivious" to know your stuff. |

- | ''"You pays your money and you makes your choice." | + | ''"You pays your money and you makes your choice." — Punch'' |

## Current revision

*"Man's got to know his limitations." — Dirty Harry*

Your resources are limited. You only have so much time and money to do your work, including the time and money needed to keep your knowledge, skills, and tools up-to-date. You can only work so hard, so fast, so smart, and so long. Your tools are only so powerful. Your target machines are only so powerful. So you have to respect the limits of your resources.

How to respect those limits? Know yourself, know your people, know your budgets, and know your stuff. Especially, as a software engineer, know the space and time complexity of your data structures and algorithms, and the architecture and performance characteristics of your systems. Your job is to create an optimal marriage of software and systems.

Space and time complexity are given as the function *O(f(n))* which for *n* equal the size of the input is the asymptotic space or time required as *n* grows to infinity. Important complexity classes include *f(n)=log(n)*, *f(n)=n*, *f(n)=n×log(n)*, *f(n)=n ^{e}*, and

*f(n)=e*. Clearly, as

^{n}*n*gets bigger

*O(log(n))*is ever so much smaller than

*O(e*. As Sean Parent puts it, for large enough

^{n})*n*all complexity classes amount to near-infinite, near-linear, or near-constant.

Complexity analysis is in terms of an abstract machine, but software runs on real machines. Modern computer systems are organized as hierarchies of physical and virtual machines, including language runtimes, operating systems, CPUs, cache memory, random-access memory, disk drives, and networks. Typical limits on random access time and storage capacity include:

access time | capacity | ||

register | < 1 ns | 64 b | |

cache line | 64 B | ||

L1 cache | 1 ns | 64 KB | |

L2 cache | 4 ns | 8 MB | |

RAM | 20 ns | 32 GB | |

disk | 10 ms | 10 TB | |

LAN | 20 ms | > 1 PB | |

Internet | 100 ms | > 1 ZB | |

Note that capacity and speed vary by several orders of magnitude. Caching and lookahead are used heavily at every level of our systems to hide this variation, but they only work when access is predictable. When cache misses are frequent the system will be thrashing. For example, to randomly inspect every byte on a hard drive could take 32 years. Even to randomly inspect every byte in RAM could take 11 minutes. You can learn the limits of your systems from the manufacturers' literature, and can monitor the performance of your systems with tools like *top*, *oprofile*, *gprof*, *ping*, and *traceroute*.

n | vEB | binary | linear |
---|---|---|---|

8 | 40 | 90 | 50 |

64 | 70 | 150 | 180 |

512 | 100 | 230 | 1200 |

4096 | 160 | 320 | 17000 |

Algorithms and data structures vary in how effectively they use caches. For instance, linear search makes good use of lookahead, but requires *O(n)* comparisons. Binary search of a sorted array requires only *O(log(n))* comparisons, but tends to be cache-hostile, whereas searching a B-tree or van Emde Boas tree is *O(log(n))* and cache-friendly. Study up on "cache-aware" and "cache-oblivious" to know your stuff.

*"You pays your money and you makes your choice." — Punch*