NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

ulimit -d/-m do not actually work



I suspect that "ulimit -d" does not work correctly, so I wrote a test
program, which simply allocates 4K chunks and writes an int into each.
It keeps a count, and prints the amount it was able to allocate in kB.

(Yes, I know there's malloc overhead and other things; the point is just
to see if limits are working at get a feeling for the malloc overhead
and other data, to sanity check using limits in a program that's too
complicated to understand 100% reliably.)

The tests below are on reasonably recent netbsd-10 amd64, that has 32G
of RAM.

I limited the test program to 4GB (to avoid provoking unrelated zfs
locking bugs I've written about before).

Running it with my default limits:

  number of threads                   (-T) 8192
  socket buffer size           (bytes, -b) unlimited
  core file size              (blocks, -c) unlimited
  data seg size               (kbytes, -d) 8388608
  file size                   (blocks, -f) unlimited
  max locked memory           (kbytes, -l) 10740156
  max memory size             (kbytes, -m) 32220468
  open files                          (-n) 20000
  pipe size                (512 bytes, -p) 1
  stack size                  (kbytes, -s) 4096
  cpu time                   (seconds, -t) unlimited
  max user processes                  (-u) 1044
  virtual memory              (kbytes, -v) unlimited

got me

  4194304

I didn't want to mess up my shell's limits, so I started a new /bin/sh,
and reduced the data limit to 1024 and the memory limit to 1024.  The
unit is kB, so this is a mere 1MB of memory.  Which is plenty to run the
test program:

   text    data     bss     dec     hex filename
   2600     578      72    3250     cb2 test-data

But, I still can allocate 4GB:

  $ ulimit -a
  time          (-t seconds    )    unlimited
  file          (-f blocks     )    unlimited
  data          (-d kbytes     )      8388608
  stack         (-s kbytes     )         4096
  coredump      (-c blocks     )    unlimited
  memory        (-m kbytes     )     32220468
  locked memory (-l kbytes     )     10740156
  thread        (-r threads    )         8192
  process       (-p processes  )         1044
  nofiles       (-n descriptors)        20000
  vmemory       (-v kbytes     )    unlimited
  sbsize        (-b bytes      )    unlimited
  $ ulimit -d 1024
  $ ulimit -a 
  time          (-t seconds    )    unlimited
  file          (-f blocks     )    unlimited
  data          (-d kbytes     )         1024
  stack         (-s kbytes     )         4096
  coredump      (-c blocks     )    unlimited
  memory        (-m kbytes     )     32220468
  locked memory (-l kbytes     )     10740156
  thread        (-r threads    )         8192
  process       (-p processes  )         1044
  nofiles       (-n descriptors)        20000
  vmemory       (-v kbytes     )    unlimited
  sbsize        (-b bytes      )    unlimited
  $ ./test-data
  4194304
  $ ulimit -m 1024
  $ ulimit -a
  time          (-t seconds    )    unlimited
  file          (-f blocks     )    unlimited
  data          (-d kbytes     )         1024
  stack         (-s kbytes     )         4096
  coredump      (-c blocks     )    unlimited
  memory        (-m kbytes     )         1024
  locked memory (-l kbytes     )     10740156
  thread        (-r threads    )         8192
  process       (-p processes  )         1044
  nofiles       (-n descriptors)        20000
  vmemory       (-v kbytes     )    unlimited
  sbsize        (-b bytes      )    unlimited
  $ ./test-data
  4194304

Questioning my program, I ran top in another window and saw "4067M" in
the RSS column.

Yet in that shell in that state, "unison" fails:

    $ unison
    sh: unison: not enough memory

So it seems NetBSD won't exec a process that would exceed the limit at
exec time, but malloc is able to obtain virtual memory (which is backed
by actual memory) that is not constrained.

background (skippable):

  I am trying to test unison (a file sync tool), to find out how much
  memory it needs for various workloads.  I wrote a script to set limits
  via ulimit(1), both data and stack, sticking to POSIX, and invoked
  unison.  I then did binary search manually, to find the smallest
  limits that worked.

  For stack, it was 88, 100, and 212, for 10000, 20000, and 40000 files.
  That wasn't really surprising.

  For data, it was 1376.  That's kB, and it didn't seem remarkable.
  But, it was the same for varying workloads.


----------------------------------------
/*
 * test-data.c: Test data size limit. 
 * Allocate memory until failure.
 * Print amount allocated.
 */

#include <stdio.h>
#include <stdlib.h>

#define BUFSIZK	4

int
main(int argc, char **argv)
{
  int i;
  int *buf;

  /*
   * Limit to 4 GB, to avoid problems if data segment limits are not
   * working as expected.
   */
  for (i = 0; i < (4 * 1024 * 1024) / BUFSIZK; i++) {
    /* Allocate, write to force a page, and discard. */
    buf = malloc(BUFSIZK * 1024);
    if (buf == NULL)
      break;
    buf[0] = 0;
    buf = NULL;
  }

  /* Print in kB. */
  printf("%d\n", i * BUFSIZK);
}


Home | Main Index | Thread Index | Old Index