[rrd-developers] Use of madvise / msync kills performance for me

Marcus Reid marcus at blazingdot.com
Wed Jun 25 23:46:46 CEST 2008


Hello,

I'm using py-rrdtool 0.2.1 and rrdtool 1.3.0 under FreeBSD 7.0-STABLE,
and for me madvise and msync really hurts performance.  There might be
a more efficient way of doing things, but for every update the .rrd
file is opened, mapped into memory, written to, and then closed.  Here
is a kdump of an update before commenting out the madvise/msync
code:

   65074 python   0.000009 CALL  open(0x831a1b4,O_RDWR,<unused>0)
   65074 python   0.000013 NAMI  "rg2.rrd"
   65074 python   0.000024 RET   open 7
   65074 python   0.000007 CALL  fstat(0x7,0xbfbfe428)
   65074 python   0.000011 RET   fstat 0
   65074 python   0.000008 CALL  mmap(0,0x453b7618,PROT_READ|PROT_WRITE,MAP_SHARED,0x7,0,0)
   65074 python   0.000018 RET   mmap 679235584/0x287c5000
   65074 python   0.000007 CALL  madvise(0x287c5000,0x453b7618,_MADV_RANDOM)
   65074 python   0.000008 RET   madvise 0
   65074 python   0.000006 CALL  madvise(0x287c5000,0x70,_MADV_WILLNEED)
   65074 python   0.027455 RET   madvise 0
   65074 python   0.000058 CALL  madvise(0x287c5000,0x1c20,_MADV_WILLNEED)
   65074 python   0.016904 RET   madvise 0
   65074 python   0.000179 CALL  madvise(0x287c6000,0x1950,_MADV_WILLNEED)
   65074 python   0.008629 RET   madvise 0
   65074 python   0.000040 CALL  madvise(0x287c8000,0x8,_MADV_WILLNEED)
   65074 python   0.004173 RET   madvise 0
   65074 python   0.000048 CALL  gettimeofday(0xbfbfe554,0)
   65074 python   0.000009 RET   gettimeofday 0
   65074 python   0.000012 CALL  fcntl(0x7,<invalid=12>,0xbfbfe478)
   65074 python   0.000024 RET   fcntl 0
   65074 python   0.006084 CALL  msync(0x287c5000,0x453b7618,MS_ASYNC)
   65074 python   0.106284 RET   msync 0
   65074 python   0.000483 CALL  munmap(0x287c5000,0x453b7618)
   65074 python   0.000356 RET   munmap 0
   65074 python   0.000012 CALL  close(0x7)
   65074 python   0.000046 RET   close 0
   65074 python   0.000173 CALL  __sysctl(0xbfbfe388,0x2,0xbfbfe394,0xbfbfe398,0,0)
   65074 python   0.000016 RET   __sysctl 0

The third column is seconds elapsed relative to last call.

Here's the same thing after applying the following diff to rrd_open.c .  For
some reason there's still some madvise calls going on, but not quite the same
and it takes less time.  Note the absence of the tenth of a second taken up
by msync().

   96372 python   0.000011 CALL  open(0x831aa34,O_RDWR,<unused>0)
   96372 python   0.000016 NAMI  "rg2.rrd"
   96372 python   0.000025 RET   open 7
   96372 python   0.000009 CALL  fstat(0x7,0xbfbfe428)
   96372 python   0.000014 RET   fstat 0
   96372 python   0.000010 CALL  mmap(0,0x453b7618,PROT_READ|PROT_WRITE,MAP_SHARED,0x7,0,0)
   96372 python   0.000021 RET   mmap 679235584/0x287c5000
   96372 python   0.000101 CALL  madvise(0x287c5000,0x1c20,_MADV_WILLNEED)
   96372 python   0.000013 RET   madvise 0
   96372 python   0.000010 CALL  madvise(0x287c6000,0x1950,_MADV_WILLNEED)
   96372 python   0.000010 RET   madvise 0
   96372 python   0.000009 CALL  madvise(0x287c8000,0x8,_MADV_WILLNEED)
   96372 python   0.000009 RET   madvise 0
   96372 python   0.000010 CALL  gettimeofday(0xbfbfe554,0)
   96372 python   0.000009 RET   gettimeofday 0
   96372 python   0.000011 CALL  fcntl(0x7,<invalid=12>,0xbfbfe478)
   96372 python   0.000016 RET   fcntl 0
   96372 python   0.002024 CALL  munmap(0x287c5000,0x453b7618)
   96372 python   0.000366 RET   munmap 0
   96372 python   0.000016 CALL  close(0x7)
   96372 python   0.000046 RET   close 0
   96372 python   0.000108 CALL  __sysctl(0xbfbfe388,0x2,0xbfbfe394,0xbfbfe398,0,0)
   96372 python   0.000017 RET   __sysctl 0

The rate of updates fluctuates a bit, but the OS seems to do a much better
job of managing the IO without interference.

Marcus


*** src/rrd_open.c.orig Tue Jun 10 23:12:55 2008
--- src/rrd_open.c      Wed Jun 25 21:43:54 2008
***************
*** 175,191 ****
  #endif
      if (rdwr & RRD_CREAT)
          goto out_done;
- #ifdef USE_MADVISE
-     if (rdwr & RRD_COPY) {
-         /* We will read everything in a moment (copying) */
-         madvise(data, rrd_file->file_len, MADV_WILLNEED | MADV_SEQUENTIAL);
-     } else {
-         /* We do not need to read anything in for the moment */
-         madvise(data, rrd_file->file_len, MADV_RANDOM);
-         /* the stat_head will be needed soonish, so hint accordingly */
-         madvise(data, sizeof(stat_head_t), MADV_WILLNEED | MADV_RANDOM);
-     }
- #endif
  
      __rrd_read(rrd->stat_head, stat_head_t,
                 1);
--- 175,180 ----
***************
*** 388,396 ****
      int       ret;
  
  #ifdef HAVE_MMAP
-     ret = msync(rrd_file->file_start, rrd_file->file_len, MS_ASYNC);
-     if (ret != 0)
-         rrd_set_error("msync rrd_file: %s", rrd_strerror(errno));
      ret = munmap(rrd_file->file_start, rrd_file->file_len);
      if (ret != 0)
          rrd_set_error("munmap rrd_file: %s", rrd_strerror(errno));
--- 377,382 ----



More information about the rrd-developers mailing list