bug-binutils
[Top][All Lists]
Advanced

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

[Bug gas/15295] New: gas rebuffer_line() routine (listing.c) issues exce


From: jtison at us dot ibm.com
Subject: [Bug gas/15295] New: gas rebuffer_line() routine (listing.c) issues excessive read syscalls
Date: Fri, 22 Mar 2013 13:44:46 +0000

http://sourceware.org/bugzilla/show_bug.cgi?id=15295

             Bug #: 15295
           Summary: gas rebuffer_line() routine (listing.c) issues
                    excessive read syscalls
           Product: binutils
           Version: 2.20
            Status: NEW
          Severity: normal
          Priority: P2
         Component: gas
        AssignedTo: address@hidden
        ReportedBy: address@hidden
    Classification: Unclassified


Created attachment 6939
  --> http://sourceware.org/bugzilla/attachment.cgi?id=6939
1.7 MiB of GPL C code that produces 460 KLOC of assembler.

A monolithic C program, attached, when compiled at -O2 and stopped at the
assembler output phase (-S), produces a monolithic assembler source file. No
surprises. --host==--build==--target=s390-ibm-linux

as-2.19 combines the assembler and C listings using about 1500 read syscalls.
The assembler code I used was obtained with:
  gcc -S -g -O2 -o offldr.s offldr.i

as-2.20 appears to have refactored most of listing.c. The rebuffer_line()
function issues an ftell() to see what its last position was, then immediately
issues an fseek(0,SEEK_SET) and re-reads all of the current file (C source is
the most painful) from its very beginning. as-2.20 uses a little over a million
read syscalls to achieve the same goal that 2.19 accomplished in less than 1500
syscalls. fd 5 appears to be reused for both the assembler source and the C
language source & header files; whenever the use of the fd changes, each file
is read from offset zero instead of its last known position.

I tried a fast patch (see below) to as-2.20 to change what I thought the
offensive behavior was, and managed to reduce the read syscalls to around
27,000; but the HLL and assembly now seem out of sync. I have to confess I'm
not familiar with this code and I might have missed something important, or
maybe there's a better way to correct this behavior. I've sent it along only as
a suggestion of what might need correction.

Times and strace summaries look like this: 
time as-2.19 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s

real    0m2.071s
user    0m1.606s
sys    0m0.142s

strace -c as-2.19 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 55.44    0.029016          22      1333           write
 19.98    0.010457           7      1490           read
 12.82    0.006711          13       498       195 open
  3.75    0.001963           7       300           munmap
  1.62    0.000849         849         1           unlink
  1.58    0.000828           2       388           brk
  1.31    0.000683           2       322           mmap
  1.03    0.000537           2       303           close
  0.81    0.000423           2       192       189 stat
  0.48    0.000249           1       303           fstat
  0.45    0.000235         235         1           execve
  0.44    0.000231           1       312           lseek
  0.20    0.000106          27         4           fadvise64
  0.08    0.000042           7         6           mprotect
  0.01    0.000004           4         1         1 access
  0.00    0.000001           1         1           getrusage
  0.00    0.000001           1         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00    0.052336                  5456       385 total

time as-2.20 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s

real    4m34.289s
user    4m27.146s
sys    0m3.857s

strace -c as-2.20 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 87.56    3.093972           3   1020659           read
  3.44    0.121514           9     13246           munmap
  3.25    0.114720           9     13316        67 open
  1.95    0.068848          43      1599           write
  1.80    0.063709           5     13249           close
  0.98    0.034803           3     13267           mmap
  0.58    0.020548           1     26204           lseek
  0.37    0.012923           1     13249           fstat
  0.02    0.000794           2       388           brk
  0.02    0.000703         176         4           fadvise64
  0.01    0.000505         505         1           unlink
  0.01    0.000235         235         1           execve
  0.01    0.000206           3        64        63 stat
  0.00    0.000047           8         6           mprotect
  0.00    0.000006           6         1         1 access
  0.00    0.000002           1         2           fcntl
  0.00    0.000001           1         1           getrusage
  0.00    0.000001           1         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00    3.533537               1115258       131 total

(as-2.20-1 is patched like so, I'm sure there is something wrong with it, a fix
like this cannot be this simple:)
/////////////////////////////  cut here ///////////////////////////////////
--- binutils-2.20.1/gas/listing.c.old    2010-01-14 05:48:31.000000000 -0500
+++ binutils-2.20.1/gas/listing.c    2013-03-18 14:35:22.000000000 -0400
@@ -544,7 +544,6 @@ rebuffer_line (file_info_type *  file,
            unsigned int      size)
 {
   unsigned int count = 0;
-  unsigned int current_line = 1;
   char * p = buffer;
   long pos;
   int c;
@@ -577,14 +576,8 @@ rebuffer_line (file_info_type *  file,
     fseek (last_open_file, file->pos, SEEK_SET);
     }

-  /* Remember where we are in the current file.  */
-  pos = ftell (last_open_file);
-
-  /* Go back to the beginning.  */
-  fseek (last_open_file, 0, SEEK_SET);
-
   /* Skip lines prior to the one we are interested in.  */
-   while (current_line < linenum)
+  while (file->linenum < linenum)
     {
       /* fgets only stops on newlines and has a size limit,
      so we read one character at a time instead.  */
@@ -594,7 +587,7 @@ rebuffer_line (file_info_type *  file,
     }
       while (c != EOF && c != '\n' && c != '\r');

-      ++ current_line;
+      ++ file->linenum;

       if (c == '\r' || c == '\n')
     {
///////////////////////////////////////////////////////////////////
I must confess to not knowing what I'm doing inside listing.c, I am merely
taking a stab at what I think some of the more egregious calls might be. I
leave the final solution to you, this patch is not a suggested fix. If at all
possible, could we pick up reading the last user of fd 5 perhaps a few bytes
behind its last used position?

Here's how this patched code runs:

time as-2.20-1 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s

real    0m3.045s
user    0m2.396s
sys    0m0.422s

strace -c as-2.20-1 -o offldr.o2.o -alshd=offldr.o2.lst offldr.o2.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 33.32    0.169969           6     26781           read
 18.35    0.093618           7     13136        67 open
 17.72    0.090398           7     13066           munmap
 10.11    0.051572          33      1547           write
  7.10    0.036214           3     13069           close
  6.77    0.034531           3     13087           mmap
  3.46    0.017665           1     19489      6405 lseek
  2.65    0.013509           1     13069           fstat
  0.25    0.001268           3       388           brk
  0.15    0.000782         782         1           unlink
  0.06    0.000305         305         1           execve
  0.04    0.000204           3        64        63 stat
  0.01    0.000042          11         4           fadvise64
  0.01    0.000037           6         6           mprotect
  0.00    0.000005           5         1         1 access
  0.00    0.000003           2         2           fcntl
  0.00    0.000001           1         1           getrusage
  0.00    0.000001           1         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00    0.510124                113713      6536 total

This PR goes with an e-mail I sent to the bug-binutils mailing list the day
before yesterday.

I talked with IBM Legal yesterday about shipping out our licensed code as a
test case. They denied me permission to do so. Instead, as a test case, I found
an even larger GPL program that displays even greater contrasts: oggenc.c (Ogg
Vorbis encoding) which is licensed under GPL v2. You should have no trouble
seeing the read syscalls nor the effects on assembly time.

To create your test case on a native s390x-ibm-linux gcc compiler equipped with
binutils-2.21, do this: 
   gcc -O2 -S -g -o oggenc.s oggenc.c
   as -o oggenc.o -alshd=oggenc.lst oggenc.s # Make sure you get a listing!

Here's what I see for timings & strace summaries with all three assemblers:

time as-2.19 -o oggenc.o -alshd=oggenc.lst oggenc.s

real    0m7.311s
user    0m6.924s
sys    0m0.359s

time as-2.20 -o oggenc.o -alshd=oggenc.lst oggenc.s

real    13m24.879s
user    13m8.837s
sys    0m9.649s

time as-2.20-1 -o oggenc.o -alshd=oggenc.lst oggenc.s

real    0m11.241s
user    0m8.960s
sys    0m0.700s

strace -c as-2.19 -o oggenc.o -alshd=oggenc.lst oggenc.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 69.24    0.120428          22      5478           write
 11.94    0.020768           8      2653           read
 10.39    0.018070          34       533       262 open
  2.30    0.004003        1001         4           fadvise64
  1.54    0.002672        2672         1           unlink
  1.46    0.002538           2      1292           brk
  1.13    0.001958           7       270           munmap
  0.61    0.001060           4       256       252 stat
  0.41    0.000715           2       292           mmap
  0.30    0.000524           2       271           close
  0.30    0.000516         516         1           execve
  0.14    0.000244           1       271           fstat
  0.14    0.000236          39         6           mprotect
  0.11    0.000193           1       280           lseek
  0.00    0.000008           8         1         1 access
  0.00    0.000002           2         1           getrusage
  0.00    0.000001           1         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00    0.173936                 11611       515 total

strace -c as-2.20 -o oggenc.o -alshd=oggenc.lst oggenc.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 94.00   14.906169           5   2757563           read
  1.45    0.229871          12     18646           munmap
  1.15    0.181850          32      5692           write
  1.09    0.172328           9     18846       199 open
  0.70    0.110274           6     18647           close
  0.66    0.104281           3     37032           lseek
  0.54    0.086084           5     18667           mmap
  0.35    0.055968           3     18647           fstat
  0.03    0.005022           4      1292           brk
  0.02    0.003031        3031         1           unlink
  0.01    0.001359           7       192       189 stat
  0.00    0.000668         668         1           execve
  0.00    0.000050          13         4           fadvise64
  0.00    0.000037           6         6           mprotect
  0.00    0.000008           8         1         1 access
  0.00    0.000006           3         2           fcntl
  0.00    0.000004           4         1           getrusage
  0.00    0.000004           4         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00   15.857014               2895241       389 total

2.75 MM read syscalls!!

strace -c as-2.20-1 -o oggenc.o -alshd=oggenc.lst oggenc.s
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 33.59    0.195420           5     38180           read
 21.15    0.123062          22      5684           write
 14.83    0.086272           5     18198           munmap
 12.64    0.073509           4     18398       199 open
  6.05    0.035180           2     18219           mmap
  4.70    0.027358           2     18199           close
  3.24    0.018825           1     27208      8934 lseek
  2.53    0.014738           1     18199           fstat
  0.50    0.002934        2934         1           unlink
  0.42    0.002448           2      1292           brk
  0.17    0.000990           5       192       189 stat
  0.13    0.000775         775         1           execve
  0.04    0.000226          57         4           fadvise64
  0.00    0.000029           5         6           mprotect
  0.00    0.000007           7         1         1 access
  0.00    0.000003           2         2           fcntl
  0.00    0.000002           2         1           getrusage
  0.00    0.000001           1         1           lstat
------ ----------- ----------- --------- --------- ----------------
100.00    0.581779                163786      9323 total

If there is any more information you need, please don't hesitate to contact me.
Thanks.

-- 
Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are on the CC list for the bug.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]