Paging Pool

Other versions of this page are also available for the following:

Windows Mobile Not SupportedWindows Embedded CE Supported


This topic describes the paging pool component of the Windows Embedded CE 6.0 kernel. It shows the default parameters for the loader pool and the file pool.

Overview of the Paging Pool

The pool consists mainly of a page counter and a trimming thread. During kernel initialization, the loader pool and the file pool are created. Pool initialization uses OEM parameters to set the sizes that control pool operation. It calls in to the physical page manager to reserve pages up to the target pool size. However, at that time, the pool size is still zero because it has not consumed any of the reserved pages.

The pool size can range between zero and the maximum, but besides the target there are several other intermediate sizes that define pool behavior. The pool has several parameters controlling the size, shown in the following list

  • Target: When the pool reaches or exceeds its target size, the trimming thread starts running to release pages.
  • Release increment: After the trimming thread starts running, it runs until the pool size falls below the target. The release increment is the amount of data below the target to discard before the thread stops. When the pool reaches this size, the thread stops until the pool exceeds its target size again. Too large an increment discards more data than necessary, wasting RAM and affecting performance. Too small an increment keeps the thread running almost constantly.
  • Maximum: The size a pool cannot exceed.
  • Critical increment: The critical increment is the amount of pool space that can be left before the thread goes into high-priority critical mode. When there is less than this much space left before the pool reaches its maximum, the trim thread runs at high priority. After the pool reaches this size, the thread continues running at high priority until it has paged out enough memory so that the pool has twice the critical increment of free space remaining. The thread then returns to low priority until the pool has less than the critical increment remaining again. Too large an increment starts the thread running too early and makes it run for too long. Too small an increment wakes the thread too often.

Implementation of the Page Pools

The pool has a maximum size, above which it cannot grow. Even if there is free memory in the system, the pool cannot exceed its maximum size. Instead, pool pages must be discarded to free space for new pages.

Whenever the pool is below or at its target size, system tools show the target amount of memory being consumed, even if the pool is not currently using that much memory. When the pool is larger than its target, the system tools show additional memory being used, as well.

The pool does not use a predetermined set of physical pages, and the set of physical pages used by the pool changes freely. There is no way to determine which physical pages are in use by the pool at any time, only how many pages are in use.

Pool target and maximum sizes are set at the beginning of boot and never change. There are currently no plans to make pool parameters dynamically changeable.

The kernel has two pools: one for loader pages (EXE and DLL pages) and another for the file cache and memory-mapped files. The two pools can be controlled independently, and can be disabled by setting their sizes to zero. When a pool is disabled, there are no constraints on memory usage. The loader or file cache can consume pages up to the limit of free physical memory.

The pool parameters are configurable with the Config.bib file FIXUPVAR values, so it is possible to modify these values without modifying code or rebuilding the OEM adaptation layer (OAL).

const volatile DWORD LoaderPoolTarget;
const volatile DWORD LoaderPoolMaximum;
const volatile DWORD LoaderPoolReleaseIncrement;
const volatile DWORD LoaderPoolCriticalIncrement;
const volatile DWORD LoaderPoolNormalPriority256;
const volatile DWORD LoaderPoolCriticalPriority256;
const volatile DWORD FilePoolTarget;
const volatile DWORD FilePoolMaximum;
const volatile DWORD FilePoolReleaseIncrement;
const volatile DWORD FilePoolCriticalIncrement;
const volatile DWORD FilePoolNormalPriority256;
const volatile DWORD FilePoolCriticalPriority256;

OEMs can also modify the values at run-time, by calling an OAL I/O control, IOCTL_HAL_GET_POOL_PARAMETERS, and passing a NKPagePoolParameters structure.

For debugging purposes, the kernel exposes pool state with an I/O control. An application can query the pool state by calling KernelLibIoControl with IOCTL_KLIB_GET_POOL_STATE, and passing a NKPagePoolState structure.

Setting the Paging Pool Size

Set the paging pool size by setting the PAGINGPOOLSIZE environment variable in the build window, followed by running makeimg. The following code example shows how to set the paging pool size to 4.5 MB:


Collecting Performance Data

The boot time and application launch time are affected by the paging pool size. Therefore, they provide good data for determining the optimum paging pool size. It is important to measure the boot time and application launch time consistently 3-5 times, and then use the data average.

Boot Time

Start the stopwatch as soon as you press the power button (method 1) or when you see the boot loader screen (method 2). Make sure to be consistent, since there is a few seconds difference between the two methods. Stop the time when the home screen soft keys are drawn.

Do not measure the first couple of boots after clearing flash because the software performs extra initialization during those boots. Subsequent boot times should be consistent and provide good data points.

Application Launch Time

Start the stopwatch as soon as you perform the appropriate user input to launch the application. Stop the time as soon as the soft keys are drawn for the application. Inbox, Contacts, and Calendar are good candidates for these measurements. It is important to measure the first launch after boot. It is even more important to launch the applications in the same order at every boot.

Taking Advantage of NOR

If you have NOR flash available, consider uncompressing as many packages as possible onto the NOR flash. It helps both performance and RAM usage because the code can be run in place.

Write-back Cache

Writing to flash is a bottleneck for a lot of scenarios on the device. To mitigate the bottleneck, you can enable the write-back cache for the flash file system on the platform. A 64-KB cache is enough for the key user scenarios. When registering the flash file system in platform.reg, the following registry keys set up the flash file system for a 64-KB write-back cache. MSFlash should be replaced with the name of the profile for the block driver that controls the TFAT partition.

   128 sectors(128*512=64KB)

Default Parameters for the Loader Pool

The following table shows the default parameters for the loader pool.

Parameter Value Description


4 MB

Typical pool size.


6 MB

Should be reasonable for accommodating cases such as booting, which runs more code.

Release increment

128 KB

Leaves some free pages, without wasting too much of the target size.

Critical increment

64 KB

Does not discard too much data at high priority, but leaves 128 KB of room afterward.

Normal priority

255 bytes

Lowest possible priority, to minimize effect on performance of trimming during booting and application launch.

Critical priority

247 bytes

Higher than all non-real-time priorities to run before all application threads.

Default Parameters for the File Pool

The following table shows the default parameters for the loader pool.

Parameter Value Description


1 MB

Typical file cache size. Does not consume too much memory in steady state.


10 MB

During heavy file activity, expand into more memory.

Release increment

64 KB

Not wasting too much of the target size. Extra room is probably not a priority since anyone exceeding the target probably exceeds it by a lot.

Critical increment

64 KB

Does not discard too much data at high priority, but leaves 128 KB of space afterward.

Normal priority

255 bytes

Lowest possible priority, to minimize the effect on performance of trimming during file activity.

Critical priority

251 bytes

THREAD_PRIORITY_NORMAL, to avoid causing user interface (UI) lag or other noticeable problems.

See Also


Memory Architecture

Other Resources

Developing a Device Driver
Bringing Up a Hardware Platform