SGA areas in x$ksmmem

The fixed table x$ksmmem (Kernel Layer, Service Layer, Memory Management, MEMory) is basically a memory map of your SGA. It contains a row for each memory address (addr) and the value stored at this location (ksmmmval). This post shows which areas were accessible over this structure in older versions of Oracle, and more importantly, which areas are not present anymore in more recent versions.

In all examples ASMM is enabled, AMM disabled and platform is Linux x86_64.

Version 11.2

Let’s first have a look at the shared memory segments allocated by Oracle.

oradebug setmypid
oradebug ipc
...
 Area #0 `Fixed Size' containing Subareas 0-0
  Total size 0000000000221a50 Minimum Subarea size 00000000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      0        0    32768 0x00000060000000 0x00000060000000
                              Subarea size     Segment size
                          0000000000222000 0000000008c00000
 Area #1 `Variable Size' containing Subareas 4-4
  Total size 0000000035c00000 Minimum Subarea size 00400000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      1        4    65537 0x00000068c00000 0x00000068c00000
                              Subarea size     Segment size
                          0000000035c00000 0000000035c00000
 Area #2 `Redo Buffers' containing Subareas 1-1
  Total size 0000000008565000 Minimum Subarea size 00000000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      2        1    32768 0x00000060222000 0x00000060222000
                              Subarea size     Segment size
                          0000000008565000 0000000008c00000
 Area #3 `Base Allocator Control' containing Subareas 3-3
  Total size 0000000000002000 Minimum Subarea size 00000000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      3        3    32768 0x00000068bfe000 0x00000068bfe000
                              Subarea size     Segment size
                          0000000000002000 0000000008c00000
 Area #4 `Slab Allocator Control' containing Subareas 2-2
  Total size 0000000000477000 Minimum Subarea size 00000000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      4        2    32768 0x00000068787000 0x00000068787000
                              Subarea size     Segment size
                          0000000000477000 0000000008c00000
 Area #5 `skgm overhead' containing Subareas 5-5
  Total size 0000000000003000 Minimum Subarea size 00000000
   Area  Subarea    Shmid      Stable Addr      Actual Addr
      5        5    98306 0x0000009e800000 0x0000009e800000
                              Subarea size     Segment size
                          0000000000003000 0000000000200000
...

As we can see, there are 3 different segments allocated (Shmid 32768, 65537 and 98306).

By taking the values from Actual Addr as the start address and Actual Addr + Total size as the end address, we can write a simple query to see which areas are externalized in x$ksmmem.

select area, count(*) from (
 select
  case
  when addr >= '0000000060000000' and addr < '0000000060221A50'
   then 'Fixed Size'
  when addr >= '0000000068C00000' and addr < '000000009E800000'
   then 'Variable Size'
  when addr >= '0000000060222000' and addr < '0000000068787000' 
   then 'Redo Buffers'
  when addr >= '0000000068BFE000' and addr < '0000000068C00000' 
   then 'Base Allocator Control'
  when addr >= '0000000068787000' and addr < '0000000068BFE000' 
   then 'Slab Allocator Control' 
  when addr >= '000000009E800000' and addr < '000000009E803000' 
   then 'skgm overhead'
  end as area
 from x$ksmmem)
group by area;
AREA                     COUNT(*)
---------------------- ----------
Redo Buffers             17484288
Slab Allocator Control     585216
Variable Size           112135680
Base Allocator Control       1024
Fixed Size                 279370

5 rows selected.

As can be seen, all SGA areas except skgm overhead can be accessed over this table.

Version 18.3

Let’s do the same thing in 18.3.

Instead of listing the shared memory segments via oradebug ipc we can query the new fixed table x$ksmssinfo (Probably a mnemonic for (Kernel Layer, Service Layer, Memory Management, Shared Memory Segment INFO).

select
 "AREA NAME",
 "START ADDR",
 to_char(
  to_number("START ADDR", rpad('X', 16, 'X')) + "SIZE",
  rpad('0', 16, 'X')
 ) as END_ADDR,
 "SIZE"
from x$ksmssinfo;
AREA NAME                        START ADDR       END_ADDR                SIZE
-------------------------------- ---------------- ----------------- ----------
Variable Size                    0000000060C00000  0000000096400000  897581056
Redo Buffers                     0000000096400000  000000009EBBC000  142327808
Fixed Size                       0000000060000000  0000000060844000    8667136
skgm overhead                    000000009EC00000  000000009EC05000      20480

We execute the same query as before, with only the start and end addresses changed.

select area, count(*) from (
 select
  case
  when addr >= '0000000060000000' and addr < '0000000060844000'
   then 'Fixed Size'
  when addr >= '0000000060C00000' and addr < '0000000096400000'
   then 'Variable Size'
  when addr >= '0000000096400000' and addr < '000000009EBBC000' 
   then 'Redo Buffers'
  when addr >= '000000009EC00000' and addr < '000000009EC05000' 
   then 'skgm overhead'
  end as area
 from x$ksmmem)
group by area;
AREA            COUNT(*)
------------- ----------
Fixed Size       1083204

As can be seen, in Oracle 18.3 only the Fixed Size area is externalized in x$ksmmem. In fact, this is the case since bug 19363432 (introduced in 12.1) has been fixed later in Oracle 12.1.

The behavior in Oracle 12.1 before applying the bugfix, is that x$ksmmem also displays addresses which are not currently mapped. This leads to segmentation faults when you try to access this memory location by referring to x$ksmmem.ksmmmval. Unfortunately, after applying the bugfix, all areas except Fixed Size disappear from this fixed table.

Alternatives

In some cases, you want to have access to the contents of shared memory for troubleshooting. x$ksmmem provided a convenient way to do so, because you could use it in any query (e.g. by joining to other fixed views/tables containing memory addresses). Of course, you can still use oradebug peek or any other tool you like, but it’s definitely more cumbersome.