From: dsiebert@icaen.uiowa.edu (Doug Siebert)
Subject: Re: Shared libraries have me very confused!
Date: Tue, 25 Aug 1992 21:39:25 GMT
Organization: ISCA

In article <7371254@hpfcso.FC.HP.COM> mjs@hpfcso.FC.HP.COM (Marc Sabatella) writes:
>In comp.sys.hp, dsiebert@icaen.uiowa.edu (Doug Siebert) writes:
>
>> I've got an application running on an HP 9000/710 with 48M of RAM under HP-UX
>> 8.07 that is run by up to 80 users at a time (and adding more would always be
>> an advantage) each running a separate copy of the application.
>
>When you say "running a separate copy", do you literally mean a separate copy
>of the executable file?  If so, step one is to make sure everyone runs the same
>copy of the application, so you can shared text.

No, I meant each runs in a separate process.  They are all run from the same
i-node (except at times when the software is updated and there is a transition
period during which two copies are running, but that's not a major concern I
don't think)

>> I recompiled
>> again, this time with the option "-Wl,-a,archive" to the linker, which should
>> use the archive libraries instead of the shared libraries.  I figured I would
>> be using up more real memory by not using the shared libraries, but am in fact
>> using less!  How can this be?!
>
>How did you measure real memory usage?  I don't think any of the available
>tools like "ps", "monitor", "glance", or anything using "pstat" are
>particularly smart about shared libraries.  I can easily imagine that they
>would think each instantiation of the program was using its own copy of the
>library.

I used 'monitor' to get this information.  I went by what it told me both by
analyzing processes individually and giving me their RSS size, and by the
global statistics giving the overall amount of memory usage.  With 75 users
I would dig into the first couple megabytes of swap space, though beforehand
none was used.  I assume this means that at that point physical memory has
been exhausted and inactive pages are being swapped out.  At some point pages
that are just *less* active will be swapped out, and then I'll see performance
decrease, correct?

>If you are counting swap space, then you should *not* expect to see usage go
>down with shared libraries.  Swap is never used for text segments (it is paged
>in directly from the filesystem), so only data is an issue.  With archive
>libraries, a program will have swap reserved/allocated for all the data in the
>program, plus all the data copied out of archives libraries.  A typical Motif
>program accesses only 60% (or some other relatviely small amount) of the data
>in the libraries it is linked with, so only that amount of data is copied into
>the program.  With shared libraries, however, you are allocated swap for all
>the data in all the libraries you are linked with.  Plus, you are allocated
>swap for the data structures used by the dynamic loader.  Thus, a program
>typically needs more swap space when linked with shared libraries than archive
>libraries.  This does not mean it needs more real memory, however - most of
>the swap is allocated "just in case", but still only those pages that are used
>are allocated in memory, so a given process would use almost exactly the same
>amount of memory with shared as archive libraries.  Possibly a little more due
>to fragmentation of the data it is using (the 60% of the data it uses from a
>library may be scattered over 80% of the library's pages).
>
>> 1)  How come NOT using shared libraries allowed my application to use up less
>> real memory per process?  If this is so, what is the point of shared libraries?
>
>Possibility number one is that the program really isn't using less real memory
>with archive libraries - the tools that report memory usage may be flawed, or
>you may have been measuring the wrong thing (swap space).  As I observed above,
>any given process will appear to need slightly more (due to fragmentation, and
>dynamic loader overhead) real memory with shared libraries than with archive
>libraries.  The savings comes as soon as there is sharing - memory pages used
>for library text can be shared processes.  But note that program text is shared
>anyhow.  If your program is linked against libfoobar, and it is the only
>program linked against libfoobar, then its text pages will be shared among all
>users regardless of whether it is a shared library or not.  The shared library
>is only a win if some other program is also linked against libfoobar - then
>the pages will be shared among all users of both programs, rather than having
>one set of pages for users of one program and another set for users of the
>other.
>
>To recap, you should expect any individual process to need significantly more
>swap when using shared libraries, and slightly more memory.  If you have
>several invocations of the same program at once (as you do), this only
>magnifies those differences.  The savings come when you also have *other*
>programs that use the same libraries.

OK, I think I understand what I was missing about shared libraries.  Since this
application is the major usage of this machine, and I'm not really concerned if
it is a couple hundred K larger in size, I should compile with the archive
libraries instead of the shared libraries, to avoid the overheard of swap, real
memory, and speed associated with shared libraries, which are intended to save
disk space over the many applications over the whole system.

>> 2)  How can I compile my application so as to make it share memory better among
>> the 80 copies of it that may be simultaneously running?  Is there something
>> big I'm missing?  Or would I have to tear it apart and put most of its
>> functions in a library of my own creation?  (And would I then want to make that
>> shareable or not?)
>
>Assuming the application really is shared - all 80 users are running from the
>same i-node, I think you've done all you can.  If you're wondering just how
>much difference the libraries are making, try the following experiment:
>
>1. link your application normally, with something that presumably looks like:
>
>	cc -o program.shared $(OBJS) $(LIBS)

107889 + 1852 + 18964 = 128705

>2. link it with archive libraries:
>
>	cc -o program.archive $(OBJS) -Wl,-a,archive $(LIBS)

191028 + 12220 + 43712 = 246960

>3. link it with no libraries (result will not be executable):
>
>	cc -o program.none $(OBJS)

105692 + 1524 + 15468 = 122684

>Now run "size" on each of the resultant executables, and compare.  #2 and #3
>should be similar - #2 should be slightly larger due to shared library
>overhead.  #1 should be larger.  If it is "a lot" larger, it means you are
>using a lot of library code, and any tuning should indeed be in your use of
>libraries.  If is "only a little" larger, then most of the memory you are using
>is in your application code, and the libraries don't really make much
>difference.

I'm guessing you mistyped and meant #1 and #3 should be similar, since #2 has
the extra overheard of *not* using shared libraries.  But #2 does take up less
memory, according to monitor (though you say that may be flawed)  The only
library other than libc I am using is the curses/termcap library, so there is
not much tuning I can do in that respect.  I do use the -DMINICURSES option
when compiling/linking, so I guess I'm cutting that library down as much as
possible as it is.

Thanks for your help!


-- 
/-----------------------------------------------------------------------------\
| Doug Siebert                             | "I don't have to take this abuse |
| Internet:  dsiebert@icaen.uiowa.edu      |  from you - I've got hundreds of |
| NeXTMail:  dsiebert@chop.isca.uiowa.edu  |  people waiting in line to abuse |
|     ICBM:  41d 39m 55s N, 91d 30m 43s W  |  me!"  Bill Murray, Ghostbusters |
\-----------------------------------------------------------------------------/
Hi, I'm a .signature worm.  I've already copied myself into your .signature.