On computer memory

From Helpful
(Redirected from Swapping)
Jump to: navigation, search

CPU cache notes

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

CPU caches put a little fast-but-costly memory between CPU (fast) and main RAM (slowish).

When reads from main memory are areas that happen to be mirrored in the cache, that read can be served much faster. This idea has been worth it since CPUs ran at a dozen MHz or so.

These caches are entirely transparent, in that you should not have to care about how it does its thing.

But you can design for caches to work better, so as a programmer you may want a rough idea.

And only rough, as optimizing for specific hardware is pointless a few years later, yet designing for caches in general can help speed for longer.

As can avoiding caches getting flushed more then necessary, as can avoiding cache contention - so it helps to know what that is and why it happens. And see when.

On virtual memory

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


Overcommitting RAM with disk: Swapping / paging; trashing

Page faults

See also


This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Practical notes


"How large should my page/swap space be?"

On memory scarcity


oom_kill is linux kernel code that starts killing processes when there is enough memory scarcity that memory allocations cannot happen within reasonable time - as this is good indication that it's gotten to the point that we are trashing.

Killing sounds like a poor solution, but consider that an OS can deal with completely running out of memory in roughly three ways:

  • deny all memory allocations until the scarcity stops. This isn't very useful because
it will affect every program until scarcity stops
if the cause is one flaky program - and it usually is - then the scarcity may not stop
programs that do not actually check every memory allocation will probably crash.
programs that do such checks well may have no option but to stop completely (maybe pause)
So in the best case, random applications will stop doing useful things, in the probably case they will crash, and in the worst case your system will crash.
  • delay memory allocations until they can be satisfied
this pauses all programs until scarcity stops
again, there is often no reason for this scarcity to stop
so typically means a large-scale system freeze (indistinguishable from a system crash in the practical ways of "it doesn't do anything")
  • killing the misbehaving application to end the memory scarcity.
effectively makes the assumption that the system has had enough memory for normal operation up to now, and that there is probably one process that is misbehaving or just misconfigured (e.g. pre-allocates more memory than you have)
this is assuming there is a single misbehaving (not always true, e.g. two programs allocating most of RAM would be fine individually, and needs an admin to configure them better)
...usually the process with the most allocated memory, though oom_kill tries to be smarter than that.
this could misfire on badly configured systems (e.g. multiple daemons all configured to use all RAM, or having no swap, leaving nothing to catch incidental variation)

Keep in mind that

  • You may wish to disable oom_kill when you are developing -- or at least equate an oom_kill in your logs as a fatal bug in the software that caused it.
  • oom_kill isn't really a feature you ever want to rely on.
It is meant to deal with pathological cases of misbehaviour - but even then may

pick some random daemon rather than the real offender, because in some cases the real offender is hard to define

generally, if you feel the wish to overcommit, or rely on the OOM, don't. Tweak likely offenders, tweak your system.
also, you can isolate likely offenders via cgroups now.
  • oom_kill does not always save you.
It seems that if it's trashing heavily already, it may not be able to act fast enough.
(and possibly go overboard later)
  • If you don't have oom_kill, you may still be able to get reboot instead, by setting the following sysctls:

See also


On memory fragmentation

Fragmentation in general

Slab allocation

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

The slab allocator does caches of fixed-size objects.

Slab allocation is often used in kernel modules/drivers that need to allocate uniform-sized and potentially short-lived structures - think task structures, filesystem internals, network buffers.

Fixed size, and often separated for each specific type, makes it easier to write an allocator that guarantees allocation within very small timeframe (by avoiding "hey let me look at RAM and all the allocations currently in there").

There may also be arbitrary allocation of fixed sizes like 4K, 8K, 32K, 64K, 128K, etc, used for things that have known bounds but not precise sizes.


Each such cache is easy to handle
avoids fragmentation because all holes are of the same size,
that the otherwise-typical buddy system still has
making slab allocation/free simpler, and thereby a little faster
easier to fit them to hardware caches better


It still deals with the page allocator under the cover, so deallocation patterns can still mean that pages for the same cache become sparsely filled - which wastes space.


  • SLOB: K&R allocator (1991-1999), aims to allocate as compactly as possible. But fragments faster than various others.
  • SLAB: Solaris type allocator (1999-2008), as cache-friendly as possible.
  • SLUB: Unqueued allocator (2008-today): Execution-time friendly, not always as cache friendly, does defragmentation (mostly just of pages with few objects)

For some indication of what's happening, look at

See also:

There are some similar higher-level allocators "I will handle things of the same type" allocation, from some custom allocators in C, to object allocators in certain languages, arguably even just the implementation of certain data structures.

Memory mapped IO and files

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Note that memory mapped IO is a hardware-level construction, while memory mapped files are a software construction (...because files are).

Memory mapped files

Memory mapping of files is a technique (OS feature, system call) that pretends a file is accessible at some address in memory. At first, no file data will have been fetched at all. When the process accesses those memory locations, the OS will scramble for the actual contents from disk.

(and since this is handled in the OS's kernel, this interacts well with its filesystem cache).

For caching

Because of that interaction with the page cache, the data is and stays cached as long as there is RAM for it.

This can also save memory - without memory mapping, you'll often have allocate memory for it on the process's heap, while the OS also keeps it in filesystem cache for a bit.

With mmapping, you avoid that duplication, also meaning more data can be cached in the OS caches.

The fact that the OS can flush most or all of this data can be seen as a limitation or a feature - it's not always predictable, but it does mean you can deal with large data sets without having to think about very large allocations, and how those aren't nice to other apps.

shared memory via memory mapped files

Most kernel implementations allow multiple processes to mmap the same file -- which effectively shares memory, and probably one of the simplest in a protected mode system. (Some methods of Inter-Process communication work via mmapping)

You still need some way of not clobbering each other's work, of course.

The implementation, limitations, and method of use varies per OS / kernel.

Often relies on demand paging to work.

Memory mapped IO

Map devices into memory space (statically or dynamically), meaning that memory accesses to those areas are actually backed by IO accesses (...that you can typically also do directly).

This mapping is made and resolved at hardware-level thing, and only works for DMA-capable devices (which is many).

It seems to often be done to have a simple generic interface (verify) - it means drivers and software can avoid many hardware-specific details.

See also:


Memory limits on 32-bit and 64-bit machines

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


  • If you want to use significantly more than 4GB of RAM, you want a 64-bit OS.
  • ...and since that is now typical, most of the details below are irrelevant

TODO: the distinction between (effects from) physical and virtual memory addressing should be made clearer.

Overall factoids

OS-level and hardware-level details:

From the I want my processes to map as much as possible angle:

  • the amount of memory a single process could hope to map is limited by its pointer size, so ~4GB on 32-bit OS, 64-bit (lots) on a 64-bit OS.
Technically this could be entirely about the OS, but in reality this tied intimately to what the hardware natively does, because anything else would be slooow.
  • Most OS kernels have a split (for their own ease) that means the practical limit of single 32-bit userspace processes is lower - 3GB, 2GB sometimes even 1GB
this is mostly some pragmatic implementation detail from back when 32 megabytes was a lot of memory, and leftover ever since

  • Each process is mapped to memory separately, so in theory you can host multiple 32-bit processes to together use more than 4GB
...even on 32-bit OSes: you can for example compile the 32-bit linux kernel to use up to 64GB this way
a 32-bit OS can only do this through PAE, which has to be supported and enabled in motherboard, and supported and enabled in the OS. (Note: Disabled in windows XP SP2; see details below)
Note: both 32-bit and 64-bit PAE-supporting motherboards may have somewhat strange limitations, e.g. the amount of memory they will actually allow/support (mostly a problem in old, early PAE motherboards)
and PAE was problematic anyway - it's a nasty hack in nature, and e.g. drivers had to support it. In the end it was mostly seen in servers, where the details were easier to oversee.
  • device memory maps would take mappable memory away from within each process, which for 32-bit OSes would often mean that you couldn't use all of that installed 4GB

On 32-bit systems:

Process-level details:

  • No single 32-bit process can ever map more than 4GB as addresses are 32-bit byte-addressing things.
  • A process's address space has reserved parts, to map things like shared libraries, which means a single app can actually allocate less (often by at most a few hundred MBs) than what it can map(verify). Usually no more than ~3GB can be allocated, sometimes less.

On 64-bit systems:

  • none of the potentially annoying limitations that 32-bit systems have apply
(assuming you are using a 64-bit OS, and not a 32-bit OS on a 64-bit system).
  • The architecture lets you map 64-bit addresses
...in theory, anyway. The instruction set is set up for 64 bit everything, but the current x86-64 CPU implementation's address lines are 48-bit (for 256TiB), mainly because we can increase that later without breaking compatibility, and right now it saves copper and silicon 99% of computers won't use
...because in practice it's still more than you can currently physically put in most systems. (there are a few supercomputers for which this matters, but arguably even there it's not so important because horizontal scaling is generally more useful than vertical scaling. But there are also a few architectures designed with a larger-than-64-bit addressing space)

On both 32-bit (PAE) and 64-bit systems:

  • Your motherboard may have assumptions/limitations that impose some lower limits than the theoretical one.
  • Some OSes may artificially impose limits (particularly the more basic versions of Vista seem to do this(verify))

Windows-specific limitations:

  • 32-bit Windows XP (since SP2) gives you no PAE memory benefits. You may still be using the PAE version of the kernel if you have DEP enabled (no-execute page protection) since that requires PAE to work(verify), but PAE's memory upsides are disabled (to avoid problems with certain buggy PAE-unaware drivers, possibly for other reasons)
  • 64-bit Windows XP: ?
  • /3GB switch moves the user/kernel split, but a single process to map more than 2GB must be 3GB aware
  • Vista: different versions have memory limits that seem to be purely artificial (8GB, 16GB, 32GB, etc.) (almost certainly out of market segregation)

Longer story / more background information

A 32-bit machine implies memory addresses are 32-bit, as is the memory address bus to go along. It's more complex, but the net effect is still that you can ask for 2^32 bytes of memory at byte resolution, so technically allows you to access up to 4GB.

The 'but' you hear coming is that 4GB of address space doesn't mean 4GB of memory use.

The device hole (32-bit setup)

One of the reasons the limit actually lies lower is devices. The top of the 4GB memory space (usually directly under the 4GB position) is used to map devices.

If you have close to 4GB of memory, this means part of your memory is now effectively missing - it is not addressible by the CPU. The size of this hole depends on chipset, BIOS configuration, the actual devices, and more(verify).

The BIOS settles the memory address map at boot time(verify), and you can inspect the effective map (Device Manager in windows, /proc/iomem in linux) in case you want to know whether it's hardware actively using the space (The hungriest devices tend to be video cards - at the time having two 768MB nVidia 8800s in SLI was one of the worst cases) or whether your motherboard just doesn't support more than, say, 3GB at all. Both these things can be the reason some people report seeing as little as 2.5GB out of 4GB you plugged in.

This problem goes away once you run a 64-bit OS on a 64-bit processor -- though there were some earlier motherboards that still had old-style addressing leftovers and hence some issues.

Note that the subset of these issues caused purely by limited address space on 32-bit systems could also be alleviated, using PAE:


It is very typical to use virtual memory systems. While the prime upside is probably the isolation of memory, the fact that a memory map is kept for each process also means that on 32-bit, each application has its own 4GB memory map without interfering with anything else (virtual mapping practice allowing).

Which means that while each process could use 4GB at the very best, if the OS could see more memory, it might map distinct 4GBs to each process so that collectively you can use more than 4GB (or just your full 4GB even with device holes).

Physical Address Extension is a memory mapping extension (not a hack, as some people think) that does roughly that. PAE needs specific OS support, but doesn't need to break the 32-bit model as applications see it.

It allowed mapping 32-bit virtual memory into the 36 bit hardware address space, which allows for 64GB (though most motherboards had a lower limit)

PAE implies some extra work on each memory operation, but because there's hardware support it only kicked a few percent off memory access speed.

All newish linux and windows version support PAE, at least technically. However:

  • The CPU isn't the only thing that accesses memory. Although many descriptions I've read seem kludgey, I easily believe that any device driver that does DMA and is not aware of PAE may break things -- such drivers are broken in that they are not PAE-aware - they do not know the 64-bit pointers that are used internally used should be limited to 36-bit use.
  • PAE was disabled in WinXP's SP2 to increase stability related to such issues, while server windowses are less likely to have problems since they use tend to use more standard hardware and thereby drivers.

Kernel/user split

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

The kernel/user split, specific to 32-bit OSes, refers to an OS-enforced formalism splitting the mappable process space between kernel and each process.

It looks like windows by default gives 2GB to both, while (modern) linuces apparently split into 1GB kernel, 3GB application by default (which is apparently rather tight on AGP and a few other things).

(Note: '3GB for apps' means that any single process is limited to map 3GB. Multiple processes may sum up to whatever space you have free.)

In practice you may want to shift the split, particularly in Windows since almost everything that would want >2GB memory runs in user space - mostly databases. The exception is Terminal Services (Remote Desktop), that seems to be kernel space.

It seems that:

  • linuxes tend to allow 1/3, 2/2 and 3/1,
  • BSDs allow the split to be set to whatever you want(verify).
  • It seems(verify) windows can only shift its default 2/2 to the split to 1GB kernel, 3GB application, using the /3GB boot option (the feature is somewhat confusingly called 4GT), but it seems that windows applications are normally compiled with the 2/2 assumption and will not be helped unless coded to. Exceptions seem to primarily include database servers.
  • You may be able to work around it with a 4G/4G split patch, combined with PAE - with some overhead.

See also

Some understanding of memory hardware

"What Every Programmer Should Know About Memory" is a good overview of memory architectures, RAM types, reasons bandwidth and access speeds vary.

RAM types

DRAM - Dynamic RAM

lower component count per cell than most (transistor+capacitor mainly), so high-density and cheaper
yet capacitor leakage means this has to be refreshed regularly, meaning a DRAM controller, more complexity and higher latency than some
(...which can be alleviated and is less of an issue when you have multiple chips)
typical as main RAM, due to cost

SRAM - Static RAM

Has a higher component count per cell than e.g. DRAM (6 transistors).
Retains state as long as power is applied
no need for a controller means it's simpler to use
No refreshing means it's often a little lower-latency.
e.g used in caches, due to speed, and acceptable cost for lower amounts

PSRAM - PseudoStatic RAM

DRAM with built-in refresh (while DRAM can have this, that's often a sleep mode that retains state without an active DRAM controller)
as standalone as SRAM, higher-density more like DRAM

SDRAM - Synchronous DRAM

DRAM coordinated via an external clock signal (previous DRAM was asynchronous, manipulating state as soon as lines changed)
This allows the interface to be a predictable state machine, which allows some buffering and interleaving of internal banks
...and thereby higher data rates (though not necessarily lower latency)
DDR doubled busrate by widening the (minimum) units they read/write (double that of SDR), which they can do from single DRAM bank(verify)
similarly, DDR2 is 4x larger units than SDR and DDR3 is 8x larger units than SDR
DDR4 uses the same width as DDR3, instead doubling the busrate by interleaving from banks
unrelated to latency, it's just that the bus frequency also increased over time.

Graphics RAM refers to varied specialized

Earlier versions would e.g. allow reads and writes (almost) in parallel, making for lower-latency framebuffers
recent GPUs mostly use GDDR, a somwhat specialized form of DDR SDRAM

Memory stick types


can detect many (and correct some) hardware errors in RAM
The rate of of bit-flips is low, but will happen. If your computations or data are very important to you, you want ECC.
See also:
DRAM Errors in the Wild: A Large-Scale Field Study

Registered RAM basically places a buffer on the DRAM modules (so register as in hardware register)

offloads some electrical load from the main controller to these buffers, making it easier to design stably with more individual memory sticks/chips.
at a small latency hit
typical in servers, because they can accept more sticks
Must be supported by the memory controller, which typically means you will decide it as part of motherboard choice
pricier (more electronics, fewer units sold)
because of server use, most registered RAM is specifically registered ECC RAM
yet there is also unregistered ECC, and registered non-ECC, which can be good options on specific designs of simpler servers and beefy workstations.
sometimes called RDIMM -- in the same context UDIMM is used to refer to unbuffered

FB-DIMM, Fully Buffered DIMM

same intent as registered RAM - more stable sticks on one controller
the buffer is now between stick and controller [1]
physically different pinout/notching

SO-DIMM (Small Outline DIMM)

Smaller RAM. Used in laptops, some networking hardware, some Mini-ITX

EPP and XMP (Enhanced Performance Profile, Extreme Memory Profiles)

basically, one-click overclocking for RAM
so you can configure faster timings (and Vdimm and such) according to the modules, rather than your guess
normally, memory timing is configured according to a table in the SPD, which are JEDEC-approved ratings and typically conservative.
EPP and XMP basically means running them as fast as they could go (and typically higher voltage)

On pin count

SO-DIMM tends to have a different pin count
e.g. DDR3 has 240 pins, DDR3 SO-DIMM has 204
e.g. DDR4 has 288 pins, DDR4 SO-DIMM has 260
Registered RAM has the same pin count
ECC RAM has the same pin count

In any case, the type of memory must be supported by the memory controller

DDR2/3/4 - physically won't fit
Note that while some controllers (e.g. those in CPUs) support two generations, a motherboard will typically have just one type of memory socket
registered or not
ECC or not

Historically, RAM controllers were a thing on the motherboard near the CPU, while there are now various cases where the controller is on the CPU.

More on DRAM versus SRAM

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


Buffered/registered RAM

EPROM, EEPROM, and variants

Flash memory


Flash memory

Memory card types

These are primarily notes
It won't be complete in any sense.
It exists to contain fragments of useful information.

See also http://en.wikipedia.org/wiki/Comparison_of_memory_cards

MultiMediaCard (MMC)

In context of today, this was the predecessor for SD.

Secure Digital (SD, miniSD, microSD)

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)


Sizes and basic pins (not showing extra UHS pins)

Physical sizes: There's mainly

  • SD (24x32x2.1mm)
  • microSD (11x15x1.0mm)
previously called TransFlash, and some parts of the world still prefer that name

(There's also MiniSD, which never really took off)

The variants are pin-compatible (some footnotes on the faster ones), so adapters to larger sizes exist, and the choice of which you want relates more to the device. For example, cameras and laptops and generic card readers often prefer SD, which is a little sturdier and less fiddly to move around, smartphones use microSD because of the smaller size and it being more or less permanently in there anyway.


  • there are a few footnotes to compatibility, e.g. that the newest generation are not guaranteed to work in the oldest readers
  • SD readers for a long while also had sockets for MMC cards, because MMC was the previous generation, so reader ICs support them, and it was a a nice extra feature to put on the box even when MMC cards are becoming rare.

Capacity types / families

  • SD (now SDSC, 'standard capacity', to distinguish it)
    • size artificially limited to 1-4GB
  • SDHC (high capacity)
    • physically identical but conforming to a new standard that allows for higher capacity and speed.
    • adressing limited to 32GB
  • SDXC (eXtended-Capacity )
    • successor to SDHC (2009) that allows for higher capacity and speed
    • adressing limited to 2TB
  • Ultra-Capacity (SDUC)
  • SDIO
    • allows more arbitrary communication, basically a way to plug in specific accessories, at least on supporting hosts - not really an arbitrarily usable bus for consumers
    • (supports devices like GPS, wired and wireless networking)

The above is partly about capacity, and partly about function. It's also not entirely aligned with SD versions, protocolwise it's even more interesting, particularly with the extra buses for the faster (UHS and Express) modes.

I think most people have list track of the details by now.

Speed rating

There are two gotchas to speed ratings:

  • due to the nature of flash, it will read faster than it will write.
how much faster/slower depends, but it's easily a factor 2
if marketers can get away with it, they will specify the read speed
note that the differences vary, due to differences in controlles. E.g. external card readers tend to be cheap shit, though there are some examples of slow
  • writes can be faster in short bursts.
because you're actually talking to a storage controller, managing the flash
You usually care about sustained average write instead
And sometimes about the guaranteed speed, i.e. the minimum per second-or-so


Should specify minimum sustained write speed.

  • Class 0 doesn't specify performance
  • Class 2 means ≥2 MB/s
  • Class 4 means ≥4 MB/s
  • Class 6 means ≥6 MB/s
  • Class 10 means ≥10 MB/s

Apparently these are not required to be sustained speed or write speed(verify), or at least practice proves not everyone keeps to this, so if it looks dubious, it probably is.

It seems to vary with honesty, so a good Class 6 card may well perform better than a bad Class 10 one.

These days, most decent SDs can sustain 10MB/s writes (and not necessarily much more), so the class system is no longer a useful indication of actual speed.

x rating

Units of 150kByte/sec.

For some numeric idea, though:

  • 13x is roughly equivalent to class 2
  • 40x is roughly equivalent to class 6
  • 66x is roughly equivalent to class 10
  • 300x is ~45MB/s
  • 666x is ~100MB/s

Apparently these are not required to be sustained speed or write speed(verify), or at least practice proves not everyone keeps to this, so if it looks dubious, it probably is.

UHS class (number ini a U/bucket)

  • 1 means 10MByte/s
  • 3 means 30MByte/s

Video Speed Class, V Class

  • V6 6MB/s
  • V10 10MB/s
  • V30 30MB/s
  • V60 60MB/s
  • V90 90MB/s

These were introduced because realtime-not-too-compressed HD video tends to want

perhaps 10MByte/s for 1080p
perhaps 30MByte/s for FHD
perhaps 60MByte/s for 4k
perhaps 90MByte/s for 8k

These are apparently required to be sustained speeds(verify)


CompactFlash (CF)

Type I:

  • 3.3mm thick

Type II:

  • 5mm thick

Memory Stick (Duo, Pro, Micro (M2), etc.)


A few types, sizes up to 512MB and 2GB varying with them.

Apparently quite similar to SmartMedia

SmartMedia (SM)

  • Very thin (for its length/width)
  • capacity limited to 128MB (...so not seen much anymore)

On fake flash

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

Fake flash refers to a scam where cards's controller reports a larger size than there is actually storage.

These seem to come in roughly two variants:

addressing storage that isn't there will fail,
or it will wrap back on itself and write in existing area.

In both cases it will seem to work for a little while, and in both cases it will corrupt later. Exactly how and when depends on the type, and also on how it was formatted (FAT32 is likelier to fail a little sooner than NTFS due to where it places important filesystem data)

There are some tools to detect fake flash. You can e.g. read out what flash memory chips are in there and whether that adds up. Scammers don't go so far to fake this.

But the more thorough check is a write-and-verify test, see below.

Memory card health

This article/section is a stub — probably a pile of half-sorted notes, is not well-checked so may have incorrect bits. (Feel free to ignore, fix, or tell me)

While memory cards and USB sticks are flash memory, most lack the wear leveling and health introspection that e.g. SSDs have.

So generally they will work perfectly, until they start misbehaving, and without warning.

Things like windows chkdsk will by default only check the filesystem structure. While such tools can often be made to read all disk surface (for chkdsk it's the 'scan for an attempt recovery of bad sectors" checkbox), this only guarantees that everything currently on there can be read.

This is a decent check for overall failure, but not a check of whether any of it is entirely worn (and would will not take new data), and also not a test for fake flash.

The better test is writing data to all blocks, then checking back its contents. Depending a little on how this is done, this is either destructive, or only checks free space.

Yes, you can these checks relatively manually, but it's a little finicky to do right.

One useful tool is H2testw, which creates a file in free space (if empty, then almost all the SD card)

It will also tell you write and read speed.

And implicitly be a fake flash test.

What's stored