Memory Allocation and SWAP

From Wiki-UX.info
Jump to: navigation, search

Abstract[edit]

Memory allocation is a subtle matter under UNIX Operating Systems, and the same holds true for HP-UX 11i; 32 to 64 bit applications still relays on the concept of quadrants to handle the individual process address space. The process virtual address space, likewise, takes an amount from the total system addressable virtual space (physical memory and swap).

The following programs mallocmax and memalloc allows to understand an application usage of memory using the malloc syscall. This allows to explain the limitation by example. This not details other system calls like

At the same time, 32 and 64 bit application are caped by the corresponding maxdsiz and maxdsiz_64bit_64 kernel parameters. Additional, other memory may be used in other areas, like share memory segments or the VxFS file buffer cache.

mallocmax.c[edit]

/*
This program (mallocmax.c) progressively request RAM using the malloc
system call and can be use to establish current memory allocation limits.
It comes with no support and HP makes no representations as to its
fitness for purpose. It is up to whoever uses this program to ensure
that whatever functionality it provides is what they require.
(c) Wiki-UX.info (2010)

=============================================
The following compile options determine the maximum working space
of the tool.

Compile with no flags to allow up to 900 megs.

     cc -Ae -o mallocmax mallocmax.c

Compile with -Wl,-N to allow up to 1700 megs.

     cc -Ae -Wl,-N -o mallocmax mallocmax.c

Use "chatr +q3p enable" to increase to about 2700 megs:

     chatr +q3p enable mallocmax

and chatr +q4p enable mallocmax to reach 3700 megs.

     +q3p = 11.00 with patches PHKL_20222, PHKL_20223,
       PHKL_20224, PHKL_20225, PHKL_20226, PHKL_20227,
       PHKL_20228 and PHKL_20229 (or replacements).

     +q4p = only with 11.11

For 11.23 (only), the MPAS address model is available for
32bit programs. Use the option:

     -Wl,+as,mpas

And the result is an executable with 3800 meg capability
with no chatr and less restrictions on quadrant maps.

Compile with +DA2.0W or +DD64 to create a 64bit program.
With a 64-bit program, only the kernel parameter maxdsiz_64
(and swap) will limit the total malloc area:

    cc -Ae +DD64 -o mallocmax mallocmax.c

================

There can be problems with applying chatr +q3p and +q4p to some programs. A
program that has +q3p enabled cannot map shared memory segments that were
created by other processes in the third quadrant. A program using +q3p and
+q4p cannot map any shared memory segments created by other processes.

Code compiled with +Oaggressive will have +Osignedpointers assumptions in
the generated code. That can cause bad pointer comparisons between addresses
in the first two and the last two quadrants. +q3p makes that kind of pointer
comparison more likely.
 */

# include <malloc.h>
# include <stdio.h>

main(int argc, char **argv)
{
  pid_t mypid;
  char *m;
  int i,j,chunk,schunk;

// Get chunck size, defaults 64
  printf("Chunk Size MB (1 to 1024): ");
  scanf("%d", &schunk);

  if(schunk > 0 && schunk < 1025)
     chunk = schunk*1024*1024;
  else {
     printf("Chunk size not in rage 1 to 1024 MB range!\n");
     printf("Using default value 64\n");
     schunk = 64;
     chunk = schunk*1024*1024;
     }

  for(i=1; i<=4096; i++) {
    m=malloc(chunk);
    if(m) {
       printf("Malloc of %6d MB succeeded.  Address %P. \n", i*schunk,m);
    } else {
       for(j=0;j<5;j++) {
          sleep(1);
          if( (m=malloc(chunk)) != 0) break;
       }
       if(m == 0){
          printf("malloc of %6d Meg failed.\n",i*schunk);
          break;
       } else {
    printf("malloc of %6d MB succeeded after %d sec sleep.\n",i*schunk,j+1);
       }
    }
  }
  mypid = getpid();
  fprintf(stdout, "PID = %d, press <Enter> to continue...",mypid);
  getchar();
  printf("\n");
}

Examples[edit]

1. Within the 900 MB memory limit

# cc -Ae -o mallocmax mallocmax.c
./mallocmax
Chunk Size MB (1 to 1024): 100
Malloc of 100 MB succeeded.  Address 400071E0.
Malloc of 200 MB succeeded.  Address 464071E8.
Malloc of 300 MB succeeded.  Address 4C8071F0.
Malloc of 400 MB succeeded.  Address 52C071F8.
Malloc of 500 MB succeeded.  Address 59007200.
Malloc of 600 MB succeeded.  Address 5F407208.
Malloc of 700 MB succeeded.  Address 65807210.
Malloc of 800 MB succeeded.  Address 6BC07218.
Malloc of 900 MB succeeded.  Address 72007220.
malloc of 1000 Meg failed.
PID = 13226, press <Enter> to continue...

2. Within the 1700 MB memory, no additional quadrants configured.

# cc -Ae -Wl,-N -o mallocmax mallocmax.c
# ./mallocmax
Chunk Size MB (1 to 1024): 100
Malloc of 100 Meg succeeded.  Address 00006198.
Malloc of 200 Meg succeeded.  Address 064081B8.
Malloc of 300 Meg succeeded.  Address 0C8081C0.
Malloc of 400 Meg succeeded.  Address 12C081C8.
Malloc of 500 Meg succeeded.  Address 190081D0.
Malloc of 600 Meg succeeded.  Address 1F4081D8.
Malloc of 700 Meg succeeded.  Address 258081E0.
Malloc of 800 Meg succeeded.  Address 2BC081E8.
Malloc of 900 Meg succeeded.  Address 320081F0.
Malloc of 1000 Meg succeeded.  Address 384081F8.
Malloc of 1100 Meg succeeded.  Address 3E808200.
Malloc of 1200 Meg succeeded.  Address 44C08208.
Malloc of 1300 Meg succeeded.  Address 4B008210.
Malloc of 1400 Meg succeeded.  Address 51408218.
Malloc of 1500 Meg succeeded.  Address 57808220.
Malloc of 1600 Meg succeeded.  Address 5DC08228.
malloc of 1700 Meg failed.
PID = 2723, press <Enter> to continue...

3. With additional quadrants enable, but kernel maxdsiz parameter smaller that the maximum theoretical limit.

# cc -Ae -Wl,-N -o mallocmax mallocmax.c
# chatr +q3p enable mallocmax 

#  kctune -q maxdsiz
Tunable       Value  Expression  Changes
maxdsiz  2063835136  2063835136  Immed

# chatr mallocmax | grep third
         third quadrant private data space enabled <--- Third quadrant enable
         third quadrant global data space disabled
# ./mallocmax
Chunk Size MB (1 to 1024): 100
Malloc of 100 Meg succeeded.  Address 00006198.
Malloc of 200 Meg succeeded.  Address 064081B8.
Malloc of 300 Meg succeeded.  Address 0C8081C0.
Malloc of 400 Meg succeeded.  Address 12C081C8.
Malloc of 500 Meg succeeded.  Address 190081D0.
Malloc of 600 Meg succeeded.  Address 1F4081D8.
Malloc of 700 Meg succeeded.  Address 258081E0.
Malloc of 800 Meg succeeded.  Address 2BC081E8.
Malloc of 900 Meg succeeded.  Address 320081F0.
Malloc of 1000 Meg succeeded.  Address 384081F8.
Malloc of 1100 Meg succeeded.  Address 3E808200.
Malloc of 1200 Meg succeeded.  Address 44C08208.
Malloc of 1300 Meg succeeded.  Address 4B008210.
Malloc of 1400 Meg succeeded.  Address 51408218.
Malloc of 1500 Meg succeeded.  Address 57808220.
Malloc of 1600 Meg succeeded.  Address 5DC08228.
Malloc of 1700 Meg succeeded.  Address 64008230.
Malloc of 1800 Meg succeeded.  Address 6A408238.
Malloc of 1900 Meg succeeded.  Address 70808240.
malloc of 2000 Meg failed.
PID = 20689, press <Enter> to continue...

4. With additional quadrants enable and maxdsiz parameter set to 3 GB.

# kctune -s maxdsiz=3221225472
popov: /var/tmp # ./mallocmax
Chunk Size MB (1 to 1024): 100
Malloc of 100 Meg succeeded.  Address 00006198.
Malloc of 200 Meg succeeded.  Address 064081B8.
Malloc of 300 Meg succeeded.  Address 0C8081C0.
Malloc of 400 Meg succeeded.  Address 12C081C8.
Malloc of 500 Meg succeeded.  Address 190081D0.
Malloc of 600 Meg succeeded.  Address 1F4081D8.
Malloc of 700 Meg succeeded.  Address 258081E0.
Malloc of 800 Meg succeeded.  Address 2BC081E8.
Malloc of 900 Meg succeeded.  Address 320081F0.
Malloc of 1000 Meg succeeded.  Address 384081F8.
Malloc of 1100 Meg succeeded.  Address 3E808200.
Malloc of 1200 Meg succeeded.  Address 44C08208.
Malloc of 1300 Meg succeeded.  Address 4B008210.
Malloc of 1400 Meg succeeded.  Address 51408218.
Malloc of 1500 Meg succeeded.  Address 57808220.
Malloc of 1600 Meg succeeded.  Address 5DC08228.
Malloc of 1700 Meg succeeded.  Address 64008230.
Malloc of 1800 Meg succeeded.  Address 6A408238.
Malloc of 1900 Meg succeeded.  Address 70808240.
Malloc of 2000 Meg succeeded.  Address 76C08248.
Malloc of 2100 Meg succeeded.  Address 7D008250.
Malloc of 2200 Meg succeeded.  Address 83408258.
Malloc of 2300 Meg succeeded.  Address 89808260.
Malloc of 2400 Meg succeeded.  Address 8FC08268.
Malloc of 2500 Meg succeeded.  Address 96008270.
Malloc of 2600 Meg succeeded.  Address 9C408278.
Malloc of 2700 Meg succeeded.  Address A2808280.
Malloc of 2800 Meg succeeded.  Address A8C08288.
Malloc of 2900 Meg succeeded.  Address AF008290.
malloc of 3000 Meg failed.
PID = 20841, press <Enter> to continue...

5. Return to original configuration

#  kctune -s maxdsiz=2063835136

6. Within a 64 bit address space. The failure here is product of the swap memory available for reserve.

# cc -Ae +DD64 -o mallocmax mallocmax.c
# ./mallocmax
Chunk Size MB (1 to 1024): 100
Malloc of 100 MB succeeded.  Address 8000000100008268.
Malloc of 200 MB succeeded.  Address 8000000106408278.
Malloc of 300 MB succeeded.  Address 800000010C808288.
Malloc of 400 MB succeeded.  Address 8000000112C08298.
Malloc of 500 MB succeeded.  Address 80000001190082A8.
Malloc of 600 MB succeeded.  Address 800000011F4082B8.
Malloc of 700 MB succeeded.  Address 80000001258082C8.
Malloc of 800 MB succeeded.  Address 800000012BC082D8.
Malloc of 900 MB succeeded.  Address 80000001320082E8.
Malloc of 1000 MB succeeded.  Address 80000001384082F8.
Malloc of 1100 MB succeeded.  Address 800000013E808308.
Malloc of 1200 MB succeeded.  Address 8000000144C08318.
Malloc of 1300 MB succeeded.  Address 800000014B008328.
Malloc of 1400 MB succeeded.  Address 8000000151408338.
Malloc of 1500 MB succeeded.  Address 8000000157808348.
Malloc of 1600 MB succeeded.  Address 800000015DC08358.
Malloc of 1700 MB succeeded.  Address 8000000164008368.
Malloc of 1800 MB succeeded.  Address 800000016A408378.
Malloc of 1900 MB succeeded.  Address 8000000170808388.
Malloc of 2000 MB succeeded.  Address 8000000176C08398.
Malloc of 2100 MB succeeded.  Address 800000017D0083A8.
Malloc of 2200 MB succeeded.  Address 80000001834083B8.
Malloc of 2300 MB succeeded.  Address 80000001898083C8.
Malloc of 2400 MB succeeded.  Address 800000018FC083D8.
Malloc of 2500 MB succeeded.  Address 80000001960083E8.
Malloc of 2600 MB succeeded.  Address 800000019C4083F8.
Malloc of 2700 MB succeeded.  Address 80000001A2808408.
Malloc of 2800 MB succeeded.  Address 80000001A8C08418.
Malloc of 2900 MB succeeded.  Address 80000001AF008428.
Malloc of 3000 MB succeeded.  Address 80000001B5408438.
Malloc of 3100 MB succeeded.  Address 80000001BB808448.
malloc of 3200 Meg failed.
PID = 13476, press <Enter> to continue...

memalloc.c[edit]

The following program compiled for 64 bit platform can show the swap memory allocation of an arbitrary amount of memory.

/*
This program (memalloc.c) request a specific amount of memory using
the malloc system call and can be used to review the system capacity to
reserve an specific amount of memory.

It comes with no support and HP makes no representations as to its
fitness for purpose. It is up to whoever uses this program to ensure
that whatever functionality it provides is what they require.
(c) Wiki-UX.info (2010)

Compile with +DA2.0W or +DD64 to create a 64bit program.
On a 64-bit program, only the kernel parameter maxdsiz_64bit
(and swap) will limit the total malloc allocatable area:

    cc -Ae +DD64 -o memalloc memalloc.c
*/

#include <malloc.h>
#include <stdio.h>
#include <strings.h>
#include <sys/lock.h>

main(int argc, char **argv)
{
  pid_t mypid;
  char *m;
  char bpid[2];
  int i,j,s,chunk;

// Returns Process ID
  mypid = getpid();
  fprintf(stdout, "\nProcess ID = %d\n",mypid);

  printf("Current swap allocation (swapinfo -tam):\n\n");
  system("swapinfo -tam");

// Enables memory lock using plock()
  printf("1. Lock process DATA memory using plock() (y/n)? ");
  scanf("%s", bpid);

  if(!strncmp(bpid, "y", 1)) {
    if(plock(DATLOCK) != 0)
       fprintf(stderr, "Cannot lock DATA process memory!\n");
    else
      printf("Process DATA memory locked.\n");
   }

// Set memory allocation amount
  printf("2. Request memory allocation (MB): ");
  scanf("%d", &s);

  for(i=1; i <= s; i++) {
    chunk=1*1024*1024;
    m=malloc(chunk);
    if(m) {
/* Uncomment next line to display memory allocation progress */
/*        printf("Malloc of %d MBs succeeded.  Address %P. \n",1*i,m); */
    } else {
       for(j=0;j<5;j++) {
          sleep(1);
          if( (m=malloc(chunk)) != 0) break;
       }
       if(m == 0){
          printf("malloc of %d MBs failed.\n",i*1);
          break;
       } else {
    printf("malloc of %d MBs succeeded after %d sec sleep.\n",i*1,j+1);
       }
    }
  }
  printf("\nPost execution swap allocation (swapinfo -tam):\n\n");

  system("swapinfo -tam");

  printf("-- Press Return to complete --\n");
  getchar(); // Bypass the scanf Enter //
  getchar();

// Release process memory lock

  if(!strncmp(bpid, "y", 1)) {
    if(plock(UNLOCK) != 0)
      fprintf(stderr, "Cannot unlock DATA process memory!\n");
    else printf("Process DATA memory unlocked\n");
  }

  return 0;
}

Example[edit]

1. Compile as a 64 bit application.

# cc -Ae +DD64 -o memalloc memalloc.c


2. Execute and Reserve 1024 MB (below the physical swap device usage).

# ./memalloc
Current swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -     283    -283
memory     1946     356    1590   18%
total      3994     639    3355   16%       -       0    -

Request memory allocation (MB): 1024

Post execution swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -    1307   -1307
memory     1946     357    1589   18%
total      3994    1664    2330   42%       -       0    -

PID = 4856, press <Enter> to continue...


3. Execute and Reserve 3048 MB (above the physical swap device, but below available).

# ./memalloc
Current swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -     278    -278
memory     1946     357    1589   18%
total      3994     635    3359   16%       -       0    -

Request memory allocation (MB): 3048

Post execution swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -    2048   -2048
memory     1946    1651     295   85%
total      3994    3699     295   93%       -       0    -

PID = 4906, press <Enter> to continue...


4. Execute and Reserve 4096 MB (fails because exceeds the available virtual memory space).

# ./memalloc
Current swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -     281    -281
memory     1946     358    1588   18%
total      3994     639    3355   16%       -       0    -

Request memory allocation (MB): 4096
malloc of 3339 MBs failed.

Post execution swap allocation (swapinfo -tam):

             Mb      Mb      Mb   PCT  START/      Mb
TYPE      AVAIL    USED    FREE  USED   LIMIT RESERVE  PRI  NAME
dev        2048       0    2048    0%       0       -    1  /dev/vg00/lvol2
reserve       -    2048   -2048
memory     1946    1946       0  100%
total      3994    3994       0  100%       -       0    -

PID = 5044, press <Enter> to continue...

Reference[edit]

Authors[edit]