1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
\input{configpres}
\title{Linux Memory Management}
\maketitle
\subsection{Linux Memory Management}
\begin{frame}
\frametitle{Overview}
\tableofcontents
\end{frame}
\subsubsection{Basics}
\begin{frame}
\frametitle{Overview}
\begin{itemize}
\item over-committing
\item Copy-On-Write
\item Page relocation
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{over-committing}
\begin{itemize}
\item Comparable to those low-cost airlines ;)
\pause
\item ...selling more tickets than available seats
\pause
\item ...hoping not everyone will come ;)
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{over-commit settings}
\begin{verbatim}
/proc/sys/vm/overcommit_memory
\end{verbatim}
Possible settings are:
\begin{itemize}
\item 0: Heuristic overcommit handling (default)
\item 1: Always overcommit
\item 2: Don't overcommit
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{The OOM Killer}
...is invoked if you ask for more memory than available.\\
\pause
\textbf{Result}: The kernel kills a task
\end{frame}
\begin{frame}
\frametitle{Copy-On-Write}
\begin{itemize}
\item completely transparently for userspace
\item you don't need the same data twice
\item only updated if one virtual memory area is updated
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{Page relocation}
\begin{itemize}
\item AKA paging or swapping
\item Linux can move a page to / from swap
\item also completely transparently for userspace
\end{itemize}
\end{frame}
\subsubsection{The stack}
\begin{frame}
\frametitle{The stack}
\begin{itemize}
\item Grows top - down
\item Configurable stack size
\item Stack grows on demand. Access beyond current size ends up in a
''Stackfault'' which is handled by the kernel
\item ulimit -a shows the current maximum stack size
\item ulimit -s \emph{size} sets the maximum stack size
\item Default maximum stack size is 8MiB
\end{itemize}
\end{frame}
\subsubsection{The heap}
\begin{frame}
\frametitle{The heap: Userland handling}
\begin{itemize}
\item Memory is allocated using malloc()
\item Memory is freed using free()
\item malloc() uses the mmap() and the sbrk() system calls
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{The heap: Userland handling}
\begin{itemize}
\item For small chunks, malloc() allocates memory from the heap and adjusts the
size using sbrk()
\item For larger blocks (larger than defined in MMAP\_THRESHOLD) the memory is
allocated as private, anonymous mapping
\item MMAP\_THRESHOLD is 128kb by default
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{malloc()}
\begin{itemize}
\item Keep over-commit in mind!
\item If over-commit is enabled: A non-null return value from malloc() doesn't
guarantee that the memory really is available.
\end{itemize}
\end{frame}
\subsection{Do's and Dont's}
\subsubsection{The heap}
% fragmentation
% check return value
% ulimit (limit memory consumption)
\begin{frame}
\frametitle{Return value}
Always check malloc's return value!!
\end{frame}
\begin{frame}
\frametitle{How to avoid heap fragmentation}
\begin{itemize}
\item GLIBCs malloc() itself tries to avoid fragmentation
\item The allocator can't avoid fragmentation caused by a bad application
design!
\item Try to re-use memory pools
\item free memory you don't need anymore!
\end{itemize}
\end{frame}
\begin{frame}
\frametitle{How to limit memory consumption}
ulimit:
\begin{itemize}
\item ulimit -s sets the maximum stack size
\item ulimit -d sets a limit for the data segment
\item ulimit -v sets a limit for the virtual memory
\item Check limits with ulimit -a
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{ulimit example}
\scriptsize
\begin{verbatim}
$ ulimit -a
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 20
file size (blocks, -f) unlimited
pending signals (-i) 16382
max locked memory (kbytes, -l) 64
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) unlimited
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
\end{verbatim}
\end{frame}
\subsection{Realtime}
\subsubsection{General}
\begin{frame}[fragile]
\frametitle{Locking the memory}
\begin{verbatim}
/* Lock memory */
if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
perror("mlockall failed");
exit(-2);
}
\end{verbatim}
\end{frame}
\subsubsection{Stack}
\begin{frame}[fragile]
\frametitle{Stack prefaulting}
\begin{verbatim}
#define MAX_SAFE_STACK (64*1024)
void stack_prefault(void) {
unsigned char dummy[MAX_SAFE_STACK];
memset(&dummy, 0, MAX_SAFE_STACK);
}
\end{verbatim}
\end{frame}
\subsubsection{Heap}
\begin{frame}
\frametitle{Allocations from Realtime context}
\begin{itemize}
\item If possible, avoid memory allocations from Realtime context
\item Try to use a pre-allocated buffer
\end{itemize}
\end{frame}
\begin{frame}[fragile]
\frametitle{Disable malloc trimming and mmap usage}
\begin{verbatim}
mallopt(M_TRIM_THRESHOLD, -1);
mallopt(M_MMAP_MAX, 0);
\end{verbatim}
\end{frame}
\begin{frame}[fragile]
\frametitle{Reserve process memory}
\begin{verbatim}
static void reserve_process_memory(int size)
{
int i;
char *buffer;
buffer = malloc(size);
/* Touch each page in this piece of
* memory to get it mapped into RAM */
for (i = 0; i < size; i += sysconf(_SC_PAGESIZE))
buffer[i] = 0;
free(buffer);
}
\end{verbatim}
\end{frame}
\subsection*{sources}
\begin{frame}
\frametitle{sources}
\begin{thebibliography}{1}
\bibitem{mmm} http://cftw.wordpress.com/2009/11/02/introduction-to-the-linux-memory-management/
\bibitem{mmm} http://rt.wiki.kernel.org/
\end{thebibliography}
\end{frame}
\input{tailpres}
|