Programming Your Emu
Prior to the Solaris 9 OS, databases were typically the only users of larger page sizes through the intimate shared memory (ISM) facility provided by the SHM_SHARE_MMU option of shmat(2). The Solaris 9 OS provides three methods for advising preferred page sizes for applications:
Wrapper program, ppgsz(1)
Preload library, libmpss.so.1
Programmatic interface, memcntl(2)
UltraSPARC supports four page sizes; 8 kilobyte (default), 64 kilobyte, 512 kilobyte, and 4 megabyte.
Enabling large pages for an application's heap is quite straightforward. Simply wrap the target binary with the ppgsz command and the appropriate options, as follows:
sol9# ppgsz -o heap=4M ./testprog &
After starting the target program, you can check to see how many large pages were allocated with the pmap -sx command. In the following example, the majority of the heap has been allocated with 4-megabyte pages:
sol9# pmap -sx ´pgrep testprog´ 2953: ./testprog Address Kbytes RSS Anon Locked Pgsz Mode Mapped File 00010000 8 8 - - 8K r-x-- dev:277,83 ino:114875 00020000 8 8 8 - 8K rwx-- dev:277,83 ino:114875 00022000 3960 3960 3960 - 8K rwx-- [ heap ] 00400000 131072 131072 131072 - 4M rwx-- [ heap ] FF280000 120 120 - - 8K r-x-- libc.so.1 FF29E000 136 128 - - - r-x-- libc.so.1 FF2C0000 72 72 - - 8K r-x-- libc.so.1 FF2D2000 192 192 - - - r-x-- libc.so.1 FF302000 112 112 - - 8K r-x-- libc.so.1 FF31E000 48 32 - - - r-x-- libc.so.1 FF33A000 24 24 24 - 8K rwx-- libc.so.1 FF340000 8 8 8 - 8K rwx-- libc.so.1 FF390000 8 8 - - 8K r-x-- libc_psr.so.1 FF3A0000 8 8 - - 8K r-x-- libdl.so.1 FF3B0000 8 8 8 - 8K rwx-- [ anon ] FF3C0000 152 152 - - 8K r-x-- ld.so.1 FF3F6000 8 8 8 - 8K rwx-- ld.so.1 FFBFA000 24 24 24 - 8K rwx-- [ stack ] -------- ------- ------- ------- ------- total Kb 135968 135944 135112 -
The ppgsz command is the simplest to use, but the specified page size preferences will not be inherited across exec(2) calls. If your program execs another and you want the page size preferences, you should use the mpss.so.1 preload library to make this happen.
The mpss.so.1 shared object in /usr/lib provides a means by which the preferred stack or heap page size can be automatically enforced for launched processes and their descendants. The library has an the advantage over the wrapper in that page sizes are inherited across exec(2). To enable mpss.so, set LD_PRELOAD in the environment [see ld.so.1(1)], along with one or more MPSS environment variables. For example, you might use either of the following variables to specify the preferred page sizes for the heap and stack, respectively. The specified page size(s) are applied to all created processes.
MPSSHEAP=size
MPSSSTACK=size
For example, using sh or ksh:
sol9# LD_PRELOAD=$LD_PRELOAD:mpss.so.1 MPSSHEAP=4M sol9#./myprog
Or, using csh or tcsh:
sol9# setenv LD_PRELOAD $LD_PRELOAD:mpss.so.1 sol9# setenv MPSSHEAP 4M sol9# ./myprog
To confirm that the application is now running more efficiently, run trapstat again. Ideally, the percentage of time spent in the kernel will be lower. In this example, the percentage of time has dropped from 46.2 percent to 0.2 percent!
sol9# trapstat -T 1 cpu m size| itlb-miss %tim itsb-miss %tim | dtlb-miss %tim dtsb-miss %tim |%tim ----------+-------------------------------+-------------------------------+---- 0 u 8k| 30 0.0 0 0.0 | 221 0.1 0 0.0 | 0.1 0 u 64k| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 0 u 512k| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 0 u 4m| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 - - - - - + - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - + - - 0 k 8k| 1 0.0 0 0.0 | 4271 0.1 10 0.0 | 0.1 0 k 64k| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 0 k 512k| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 0 k 4m| 0 0.0 0 0.0 | 0 0.0 0 0.0 | 0.0 ==========+===============================+===============================+==== ttl | 31 0.0 0 0.0 | 4491 0.2 10 0.0 | 0.2