In the Activity Monitor app on your Mac, click Memory (or use the Touch Bar) to see the following in the bottom of the window. Memory Pressure: Graphically represents how efficiently your memory is serving your processing needs. Memory pressure is determined by the amount of free memory, swap rate, wired memory, and file cached memory. Mac or MAC most commonly refers to:. Mac, Gaelic for 'son', a prefix to family names often appearing in Gaelic names; Mackintosh, a raincoat made of rubberized cloth; Macintosh, a brand of computers and operating systems made by Apple Inc. Activity Monitor is a built-in application in MacOS which tells you everything that is running on your MacBook. It gives you a complete overview of your MacBook’s memory usage. Here you can find out what applications are currently running and how much memory is being utilized by each of the applications.

Efficient memory management is an important aspect of writing high performance code in both OS X and iOS. Minimizing memory usage not only decreases your application’s memory footprint, it can also reduce the amount of CPU time it consumes. In order to properly tune your code though, you need to understand something about how the underlying system manages memory.

Both OS X and iOS include a fully-integrated virtual memory system that you cannot turn off; it is always on. Both systems also provide up to 4 gigabytes of addressable space per 32-bit process. In addition, OS X provides approximately 18 exabytes of addressable space for 64-bit processes. Even for computers that have 4 or more gigabytes of RAM available, the system rarely dedicates this much RAM to a single process.

To give processes access to their entire 4 gigabyte or 18 exabyte address space, OS X uses the hard disk to hold data that is not currently in use. As memory gets full, sections of memory that are not being used are written to disk to make room for data that is needed now. The portion of the disk that stores the unused data is known as the backing store because it provides the backup storage for main memory.

Although OS X supports a backing store, iOS does not. In iPhone applications, read-only data that is already on the disk (such as code pages) is simply removed from memory and reloaded from disk as needed. Writable data is never removed from memory by the operating system. Instead, if the amount of free memory drops below a certain threshold, the system asks the running applications to free up memory voluntarily to make room for new data. Applications that fail to free up enough memory are terminated.

Note: Unlike most UNIX-based operating systems, OS X does not use a preallocated disk partition for the backing store. Instead, it uses all of the available space on the machine’s boot partition.

The following sections introduce terminology and provide a brief overview of the virtual memory system used in both OS X and iOS. For more detailed information on how the virtual memory system works, see Kernel Programming Guide.

About Virtual Memory

Virtual memory allows an operating system to escape the limitations of physical RAM. The virtual memory manager creates a logical address space (or “virtual” address space) for each process and divides it up into uniformly-sized chunks of memory called pages. The processor and its memory management unit (MMU) maintain a page table to map pages in the program’s logical address space to hardware addresses in the computer’s RAM. When a program’s code accesses an address in memory, the MMU uses the page table to translate the specified logical address into the actual hardware memory address. This translation occurs automatically and is transparent to the running application.

As far as a program is concerned, addresses in its logical address space are always available. However, if an application accesses an address on a memory page that is not currently in physical RAM, a page fault occurs. When that happens, the virtual memory system invokes a special page-fault handler to respond to the fault immediately. The page-fault handler stops the currently executing code, locates a free page of physical memory, loads the page containing the needed data from disk, updates the page table, and then returns control to the program’s code, which can then access the memory address normally. This process is known as paging.

If there are no free pages available in physical memory, the handler must first release an existing page to make room for the new page. How the system release pages depends on the platform. In OS X, the virtual memory system often writes pages to the backing store. The backing store is a disk-based repository containing a copy of the memory pages used by a given process. Moving data from physical memory to the backing store is called paging out (or “swapping out”); moving data from the backing store back in to physical memory is called paging in (or “swapping in”). In iOS, there is no backing store and so pages are are never paged out to disk, but read-only pages are still be paged in from disk as needed.

In OS X and in earlier versions of iOS, the size of a page is 4 kilobytes. In later versions of iOS, A7- and A8-based systems expose 16-kilobyte pages to the 64-bit userspace backed by 4-kilobyte physical pages, while A9 systems expose 16-kilobyte pages backed by 16-kilobyte physical pages. These sizes determine how many kilobytes the system reads from disk when a page fault occurs. Disk thrashing can occur when the system spends a disproportionate amount of time handling page faults and reading and writing pages, rather than executing code for a program.

Paging of any kind, and disk thrashing in particular, affects performance negatively because it forces the system to spend a lot of time reading and writing to disk. Reading a page in from the backing store takes a significant amount of time and is much slower than reading directly from RAM. If the system has to write a page to disk before it can read another page from disk, the performance impact is even worse.

Details of the Virtual Memory System

The logical address space of a process consists of mapped regions of memory. Each mapped memory region contains a known number of virtual memory pages. Each region has specific attributes controlling such things as inheritance (portions of the region may be mapped from “parent” regions), write-protection, and whether it is wired (that is, it cannot be paged out). Because regions contain a known number of pages, they are page-aligned, meaning the starting address of the region is also the starting address of a page and the ending address also defines the end of a page.

The kernel associates a VM object with each region of the logical address space. The kernel uses VM objects to track and manage the resident and nonresident pages of the associated regions. A region can map to part of the backing store or to a memory-mapped file in the file system. Each VM object contains a map that associates regions with either the default pager or the vnode pager. The default pager is a system manager that manages the nonresident virtual memory pages in the backing store and fetches those pages when requested. The vnode pager implements memory-mapped file access. The vnode pager uses the paging mechanism to provide a window directly into a file. This mechanism lets you read and write portions of the file as if they were located in memory.

In addition to mapping regions to either the default or vnode pager, a VM object may also map regions to another VM object. The kernel uses this self referencing technique to implement copy-on-write regions. Copy-on-write regions allow different processes (or multiple blocks of code within a process) to share a page as long as none of them write to that page. When a process attempts to write to the page, a copy of the page is created in the logical address space of the process doing the writing. From that point forward, the writing process maintains its own separate copy of the page, which it can write to at any time. Copy-on-write regions let the system share large quantities of data efficiently in memory while still letting processes manipulate those pages directly (and safely) if needed. These types of regions are most commonly used for the data pages loaded from system frameworks.

Each VM object contains several fields, as shown in Table 1.

Table 1 Fields of the VM object

Field

Description

Resident pages

A list of the pages of this region that are currently resident in physical memory.

Size

The size of the region, in bytes.

Pager

The pager responsible for tracking and handling the pages of this region in backing store.

Shadow

Used for copy-on-write optimizations.

Copy

Used for copy-on-write optimizations.

Attributes

Flags indicating the state of various implementation details.

If the VM object is involved in a copy-on-write (vm_copy) operation, the shadow and copy fields may point to other VM objects. Otherwise both fields are usually NULL.

Wired Memory

Wired memory (also called resident memory) stores kernel code and data structures that must never be paged out to disk. Applications, frameworks, and other user-level software cannot allocate wired memory. However, they can affect how much wired memory exists at any time. For example, an application that creates threads and ports implicitly allocates wired memory for the required kernel resources that are associated with them.

Table 2 lists some of the wired-memory costs for application-generated entities.

Table 2 Wired memory generated by user-level software

Resource

Wired Memory Used by Kernel

Process

16 kilobytes

Thread

blocked in a continuation—5 kilobytes; blocked—21 kilobytes

Mach port

116 bytes

Mapping

32 bytes

Library

2 kilobytes plus 200 bytes for each task that uses it

Memory region

160 bytes

Memory Museum Mac OS

Note: These measurements may change with each new release of the operating system. They are provided here to give you a rough estimate of the relative cost of system resource usage.

As you can see, every thread, process, and library contributes to the resident footprint of the system. In addition to your application using wired memory, however, the kernel itself requires wired memory for the following entities:

  • VM objects

  • the virtual memory buffer cache

  • I/O buffer caches

  • drivers

Wired data structures are also associated with the physical page and map tables used to store virtual-memory mapping information, Both of these entities scale with the amount of available physical memory. Consequently, when you add memory to a system, the amount of wired memory increases even if nothing else changes. When a computer is first booted into the Finder, with no other applications running, wired memory can consume approximately 14 megabytes of a 64 megabyte system and 17 megabytes of a 128 megabyte system.

Wired memory pages are not immediately moved back to the free list when they become invalid. Instead they are “garbage collected” when the free-page count falls below the threshold that triggers page out events.

Page Lists in the Kernel

The kernel maintains and queries three system-wide lists of physical memory pages:

  • The active list contains pages that are currently mapped into memory and have been recently accessed.

  • The inactive list contains pages that are currently resident in physical memory but have not been accessed recently. These pages contain valid data but may be removed from memory at any time.

  • The free list contains pages of physical memory that are not associated with any address space of VM object. These pages are available for immediate use by any process that needs them.

When the number of pages on the free list falls below a threshold (determined by the size of physical memory), the pager attempts to balance the queues. It does this by pulling pages from the inactive list. If a page has been accessed recently, it is reactivated and placed on the end of the active list. In OS X, if an inactive page contains data that has not been written to the backing store recently, its contents must be paged out to disk before it can be placed on the free list. (In iOS, modified but inactive pages must remain in memory and be cleaned up by the application that owns them.) If an inactive page has not been modified and is not permanently resident (wired), it is stolen (any current virtual mappings to it are destroyed) and added to the free list. Once the free list size exceeds the target threshold, the pager rests.

The kernel moves pages from the active list to the inactive list if they are not accessed; it moves pages from the inactive list to the active list on a soft fault (see Paging In Process). When virtual pages are swapped out, the associated physical pages are placed in the free list. Also, when processes explicitly free memory, the kernel moves the affected pages to the free list.

Paging Out Process

In OS X, when the number of pages in the free list dips below a computed threshold, the kernel reclaims physical pages for the free list by swapping inactive pages out of memory. To do this, the kernel iterates all resident pages in the active and inactive lists, performing the following steps:

  1. If a page in the active list is not recently touched, it is moved to the inactive list.

  2. If a page in the inactive list is not recently touched, the kernel finds the page’s VM object.

  3. If the VM object has never been paged before, the kernel calls an initialization routine that creates and assigns a default pager object.

  4. The VM object’s default pager attempts to write the page out to the backing store.

  5. If the pager succeeds, the kernel frees the physical memory occupied by the page and moves the page from the inactive to the free list.

Note: In iOS, the kernel does not write pages out to a backing store. When the amount of free memory dips below the computed threshold, the kernel flushes pages that are inactive and unmodified and may also ask the running application to free up memory directly. For more information on responding to these notifications, see Responding to Low-Memory Warnings in iOS.

Paging In Process

The final phase of virtual memory management moves pages into physical memory, either from the backing store or from the file containing the page data. A memory access fault initiates the page-in process. A memory access fault occurs when code tries to access data at a virtual address that is not mapped to physical memory. There are two kinds of faults:

  • A soft fault occurs when the page of the referenced address is resident in physical memory but is currently not mapped into the address space of this process.

  • A hard fault occurs when the page of the referenced address is not in physical memory but is swapped out to backing store (or is available from a mapped file). This is what is typically known as a page fault.

When any type of fault occurs, the kernel locates the map entry and VM object for the accessed region. The kernel then goes through the VM object’s list of resident pages. If the desired page is in the list of resident pages, the kernel generates a soft fault. If the page is not in the list of resident pages, it generates a hard fault.

For soft faults, the kernel maps the physical memory containing the pages to the virtual address space of the process. The kernel then marks the specific page as active. If the fault involved a write operation, the page is also marked as modified so that it will be written to backing store if it needs to be freed later.

For hard faults, the VM object’s pager finds the page in the backing store or from the file on disk, depending on the type of pager. After making the appropriate adjustments to the map information, the pager moves the page into physical memory and places the page on the active list. As with a soft fault, if the fault involved a write operation, the page is marked as modified.



Copyright © 2003, 2013 Apple Inc. All Rights Reserved. Terms of Use Privacy Policy Updated: 2013-04-23

(Redirected from Mac OS memory management)
'About This Computer' Mac OS 9.1 window showing the memory consumption of each open application and the system software itself.

Historically, the classic Mac OS used a form of memory management that has fallen out of favor in modern systems. Criticism of this approach was one of the key areas addressed by the change to Mac OS X.

The original problem for the engineers of the Macintosh was how to make optimum use of the 128 KB of RAM with which the machine was equipped, on Motorola 68000-based computer hardware that did not support virtual memory.[1] Since at that time the machine could only run one application program at a time, and there was no fixedsecondary storage, the engineers implemented a simple scheme which worked well with those particular constraints. That design choice did not scale well with the development of the machine, creating various difficulties for both programmers and users.

Fragmentation[edit]

The primary concern of the original engineers appears to have been fragmentation – that is, the repeated allocation and deallocation of memory through pointers leading to many small isolated areas of memory which cannot be used because they are too small, even though the total free memory may be sufficient to satisfy a particular request for memory. To solve this, Apple engineers used the concept of a relocatable handle, a reference to memory which allowed the actual data referred to be moved without invalidating the handle. Apple's scheme was simple – a handle was simply a pointer into a (non-relocatable) table of further pointers, which in turn pointed to the data.[2] If a memory request required compaction of memory, this was done and the table, called the master pointer block, was updated. The machine itself implemented two areas in memory available for this scheme – the system heap (used for the OS), and the application heap.[3] As long as only one application at a time was run, the system worked well. Since the entire application heap was dissolved when the application quit, fragmentation was minimized.

The memory management system had weaknesses; the system heap was not protected from errant applications, as would have been possible if the system architecture had supported memory protection, and this was frequently the cause of system problems and crashes.[4] In addition, the handle-based approach also opened up a source of programming errors, where pointers to data within such relocatable blocks could not be guaranteed to remain valid across calls that might cause memory to move. This was a real problem for almost every system API that existed. Because of the transparency of system-owned data structures at the time, the APIs could do little to solve this. Thus the onus was on the programmer not to create such pointers, or at least manage them very carefully by dereferencing all handles after every such API call. Since many programmers were not generally familiar with this approach, early Mac programs suffered frequently from faults arising from this.[5]

Palm OS and 16-bit Windows use a similar scheme for memory management, but the Palm and Windows versions make programmer error more difficult. For instance, in Mac OS, to convert a handle to a pointer, a program just de-references the handle directly, but if the handle is not locked, the pointer can become invalid quickly. Calls to lock and unlock handles are not balanced; ten calls to HLock are undone by a single call to HUnlock.[6] In Palm OS and Windows, handles are an opaque type and must be de-referenced with MemHandleLock on Palm OS or Global/LocalLock on Windows. When a Palm or Windows application is finished with a handle, it calls MemHandleUnlock or Global/LocalUnlock. Palm OS and Windows keep a lock count for blocks; after three calls to MemHandleLock, a block will only become unlocked after three calls to MemHandleUnlock.

Addressing the problem of nested locks and unlocks can be straightforward (although tedious) by employing various methods, but these intrude upon the readability of the associated code block and require awareness and discipline on the part of the coder.

Memory leaks and stale references[edit]

Awareness and discipline are also necessary to avoid memory 'leaks' (failure to deallocate within the scope of the allocation) and to avoid references to stale handles after release (which usually resulted in a hard crash—annoying on a single-tasking system, potentially disastrous if other programs are running).

Memory Museum Mac Os 11

Switcher[edit]

The situation worsened with the advent of Switcher, which was a way for a Mac with 512KB or more of memory to run multiple applications at once.[7] This was a necessary step forward for users, who found the one-app-at-a-time approach very limiting. Because Apple was now committed to its memory management model, as well as compatibility with existing applications, it was forced to adopt a scheme where each application was allocated its own heap from the available RAM.[8]The amount of actual RAM allocated to each heap was set by a value coded into the metadata of each application, set by the programmer. Sometimes this value wasn't enough for particular kinds of work, so the value setting had to be exposed to the user to allow them to tweak the heap size to suit their own requirements. While popular among 'power users', this exposure of a technical implementation detail was against the grain of the Mac user philosophy. Apart from exposing users to esoteric technicalities, it was inefficient, since an application would be made to grab all of its allotted RAM, even if it left most of it subsequently unused. Another application might be memory starved, but would be unable to utilize the free memory 'owned' by another application.[3]

While an application could not beneficially utilize a sister application's heap, it could certainly destroy it, typically by inadvertently writing to a nonsense address. An application accidentally treating a fragment of text or image, or an unassigned location as a pointer could easily overwrite the code or data of other applications or even the OS, leaving 'lurkers' even after the program was exited. Such problems could be extremely difficult to analyze and correct.

Switcher evolved into MultiFinder in System 4.2, which became the Process Manager in System 7, and by then the scheme was long entrenched. Apple made some attempts to work around the obvious limitations – temporary memory was one, where an application could 'borrow' free RAM that lay outside of its heap for short periods, but this was unpopular with programmers so it largely failed to solve the problems. Apple's System 7 Tune-up addon added a 'minimum' memory size and a 'preferred' size—if the preferred amount of memory was not available, the program could launch in the minimum space, possibly with reduced functionality. This was incorporated into the standard OS starting with System 7.1, but still did not address the root problem.[9]

Virtual memory schemes, which made more memory available by paging unused portions of memory to disk, were made available by third-party utilities like Connectix Virtual, and then by Apple in System 7. This increased Macintosh memory capacity at a performance cost, but did not add protected memory or prevent the memory manager's heap compaction that would invalidate some pointers.

32-bit clean[edit]

Originally the Macintosh had 128 kB of RAM, with a limit of 512 kB. This was increased to 4 MB upon the introduction of the Macintosh Plus. These Macintosh computers used the 68000 CPU, a 32-bit processor, but only had 24 physical address lines. The 24 lines allowed the processor to address up to 16 MB of memory (224 bytes), which was seen as a sufficient amount at the time. The RAM limit in the Macintosh design was 4 MB of RAM and 4 MB of ROM, because of the structure of the memory map.[10] This was fixed by changing the memory map with the Macintosh II and the Macintosh Portable, allowing up to 8 MB of RAM.

Because memory was a scarce resource, the authors of the Mac OS decided to take advantage of the unused byte in each address. The original Memory Manager (up until the advent of System 7) placed flags in the high 8 bits of each 32-bit pointer and handle. Each address contained flags such as 'locked', 'purgeable', or 'resource', which were stored in the master pointer table. When used as an actual address, these flags were masked off and ignored by the CPU.[4]

While a good use of very limited RAM space, this design caused problems when Apple introduced the Macintosh II, which used the 32-bit Motorola 68020 CPU. The 68020 had 32 physical address lines which could address up to 4 GB (232 bytes) of memory. The flags that the Memory Manager stored in the high byte of each pointer and handle were significant now, and could lead to addressing errors.

In theory, the architects of the Macintosh system software were free to change the 'flags in the high byte' scheme to avoid this problem, and they did. For example, on the Macintosh IIci and later machines, HLock() and other APIs were rewritten to implement handle locking in a way other than flagging the high bits of handles. But many Macintosh application programmers and a great deal of the Macintosh system software code itself accessed the flags directly rather than using the APIs, such as HLock(), which had been provided to manipulate them. By doing this they rendered their applications incompatible with true 32-bit addressing, and this became known as not being '32-bit clean'.

In order to stop continual system crashes caused by this issue, System 6 and earlier running on a 68020 or a 68030 would force the machine into 24-bit mode, and would only recognize and address the first 8 megabytes of RAM, an obvious flaw in machines whose hardware was wired to accept up to 128 MB RAM – and whose product literature advertised this capability. With System 7, the Mac system software was finally made 32-bit clean, but there were still the problem of dirty ROMs. The problem was that the decision to use 24-bit or 32-bit addressing has to be made very early in the boot process, when the ROM routines initialized the Memory Manager to set up a basic Mac environment where NuBus ROMs and disk drivers are loaded and executed. Older ROMs did not have any 32-bit Memory Manager support and so was not possible to boot into 32-bit mode. Surprisingly, the first solution to this flaw was published by software utility company Connectix, whose 1991 product MODE32 reinitialized the Memory Manager and repeated early parts of the Mac boot process, allowing the system to boot into 32-bit mode and enabling the use of all the RAM in the machine. Apple licensed the software from Connectix later in 1991 and distributed it for free. The Macintosh IIci and later Motorola based Macintosh computers had 32-bit clean ROMs.

It was quite a while before applications were updated to remove all 24-bit dependencies, and System 7 provided a way to switch back to 24-bit mode if application incompatibilities were found.[3] By the time of migration to the PowerPC and System 7.1.2, 32-bit cleanliness was mandatory for creating native applications and even later Motorola 68040 based Macs could not support 24-bit mode.[6][11]

Object orientation[edit]

The rise of object-oriented languages for programming the Mac – first Object Pascal, then later C++ – also caused problems for the memory model adopted. At first, it would seem natural that objects would be implemented via handles, to gain the advantage of being relocatable. These languages, as they were originally designed, used pointers for objects, which would lead to fragmentation issues. A solution, implemented by the THINK (later Symantec) compilers, was to use Handles internally for objects, but use a pointer syntax to access them. This seemed a good idea at first, but soon deep problems emerged, since programmers could not tell whether they were dealing with a relocatable or fixed block, and so had no way to know whether to take on the task of locking objects or not. Needless to say this led to huge numbers of bugs and problems with these early object implementations. Later compilers did not attempt to do this, but used real pointers, often implementing their own memory allocation schemes to work around the Mac OS memory model.

While the Mac OS memory model, with all its inherent problems, remained this way right through to Mac OS 9, due to severe application compatibility constraints, the increasing availability of cheap RAM meant that by and large most users could upgrade their way out of a corner. The memory was not used efficiently, but it was abundant enough that the issue never became critical. This is ironic given that the purpose of the original design was to maximise the use of very limited amounts of memory. Mac OS X finally did away with the whole scheme, implementing a modern sparse virtual memory scheme. A subset of the older memory model APIs still exists for compatibility as part of Carbon, but maps to the modern memory manager (a thread-safe malloc implementation) underneath.[6] Apple recommends that Mac OS X code use malloc and free 'almost exclusively'.[12]

Mac Os Catalina

References[edit]

  1. ^Hertzfeld, Andy (September 1983), The Original Macintosh: We're Not Hackers!, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  2. ^Hertzfeld, Andy (January 1982), The Original Macintosh: Hungarian, archived from the original on June 19, 2010, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  3. ^ abcmemorymanagement.org (December 15, 2000), Memory management in Mac OS, archived from the original on May 16, 2010, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  4. ^ abHertzfeld, Andy, The Original Macintosh: Mea Culpa, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  5. ^Apple Computer (October 1, 1985), Technical Note OV09: Debugging With PurgeMem and CompactMem, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  6. ^ abcLegacy Memory Manager Reference, Apple Inc., June 27, 2007, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  7. ^Hertzfeld, Andy (October 1984), The Original Macintosh: Switcher, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  8. ^Mindfire Solutions (March 6, 2002), Memory Management in Mac OS(PDF), p. 2, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  9. ^'System 7.1 upgrade guide'(PDF). Archived from the original(PDF) on March 4, 2016. Retrieved May 26, 2015.
  10. ^'memory maps'. Osdata.com. March 28, 2001. Retrieved May 11, 2010.CS1 maint: discouraged parameter (link)
  11. ^Apple Computer (January 1, 1991), Technical Note ME13: Memory Manager Compatibility, retrieved May 10, 2010CS1 maint: discouraged parameter (link)
  12. ^Memory Allocation Recommendations on OS X, Apple Inc, July 12, 2005, retrieved September 22, 2009CS1 maint: discouraged parameter (link)

External links[edit]

  • Macintosh: ROM Size for Various Models, Apple Inc, August 23, 2000, retrieved September 22, 2009CS1 maint: discouraged parameter (link)
Retrieved from 'https://en.wikipedia.org/w/index.php?title=Classic_Mac_OS_memory_management&oldid=1008965847'