Continue from part 1....
OK, ALL THIS STUFF LOOKS GREAT, BUT HOW COULD I
ESTIMATE THE SIZE OF A PROCESS IN MEMORY?
Taking into
account what have been told, the Resident Set Size is the closest to the size
in memory of a process, but when checking it by means of top, ps, or another Unix
tool we find a problem. The output of those commands takes into account the
shared memory segments and the shared libraries, so the results are oversized
for double counting the sizes.
In Unix we
have mainly two sources to retrieve the information about the memory map of a
process, the proc filesystem and the command pmap.
With
regards to Oracle processes, we'll find those kinds of memory segments: (Thanks
Tanel Poder for this explanations!)
lib - ld : shared libraries, dynamic linker/loader.
Unix System and Oracle libraries
oracle : the Oracle executable
shmid : System V shared memory segments (if using
memory target parameter, we will see a lot of segments instead, because memory
target uses POSIX implementation. Will comment later)
anon: anonymous memory. shortly said, process
private memory. This memory does not correspond to any real file on disk. This
is the figure we should consider to estimate the size ofthe process.
stack: a small area where some function-local scope
variables are kept and also the return
of some path to parent functions is remembered there.
heap: this is the memory "application scratch
area", called data segment, which is used when you allocate memory with
conventional malloc() calls
Text :The actual program instructions. This
section's contents are never modified during execution.
Data: Constant data that is not modified during
execution. E.g. program constants, string literals etc. etc.
BSS : Statically allocated program variables etc.
that are modified during program execution.
So, my
approach has been this:
To get the
estimate size in memory of a process, I will retrieve all the memory segments
RSS in /proc/<pid>/smaps that are not shared and are writable.
Here I
assume that, as they are writable, is less likely that they are shared and are
particular to each process.
Here is the
command I use:
for i in `ps -fu oracle | grep -v grep | grep
-v PID | awk '{print $2}'`; do cat /proc/$i/smaps |sed '1 i\1' | while read
line; do awk '$2~/w/ && $2!~/s/
{x=NR+2;next}(NR<=x){print}'; done | grep Rss | awk '{v+=$2} END{print v}';
done | awk '{total+=$1} END{print total}'
I observed
that the first line of the output of smap did not appear. It looked like as if
the cat command inside the loop read the first line as if it were not a new
line, so does not count it. To overcome this issue, I added the sed '1 i\1',
that adds a new line at the beginning of the output.
To retrieve
the size of the loaded libraries I use:
for i in `ps -fu oracle |
grep -v grep | grep -v PID | awk '{print $2}'`; do cat /proc/$i/smaps |sed '1
i\1' | while read line; do awk '($6~/ld/
|| /lib/ || /oracle/) && ($2!~/w/) {x=NR+2;next}(NR<=x){print}';
done | grep Rss | awk '{v+=$2} END{print v}'; done | sort -n
Theorically,
those libraries should be loaded in memory just once, and all the processes
should open pointers to the memory adresses where those segments are. So, what
I do is to take only one value from the
previous output, the biggest one. (asn an option, could take the average or the
median).
For the
shared memory, if do not use memory_target, then I take the output from
/proc/sysvpc/shm
cat /proc/sysvipc/shm | grep
`id -u oracle` | awk '{v+=$15} END{print v/1024}'
When the
memory_target parameter is set, we can use the contents from /dev/shm
filesystem, which contains a lot of files with this format:
ora_<SID>_14680074_143
The
"reserved space" in the filesystem for each of those files correspond
to the granule size of the Oracle instance they belong to. (output of ls -l )
The actual
space (du -h) can differ. If the output os ls -l is zero, that means that is
only the file descriptor allocated, but the segment empty.
Let's see
an example (the system is a real one, but the names have been changed):
[TST][servidor].oracle:shm
> pwd
/dev/shm
[TST][servidor].oracle:shm
>ls -l
:
:
-rw-r----- 1 oracle asmadmin
33554432 Aug 22 12:26 ora_ORCL_14680074_300
-rw-r----- 1 oracle asmadmin
33554432 Aug 22 12:26 ora_ORCL_14680074_305
-rw-r----- 1 oracle asmadmin
33554432 Aug 22 12:26 ora_ORCL_14680074_291
-rw-r----- 1 oracle asmadmin
33554432 Aug 22 12:26 ora_ORCL_14680074_317
-rw-r----- 1 oracle asmadmin
33554432 Aug 22 12:26 ora_ORCL_14680074_315
Here we'll
see that some segments show 0 in the fifth field (size)
[TST][servidor].oracle:shm
> ls -lrt *ORCL* | wc -l
321
[TST][servidor].oracle:shm >
ls -lrt *ORCL* | wc -l
[TST][servidor].oracle:shm >
ls -lrt *ORCL* | wc -l
321
[TST][servidor].oracle:shm >
Let'
connect to the instance:
ORCL SQL> select
(321*33554432)/1024/1024/1024||' GB' from dual;
(321*335544
-----------
10.03125 GB
ORCL SQL> show parameter memory_target
NAME TYPE VALUE
------------------------------------
----------- ------------------------------
memory_target big integer 10G
ORCL SQL>
So, here we
see how the contents of /dev/shm correspond to the memory target of the
instance.
The reasons
of the difference between using memory target and do not use it are explained
in note 731658.1 of Oracle Support. Basically,
when Oracle on Linux is configured to use Auto Memory Management (AMM), it
utilizes the POSIX implementation of SHM on Linux. When AMM is
disabled, Oracle falls back to using the System V SHM implementation as seen in
earlier versions of Oracle for Linux.
No hay comentarios:
Publicar un comentario