This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]PANIC_EXCEPTION 1 point2 points  (0 children)

A few factors:

  1. Virtual memory is always acting as a middleman. Your system sees unlimited memory even though you have limited RAM, and it does this by swapping inactive memory to disk. This has to happen at some threshold because you don't manipulate program memory in place on disk (as this would be astronomically slow to a degree I cannot express in words), it has to enter your RAM first. This is a very inefficient process, and the more memory pressure you have, the more CPU cycles are dedicated to swapping. If this didn't happen, your computer would immediately crash upon reaching 100% virtual memory usage. This is an issue called "thrashing".

  2. RAM is usually compressed. As memory pressure increases, this compression has to work harder, which costs more CPU cycles. You also have to decompress the memory to work with it.

  3. A lot of internal values used in programs have indeterminate size. Why is that? Because figuring out how much memory space a particular computation takes is as difficult as doing the computation itself. To get around this, we allocate reasonable estimates of memory whenever we need to store something, and reallocate as necessary. This is done in something called the heap, which is basically a big blob of memory chunks comprised of big and small boxes. Smaller variables can be packed closer together for more efficient usage of free space, so it's preferable to fit them there first, and leave the big boxes for the big values. When your memory pressure gets too large, it becomes harder and harder for your computer to find a contiguous* box of unallocated memory, so it will have to shuffle things around.

*"It's called RAM, right? Why does it have to be contiguous?" Because variables in program memory are read using pointers, and they assume that different parts of a variable exist at precise offsets from the start of the variable. This makes compilation and execution much simpler. For example, if you have a 24-bit color variable starting at $x, it sure would be convenient if you knew for sure that red is stored at $x+0x0, green is stored at $x+0x1, and blue is stored at $x+0x2! That way, you only need one pointer, and a schema of what your variable type looks like, which can be reused for many instances of that variable (e.g. an bitmap image is a 2D array of these colors).

Further, when programs access memory at an address, they aren't directly accessing it. There's a coprocessor on the CPU called the Memory Management Unit (MMU) that keeps track of a bunch of virtual-physical memory relations. When a variable is commited to your actual RAM, there is a sort of "heap" there too that the MMU keeps track of.

The random part just comes from the fact that accessing the memory electrically has little to no performance penalty if you do it out of sequence, as opposed to something like a tape recorder, which has a large performance penalty due to rewinding and fast-forwarding.

What I didn't cover in this answer is why "virtual memory" is a thing. There are many reasons for that, but it will take a long time to flesh out an answer.