At the end of March 2004, davidw pointed out that mono and Gtk# used a lot of memory for simple applications: in his mail he had 42196 KB of VSIZE and 11096 KB of RSS for a button in a window. Of course this was not good and at the time I told him to check again at the time of the mono 1.0 release or thereabouts and indeed we had some improvements: at the beginning of July the numbers were 31776 KB and 9916 KB respectively for VSIZE and RSS. The changes involved both the way Gtk# was built and the way mono loaded metadata information and how that was stored in the runtime data structures.
Today I ran the same test again to see what is the status, since we're going to release mono 1.2 in a few weeks/months. The numbers look better: 18912 KB for VSIZE and 8200 KB for RSS. These numbers are comparable to the existing perl and python bindings (17032/10028 the former, 15092/9164 the latter).
For reference, on my system the equivalent C program gives: 10568 KB for VSIZE and 4728 KB for RSS. The aumount of writable mapped memory is what counts, though, so I got some data about that, too, with a small program looking at /proc/pid/maps. The C program has about 935 KB of writable memory mapped, 290 KB of which is what looks like the relocation overhead in the numerous shared libraries loaded. Since memory is mmapped in page-sized chunks, even if a library has only a couple of relocations, it will make a whole page dirty. Ulrich Drepper has a paper on how to make shared libraries behave better that is a worthy read, but in some cases there isn't much we can do if we want to support plugin-like systems.
A very amusingly sad fact is to be noted about the libgmodule library: this is a very tiny lib (9 KB of text size). So, to be able to share 9 KB of readonly data, we waste 4 KB of writable data. Maybe it makes sense to just include the gmodule code inside the standard libglib library. libdl has a similar issue (7 KB of text, note that the wrapper library is bigger than the wrapped one, sigh): maybe some linker magic could be used to include libdl inside libc, it would increase the size of the latter by just 0.5%.
In the mono/Gtk# case, the writable memory mapped was 4.35 MBs. Of these, 1 MB is the stack setup for the thread that runs the finalizers: hardly a few KBs of this memory is ever touched, so the kernel doesn't actually commit this amount of data. There is another megabyte that consists of shared mappings from files, which is used by the io-layer to implement the win32 handle semantics. Usually, very little of this memory should be actually read or written, so it shouldn't matter much and the io-layer rewrite Dick is working on will hopefully get rid of most of the usage, too. If we subtract the amount of memory used by the C program itself, we get that the memory actually allocated by mono/gtk# is about 1.3 MBs, in the perl and the python case it's about 2.5 MBs. The 1.3 MBs include about 200 KB of GC heap size, 128 KB of memory allocated for the jitted code (of which just 20-30 KB are used) and the memory used by the mono runtime data structures: metadata from the IL images, jit bookkeeping etc. Of course we plan to reduce our memory requirements even further, since this is good both for the people using mono in embedded solutions and for the people using multiple mono desktop applications. Hopefully in another six months time we'll have as good improvements as we had in the last year:-)