lua-users home
lua-l archive

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


It was thus said that the Great William Ahern once stated:
> 
> I think the issue with C's heritage is overblown, especially considering
> that modern compilers support pre-compiled headers. The data structure
> definitions that must be parsed from header files would also have to be
> parsed and loaded from binary formats, and the speed benefits aren't really
> that astounding. I think the greater problem is the practice of people
> having dozens or even hundreds of compilation units. In many projects every
> little C or C++ file has like 2 or 3 functions defined. Far fewer people do
> stupid stuff like that in Java, C#, or other languages.

  I've been playing around with linking recently.  For an experiment, I took
a program I wrote [1], and a library it uses [2], placed all the code into
one large file, and compiled it.  It made some difference in the executable
size (a bit smaller).  Knowing that some compilers will inline static
functions, the second experiment I marked every function as static (except
for main(), which had to remain globally visible).  

  First off, there were quite a few functions that were not used (mostly
from the library), and second, a larger number of functions simply
disappeared as they were inlined.  I think I counted something like 25
functions were either no used, or inlined.  And the executable size was a
bit more noticeable this time.

  Now, I know that when code is compiled into a library, only the bits that
are actually referenced are included into the final executable, but I found
out there's a bit more to it than that.  For the library in question, it
contains the following:

   text    data     bss     dec     hex filename
   1197       0       0    1197     4ad nodelist.o (ex libcgi6.a)
   1659       0       0    1659     67b util.o (ex libcgi6.a)
   1536       0       0    1536     600 pair.o (ex libcgi6.a)
   4136       0       0    4136    1028 cgi.o (ex libcgi6.a)
   1636       0       0    1636     664 rfc822.o (ex libcgi6.a)
   4326       0       0    4326    10e6 htmltok.o (ex libcgi6.a)
    812       0       0     812     32c mail.o (ex libcgi6.a)
   1736       0       0    1736     6c8 chunk.o (ex libcgi6.a)
    341       0       0     341     155 bisearch.o (ex libcgi6.a)
   4235       0    8736   12971    32ab crashreport.o (ex libcgi6.a)
   1484       0       0    1484     5cc url.url.o (ex libcgi6.a)
   2050       0       0    2050     802 url.http.o (ex libcgi6.a)
    909       0       0     909     38d url.file.o (ex libcgi6.a)

  Now, if I were to use RFC822HeadersRead() (from rfc822.o), not only it
include the object code for RFC822LineRead() (since RFC822HeadersRead() uses
that), but also two other functions I don't use.  What's happening is that
the linker [3] is including all of rfc822.o even though I don't use all of
it.  To ensure that the exectable only includes those functions used out of
a library, you have to basically put each public routine in its own object
file, which could explain the "lots of small files" you might see in C or
C++.

  -spc

[1]	https://github.com/spc476/mod_blog

[2]	https://github.com/spc476/CGILib

[3]	I'm using an older GCC development chain.  It is possible that what
	I'm describing has changed since the version I'm using was written.