[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-core-devel
Subject: Memory Usage in KDE (LONG)
From: Waldo Bastian <bastian () suse ! de>
Date: 1999-10-18 12:50:24
[Download RAW message or body]
Hiya,
I would like to start this mail with my apologies to Stephan Kulow.
When he said at KDE-Two that each KDE application needs at least
800Kb, I accused him of looking at the wrong numbers. Unfortunately I
was wrong. My apologies for that.
This weekend I have been measuring the memroy usage of KDE applications
because I wanted to check the memory usage of mmaps within KSycoca. For
this measurement I have used a current (18-10-99) snapshot of the CVS
HEAD. The compiler used is
"gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)".
I have added to kdelibs/kdetest the program 'kmemtest' which you can
use to verify my measurements. With this program I have been measuring
two things.
1) I have been measuring the memory usage according to the
"Data" entry in /proc/<PID>/status. This is an accurate
representation of the amount of memory your process allocates with
'malloc' and 'new' and which gets actually used.
2) I have been measuring the impact of launching an additional
instance of an application on the total memory usage of my system.
I have measured the total memory usage of my system according to
the "memory used without buffers and without cache" entry
of the "free" utility. This information can also be obtained from
/proc/meminfo by taking the "Mem:/used:" entry and subtracting both
"Mem:/buffers:" and "Mem:/cached:".
I have compared the total memory usage when a single applications is
running 5 times with the total memory usage when this same application
is running 15 times.
Simple application linked against difference libraries
==========================================
I now took a look at an application which basically consisting of a
malloc of 10K and a sleep() statement. I linked against libqt,
libkdecore and libkdeui:
Measured according to method 1) the size of the Data segment is
84K with 24K reserved for the Stack.
Measured according to method 2) a single instantiation of this very
simple program needs approx. 1895K of additional memory.
I then relinked the program to only link against libqt and libkdecore:
The memory usage according to method 1) did not change.
The memory usage according to method 2) dropped to approx. 1605K.
Conclusion:
--------
Each additional instance of an application linked against kdeui requires
an additional 290K of memory.
kdeui with exception handling vs. kdeui without eception handling.
=====================================================
I was very curious why linking (without even using it!) against a
library requires so much memory in each process making use of this
library. I measured the effect of compiling kdeui without RTTI and
the effect of compiling kdeui without support for exceptions. I did not
find any significant difference in memory usage with ot without RTTI.
When I linked my application against a kdeui compiled without exception
handling (-fno-exceptions) I got the following results:
The memory usage according to method 1) did not change. (82K
data, 24K stack)
The memory usage according to method 2) became approx. 1675K.
Conclusion:
--------
Exception handling within kdeui is responsible for an increase in the
memory usage of approx. 220Kb for every instance of an application
linked against kdeui.
How much memory dow a library require for exception-handling?
=====================================================
Playing around with other libraries (most notably kdecore and libqt)
I managed to find out how much memory is needed for in each insatnce
which links against the library.
Take e.g. a look at the output of
"objdump --headers libkdeui.so.3.0.0":
(libkdecore from _current_ CVS HEAD)
libkdeui.so.3.0.0: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .hash 000094c8 00000094 00000094 00000094 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .dynsym 000152d0 0000955c 0000955c 0000955c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .dynstr 00027566 0001e82c 0001e82c 0001e82c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.version 00002a5a 00045d92 00045d92 00045d92 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.version_d 00000038 000487ec 000487ec 000487ec 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version_r 00000050 00048824 00048824 00048824 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .rel.data 00014650 00048874 00048874 00048874 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.eh_frame 00008390 0005cec4 0005cec4 0005cec4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.gcc_except_table 00013818 00065254 00065254 00065254 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rel.got 00002178 00078a6c 00078a6c 00078a6c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rel.ctors 00000190 0007abe4 0007abe4 0007abe4 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .rel.plt 00005090 0007ad74 0007ad74 0007ad74 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
12 .init 00000031 0007fe10 0007fe10 0007fe10 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .plt 0000a130 0007fe44 0007fe44 0007fe44 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .text 000d162e 00089f80 00089f80 00089f80 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .fini 0000001c 0015b5b0 0015b5b0 0015b5b0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
16 .rodata 000080a8 0015b5e0 0015b5e0 0015b5e0 2**5
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .data 0000b944 001646a0 001646a0 001636a0 2**5
CONTENTS, ALLOC, LOAD, DATA
18 .gcc_except_table 00009dd4 0016ffe4 0016ffe4 0016efe4 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .eh_frame 0002c47c 00179db8 00179db8 00178db8 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .ctors 000000d0 001a6234 001a6234 001a5234 2**2
CONTENTS, ALLOC, LOAD, DATA
21 .dtors 00000008 001a6304 001a6304 001a5304 2**2
CONTENTS, ALLOC, LOAD, DATA
22 .got 00003910 001a630c 001a630c 001a530c 2**2
CONTENTS, ALLOC, LOAD, DATA
23 .dynamic 000000c8 001a9c1c 001a9c1c 001a8c1c 2**2
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00000954 001a9d00 001a9d00 001a8d00 2**5
ALLOC
25 .stab 00000fd8 00000000 00000000 001a8d00 2**2
CONTENTS, READONLY, DEBUGGING
26 .stabstr 00002840 00000000 00000000 001a9cd8 2**0
CONTENTS, READONLY, DEBUGGING
27 .comment 00000f03 00000000 00000000 001ac518 2**0
CONTENTS, READONLY
28 .note 000004ec 00000f03 00000f03 001ad41b 2**0
CONTENTS, READONLY
29 .rel.stab 00000020 000013f0 000013f0 001adf88 2**2
CONTENTS, READONLY, DEBUGGING
In the above output entries which are labeled "DATA" but not "READONLY"
are not shared across processes. That means that these entries are
allocated for each instance of an application which links against this
library.
These entries are (size in brackets)
.data (47428 bytes)
.gcc_except_table (40404 bytes)
.eh_frame (181372 bytes)
.ctors (208 bytes)
.dtors (8 bytes)
.got (14608 bytes)
.dynamic (200 bytes)
Total size: 284228 bytes (277Kb)
When compiling without support for exceptions the .gcc_execpt_table and
.eh_frame sections are virtually empty (4 bytes total).
Size needed for exception support: 221776 bytes (216Kb)
This is roughly in line with the above measurement which showed that the
memory usage per instance dropped with 220 Kb when kdeui was compiled
without exception support.
Conclusion:
---------
The .gcc_except_table and .eh_frame sections in a library reflect the
overhead for exception handling for each instance of an application
linked against this library.
Overview of exception handling overhead in libraries
===========================================
The following list shows the exception handling overhead in each
library in kdelibs as well as for Qt.
libqt.so.2.1.0 total = 700.4Kb (717168 bytes)
libkdeui.so.3.0.0 total = 216.6Kb (221776 bytes)
libkded.so.1.0.0 total = 212.7Kb (217784 bytes)
libkpartsui.so.1.0.0 total = 179.6Kb (183936 bytes)
libkom.so.1.0.0 total = 164.4Kb (168320 bytes)
libkdecore.so.3.0.0 total = 153.5Kb (157216 bytes)
libkparts.so.1.0.0 total = 152.4Kb (156060 bytes)
libkhtml.so.3.0.0 total = 144.4Kb (147844 bytes)
libkio.so.3.0.0 total = 132.0Kb (135136 bytes)
libkab.so.0.0.0 total = 131.7Kb (134812 bytes)
libqk.so.1.0.0 total = 67.1Kb (68700 bytes)
libkfile.so.3.0.0 total = 48.5Kb (49624 bytes)
libcutesti.so.1.0.0 total = 27.6Kb (28236 bytes)
libkjs.so.1.0.0 total = 26.0Kb (26668 bytes)
libkformula.so.3.0.0 total = 25.6Kb (26248 bytes)
libkspell.so.3.0.0 total = 18.3Kb (18744 bytes)
libjscript.so.3.0.0 total = 15.0Kb (15348 bytes)
libDCOP.so.1.0.0 total = 9.0Kb (9224 bytes)
libkjava.so.1.0.0 total = 7.6Kb (7792 bytes)
libkimgio.so.3.0.0 total = 2.5Kb (2608 bytes)
libmediatool.so.3.0.0 total = 2.0Kb (2032 bytes)
Conclusion:
---------
Exception handling causes more overhead than CORBA ever did. More
importantly it causes overhead for each and every instance of an
application regardless whether it uses exceptions or not.
Testing yourself
=============
I have added a program kmemtest in kdelibs/kdetest. When you do
measurements be sure to:
* Kill all programs which aren't completely idle (inetd / crond /
kmail?)
* Have enough memory and swap.
How to proceed:
compile kmemtest (it links by default against qt, kdecore and kdeui)
* run ./kmemtest and press Ctrl-C when it says 'Sleeping'
* run ".libs/kmemtest all": this allocates all your memory and causes
unused memory to be cleaned up/swapped out.
* run ".libs/kmemtest launch": This starts itself up 15 times. At the
end it will show you what /proc/self/status says about its memory
consumption and what the actual measured memory consumption was.
If it takes longer than about 2-4 tries before your memory usage has
been stabilized you probably have some process running which you should
kill first.
* Wait patiently and don't touch your computer while kmemtest is
running.
At the end it will report the average memory usage for 1 instance of
kmemtest and will fall asleep.
* Don't forget to kill kmemtest (and lt-kmemtest) when you are done.
You can also test the memory usage of other programs by running
"kmemtest launch <program_name>". Be aware that this will try to
startup your program 15 times! (So this will fail with e.g. kmail)
Conclusions & Recommendation:
===========================
* The overhead of exception handling is huge.
* Qt and KDE should be compiled without support for exception handling.
* The use of exceptions is depreciated.
* Applications or libraries which need exception handling should enable
it for themselves and make sure not to throw any exceptions to code
which does not support it, including Qt. (Take expecially care of
signals/slots and virtual functions)
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic