------- Additional Comments From sgk at troutmask dot apl dot washington dot 
edu  2005-05-30 16:20 -------
Subject: Re:  Really, really, horrible IO performance

On Mon, May 30, 2005 at 03:20:18PM -0000, pinskia at gcc dot gnu dot org wrote:
> 
> I see the same thing on powerpc-darwin but it seems like on freebsd,
> it is actually paging in the memory which seems wrong, I almost want
> to say you should report it to freebsd as their performance bug
> (Yes working around in libgfortran is still a good idea).

It appears to be a faulty assumption in how gfortran uses mmap.
gfortran appears to assume Linux's behavior:

   (From some version of Redhat)
   MAP_SHARED   Share this mapping with all other processes that map this
                object.  Storing to the region is equivalent to writing to
                the file.  The file may not actually be updated until
                msync(2) or munmap(2) are called.

   (From FreeBSD)
   MAP_SHARED   Modifications are shared.

   MAP_NOSYNC   Causes data dirtied via this VM map to be flushed to
                physical media only when necessary (usually by the
                pager) rather than gratuitously.  Typically this pre-
                vents the update daemons from flushing pages dirtied
                through such maps and thus allows efficient sharing of
                memory across unassociated processes using a file-
                backed shared memory map.  (Much snipped, including a
                big warning about ftruncate extending a file).

   (From http://www.opengroup.org/onlinepubs/7990989775/xsh/mmap.html)
   If MAP_SHARED is specified, write references change the underlying object. 

It appears that Linux's MAP_SHARED is equivalent to FreeBSD's
(MAP_SHARED | MAP_NOSYNC).  NetBSD and OpenBSD man pages do not
have the MAP_NOSYNC flag, so they may not be affected.  Note 
POSIX doesn't state anything about when and how the underlying object 
is updated.  POSIX also doesn't include a MAP_NOSYNC flag.

I've verified that the following patch works and improves
performance, but I prefer the original O_TRUNC patch because
O_TRUNC is a POSIX flag and AFAIK most OS's implement it.

Index: unix.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/unix.c,v
retrieving revision 1.26
diff -c -p -r1.26 unix.c
*** unix.c      17 May 2005 16:54:51 -0000      1.26
--- unix.c      30 May 2005 16:06:54 -0000
*************** mmap_alloc (unix_stream * s, gfc_offset 
*** 622,628 ****
  
    length = ((where - offset) & page_mask) + 2 * page_size;
  
!   p = mmap (NULL, length, s->prot, MAP_SHARED, s->fd, offset);
    if (p == (char *) MAP_FAILED)
      return FAILURE;
  
--- 622,628 ----
  
    length = ((where - offset) & page_mask) + 2 * page_size;
  
!   p = mmap (NULL, length, s->prot, MAP_SHARED | MAP_NOSYNC, s->fd, offset);
    if (p == (char *) MAP_FAILED)
      return FAILURE;




-- 


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=21820

Reply via email to