blob: b9a96c6e3eb754aa5e50949f5b6fe42db2cd6146 [file] [log] [blame] [view]
This document describes the detailed usage of `damo`. This doesn't cover all
details of `damo` but only major features. This document may not complete and
up to date sometimes. Please don't hesitate at asking questions and
improvements of this document via GitHub
[issues](https://github.com/damonitor/damo/issues) or
[mails](https://lore.kernel.org/damon).
Prerequisites
=============
Kernel
------
You should first ensure your system is running on a kernel built with at least
``CONFIG_DAMON``, ``CONFIG_DAMON_VADDR``, ``CONFIG_DAMON_PADDR``, and
``CONFIG_DAMON_SYSFS``. Depending on the kernel version, you may need to
enable ``CONFIG_DAMON_DBGFS`` instead of ``CONFIG_DAMON_SYSFS``.
Sysfs or Debugfs
----------------
Because `damo` is using the sysfs or debugfs interface of DAMON, you should
ensure at least one of those is mounted. Note that DAMON debugfs interface is
deprecated. Please use sysfs. If you depend on DAMON debugfs interface and
cannot use sysfs interface, [report](REPORTING.md) your usecase to the
community.
Perf
----
`damo` uses `perf`[1] for recording DAMON's access monitoring results. Please
ensure your system is having it if you will need to do record full monitoring
results of DAMON (`damo` supports recording partial snapshots of DAMON
monitoring results). If you will not do the full-recording, you don't need to
install `perf` on your system, though.
[1] https://perf.wiki.kernel.org/index.php/Main_Page
Basic Concepts of DAMON
-----------------------
`damo` is a user space tool for `DAMON`. Hence, for advanced and optimized use
of `damo` rather than simple "Getting Started" tutorial, you should first
understand the concepts of DAMON. There are a number of links to resources
including DAMON introduction talks and publications at the project
[site](https://damonitor.github.io). The official design
[document](https://docs.kernel.org/mm/damon/design.html) is recommended among
those, since we will try to keep it up to date always, and appropriate for
DAMON users.
Specifically, if you want to use `damo` for profiling purpose, please ensure
you understand what `nr_accesses` and `age` mean. ['Region Based
Sampling'](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#region-based-sampling)
and ['Age
Tracking'](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#age-tracking)
sections of the kernel documentation should be helpful for that.
You should also understand DAMOS if you want to use `damo` for simple
access-aware system operations. ['Operation
Schemes'](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#operation-schemes)
section of the kernel documentation should be helpful for that.
Install
=======
Using Packaging Systems
-----------------------
There are a number of packaging systems that support `damo`. For example,
below can be used if you want to install `damo` via `dnf` or PyPi.
$ sudo dnf install damo # if you prefer dnf
$ sudo pip3 install damo # if you prefer PyPi
Note that `dnf` and PyPi are just two of the options. Refer to below
[repology](https://repology.org/project/damo) data to show the packaging status
of `damo` on your favorite packaging system.
[![Packaging status](https://repology.org/badge/vertical-allrepos/damo.svg)](https://repology.org/project/damo/versions)
Using Source Code
-----------------
Simply downloading the source code and using `damo` file at the root of the
source tree is also a completely supported method for `damo` installation. It
would be particularly preferred if you want to participate in `damo`
development. In the case, you could add the path to the source tree to your
`$PATH` for convenience.
Overview
========
`damo` provides a subcommands-based interface. You can show the list of the
available commands and brief description of those via `damo --help`. The major
commands can be categorized as below:
- For controlling DAMON (monitoring and monitoring-based system optimization)
- `start`, `tune`, and `stop` are included
- For recording, snapshot, and visualization of useful data including DAMON's
monitoring results, DAMON's working status, and additional system information
- `record` and `report` are included
- For more convenient use of `damo`
- `version` and `args` are included
Every subcommand also provides `--help` option, which shows the basic usage of
it. Below sections introduce more details about the major subcommands.
Note that some of the subcommands that not described in this document would be
in experimental stage, or not assumed to be used in major use cases. Those
could be deprecated and removed without any notice and grace periods. Refer to
[FEATURES_DEPRECATION_PROCESS.md](FEATURES_DEPRECATION_PROCESS.md) for more
details.
DAMON Control (Access Monitoring and Monitoring-based System Optimization)
==========================================================================
The main purposes of `damo` is operating DAMON, as the name says (DAMO: Data
Access Monitor Operator). In other words, `damo` is for helping control of
DAMON and retrieval/interpretation of the results.
`damo start`
------------
`damo start` starts DAMON as users request. Specifically, users can specify
how and to what address spaces DAMON should do monitor accesses, and what
access monitoring-based system optimizations to do. The request can be made
via several command line options of the command.
Refer to files under `scripts/` directory for example usages of this command
for memory tiering and LRU lists sorting. For more details about the command
line options, use `damo help damon_param_options -h`.
The command exits immediately after starting DAMON as requested. It exits with
exit value `0` if it successfully started DAMON. Otherwise, the exit value
will be non-zero.
### Simple Target Argument
The command receives one positional argument called deducible target. It could
be used for specifying monitoring target, or full DAMON parameters. The
command will try to deduce the type of the argument value and use it.
With the argument, users can specify the monitoring target with 1) the command
for execution of the monitoring target process, 2) pid of running target
process, or 3) the special keyword, `paddr`, if you want to monitor the
system's physical memory address space.
Below example shows a command target usage:
# damo start "sleep 5"
The command will execute ``sleep 5`` by itself and start monitoring the data
access patterns of the process.
Note that the command requires the root permission, and hence executes the
monitoring target command as a root. This means that the user could execute
arbitrary commands with root permission. Hence, sysadmins should allow only
trusted users to use ``damo``.
Below example shows a pid target usage:
# sleep 5 &
# damo start $(pidof sleep)
Finally, below example shows the use of the special keyword, `paddr`:
# damo start paddr
In this case, the monitoring target regions defaults to the largest 'System
RAM' region specified in `/proc/iomem` file. Note that the initial monitoring
target region is maintained rather than dynamically updated like the virtual
memory address spaces monitoring case.
### Partial DAMON Parameters Update
`damo` sets DAMON parameters such as monitoring intervals with its default
values. Users can continue using the default values but set specific
parameters as they want, via command line options. For the list and brief
explanation of the options for those options, use `damo help
damon_param_options monitoring`.
To understand what each of the command line options really mean, you may need
to read DAMON core concepts
[document](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#core-logics).
For keyword parameters such as operations set name (`--ops`), those on DAMON
design document is samely applied. For example the keywords for `--ops` can be
found from the kernel doc
[session for operations set](https://docs.kernel.org/mm/damon/design.html#operations-set-layer).
Users can create multiple monitoring targets, multiple DAMON contexts and
multiple kdamonds. For that, users can specify related options multiple times
to set the parameter values with non-default ones. Users should also set
`--nr_targets` and `--nr_ctxs` when multiple contexts are used, for assigning
monitoring targets to each context, and contexts to each kdamond.
To see what full DAMON parameters are created with given command line, users
can use `damo args damon --format report`. For example:
```
$ sudo ./damo args damon --format report \
--ops paddr --regions 100-200 --damos_action migrate_cold 1 \
--ops paddr --regions 400-700 --damos_action migrate_hot 0 \
--nr_targets 1 1 --nr_schemes 1 1 --nr_ctxs 1 1
kdamond 0
context 0
ops: paddr
target 0
region [100, 200) (100 B)
intervals: sample 5 ms, aggr 100 ms, update 1 s
nr_regions: [10, 1,000]
scheme 0
action: migrate_cold to node 1 per aggr interval
target access pattern
sz: [0 B, max]
nr_accesses: [0 %, 18,446,744,073,709,551,615 %]
age: [0 ns, max]
quotas
0 ns / 0 B / 0 B per max
priority: sz 0 %, nr_accesses 0 %, age 0 %
watermarks
metric none, interval 0 ns
0 %, 0 %, 0 %
kdamond 1
context 0
ops: paddr
target 0
region [400, 700) (300 B)
intervals: sample 5 ms, aggr 100 ms, update 1 s
nr_regions: [10, 1,000]
scheme 0
action: migrate_hot to node 0 per aggr interval
target access pattern
sz: [0 B, max]
nr_accesses: [0 %, 18,446,744,073,709,551,615 %]
age: [0 ns, max]
quotas
0 ns / 0 B / 0 B per max
priority: sz 0 %, nr_accesses 0 %, age 0 %
watermarks
metric none, interval 0 ns
0 %, 0 %, 0 %
```
### Partial DAMOS Parameters Update
Command line options having prefix of `--damos_` are for DAMON-based operation
schemes. Those options are allowed to be specified multiple times for
requesting multiple schemes. When user creates schemes with multiple DAMON
contexts, `--nr_schemes` should also be provided for assigning the schemes to
each context. For example, below shows how you can start DAMON with two DAMOS
schemes, one for proactive LRU-prioritization of hot pages and the other one
for proactive LRU-deprioritization of cold pages.
# damo start \
--damos_action lru_prio --damos_access_rate 50% max --damos_age 5s max \
--damos_action lru_deprio --damos_access_rate 0% 0% --damos_age 5s max
This command will ask DAMON to find memory regions that showing >=50%
[access rate](#access-rate) for >=5 seconds and prioritize the pages of the
regions on the Linux kernel's LRU lists, while finding memory regions that not
accessed for >=5 seconds and deprioritizes the pages of the regions from the
LRU lists.
For the list and brief explanations of the command line options, `damo help
damon_param_options damos` can help. For options that need more explanations
of usage, please read below additional section.
For keyword parameters such as DAMOS action or DAMOS filter types, those on
DAMOS design document are samely applied. For example, those for
`--damos_action` can be found from kernel doc [session for DAMOS
action](https://docs.kernel.org/mm/damon/design.html#operation-action).
#### Access rate
Access rate is the ratio of
[`nr_accesses`](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#region-based-sampling)
of the region to maximum `nr_accesses` that possible on given DAMON parameters.
For example, if the sampling interval is 5 milliseconds and the aggregation
interval is 100 milliseconds, the "maximum nr_accesses" is 20 (100 milliseconds
divided by 5 milliseconds). And if a region has `nr_accesses` value 4, it's
access rate is 20% (`4 / 20 * 100`).
#### Access hz
Access hz is the ratio of
[`nr_accesses`](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#region-based-sampling)
of the region to the aggregation interval, simply speaking, Hertz. That is, if
a region's "access hz" is 100, it means the region is accessed 100 times per
second.
#### `--damos_filter` Option Format
`--damos_filter` option's format is as below:
```
<allow|reject> [none] <type> [<additional type options>...] [<damos filter>....]
```
The first argument (`allow` or `reject`) specifies if the filter should `allow`
or `reject` the memory. If it is not given, it applies `reject` by default.
Note that kernel support of `allow` behavior is not yet mainlined as of
2025-01-19. It is expected to be supported from Linux v6.14.
`<type>` is the type of the memory that the filter should work for. Depending
on the `<type>`, `<additional type options>` need to be given. For example, if
`<type>` is `memcg`, the memory cgroup's mount point should be passed as
`<additional type options>`. Supported types and required additional options
are as below.
- anon: no additional options are required.
- memcg: the path to the memory cgroup should be provided.
- young: no additional options are required.
- hugeapge_size: minimum and maximum size of hugepages should be provided.
- addr: start and end addresses of the address range should be provided.
- target: the DAMON target index should be provided.
If the filter is for memory exclude the given type, `none` keyword can be given
before the `<type>` part. For example,
- `reject young`: Reject applying the DAMOS action to young pages. In other
words, apply the action to non-young pages only.
- `reject none young`: Reject applying the DAMOS action to none-young pages.
In other words, apply the action to young pages only.
- `reject none addr 1234 56678`: Reject applying the DAMOS action to address
ranges except 1234-5678. In other words, apply the action to only 1234-5678
address range.
To use multiple filters, users can put the options in single
`--[snapshot_]damos_filter` option, or do that with another
`--[snapshot_]damos_filter` flag. For example,
```
--damos_filter allow anon reject memcg foo
```
and
```
--damos_filter allow anon --damos_filter reject memcg foo
```
Will install two DAMOS filters in same way.
Read DAMON design documentation for more details including [how filters
work](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#filters).
##### Old `--damos_filter` Format
Before damo v2.6.4, only below old version of the format was supported. The
format is still supported, but might be deprecated in future.
```
<type> <matching|nomatching> [additional type options>...] [allow|reject]
```
Meaning of `<type>`, `<additional type options>` are same to that of the above
format.
Second argument says if the filter is for memory that matches (`matching`) or
not matches (`nomatching`) the `<type>`. Same to not giving `none` keyword or
not to the above format.
Finally, users can specify if the filter should `allow` of `reject` the memory.
Same to what `allow` or `reject` on the above format means. If it is not
given, it applies `reject` by default.
Unlike the new format, this format doesn't support specifying multiple filter
options with single `--[snapshot]_damos_filter` flag. For multiple filters,
multiple `--[snapshot]_damos_filter` flags should be provided.
### Full DAMON Parameters Update
As mentioned above, the partial DAMON parameters update command line options
support only single kdamond and single DAMON context. That should be enough
for many use cases, but for system-wide dynamic DAMON usages, that could be
restrictive. Also, specifying each parameter that different from their default
values could be not convenient. Users may want to specify full parameters at
once in such cases. For such users, the command supports `--kdamonds` option.
It receives a specification of kdamonds that would contains all DAMON
parameters in `json` or `yaml` format. Either a string of the format, or a
path to a file containing the string can be passed to the option. Then, `damo`
starts DAMON with the specification.
For the full DAMON parameters input format, please refer to `damo args damon`
[documentation](#damo-args-damon) below, or simply try the command. The
`--kdamonds` option keyword can also simply omitted because the full DAMON
parameters input can be used as is for the `deducible target` (refer to "Simple
Target Argument" [section](#simple-target-argument) above).
### Full DAMOS Parameters Update
The Partial DAMOS parameters update options support multiple schemes as abovely
mentioned. However, it could be still too manual in some cases and users may
want to provide all inputs at once. For such cases, `--schemes` option
receives a json-format specification of DAMOS schemes. The format is same to
schemes part of the `--kdamonds` input.
You could get some example json format input for `--schemes` option from
any `.json` files in `damon-tests`
[repo](https://github.com/damonitor/damon-tests/tree/next/perf/schemes).
`damo tune`
-----------
`damo tune` applies new DAMON parameters while DAMON is running. It provides
the set of command line options that same to that of `damo start`. Note that
users should provide the full request specification to this command. If only a
partial parameters are specified via the command line options of this command,
unspecified parameters of running DAMON will be updated to their default
values.
The command exits immediately after updating DAMON parameters as requested. It
exits with exit value `0` if the update succeeded. Otherwise, the exit value
will be non-zero.
`damo stop`
-----------
`damo stop` stops the running DAMON.
The command exits immediately after stopping DAMON. It exits with exit value
`0` if it successfully terminated DAMON. Otherwise, the exit value will be
non-zero.
For Recording, Snapshot, and Visualization of Data
==================================================
There are two major DAMON usages. Automated access-aware system operation, and
profiling.
Automated access-aware system operation specifies what kind of access-aware
system operation the users want to do, and ask DAMON to do that on its own.
That is, using DAMON-based Operation Schemes, aka
[DAMOS](https://www.kernel.org/doc/html/latest/mm/damon/design.html#operation-schemes).
`damo` users can do this via `damo start` or `damo tune` with DAMOS parameter
options.
The second major usage of DAMON is profiling. In this usage, users retrieve
DAMON's access monitoring results, visualize it, and better understand the
behavior of the system and workloads. With the understanding, users could
further make profiling-guided optimizations. Utilizing not only DAMON's
monitoring results but also some additional information can make it more
powerful. Status of DAMON, memory footages, CPU usage, and hot code paths of
system and processes could be such example. `damo` provides two commands for
retrieving such data as snapshots and save as record files, and visualizing
those.
`damo record`
-------------
`damo record` records data including DAMON's monitoring results, DAMON's
status, and additional system/workloads information as snapshots, and save
those in files. Users can set the prefix of the resulting files' paths using
`--out` option. It is `./damon.data` by default. The command requires root
permission. The output files will also be owned by `root` and have `600`
permission by default, so only root can read those. Users can change the
permission via `--output_permission` option.
If the command runs long time, resulting output files could be too huge to
process in a practically short time. To avoid the problems from such too huge
output files, `damo record` flushes the outputs per user-specified time into
intermediate output files. The time can be specified in seconds, using
`--output_flush_sec` option. The default value is 3600 seconds (one hour).
The intermediate output files are complete ones, so can be processed like
normal output files. The autoamtically split outputs are stored in directories
named as `<given_out_file>.<timestamp>`. `<given_out_file>` is same to the
`--out` option input, which is `damon.data` by default. `<timestamp>` is the
time of the intermediate record creation, in `%Y-%m-%d-%H-%M-%S` format.
For the DAMON's monitoring results, it retrieves and saves every
DAMON-generated monitoring result snapshots. Because DAMON's monitoring result
snapshot contains `age` information, the full record is not always required.
Users can retrieve and save only specific number of snapshots with a specific
time delay between snapshots, using `--snapshot` option.
`damo record` records monitoring results and status of running DAMON by
default. If no DAMON is running, users can start DAMON first using `damo
start`, and then run `damo record`. For example, below will start DAMON for
physical address space monitoring, record the monitoring results, and save the
records in `damon.data` file.
# damo start
# damo record
To make the commands shorter, users can also ask `damo record` to start DAMON
by themselves, together with the monitoring target command if needed, and then
start the recording of the newly-started DAMON. For this use case, `damo
record` receives command line options that same to those for `damo start`. For
example, below command can be used.
# damo record "sleep 5"
or, for already running process, like below:
# damo record $(pidof my_workload)
### Recording Profile Information
Note: This feature is an experimental one. Some changes could be made, or the
support can be dropped in future.
`damo record` commands records record profiling information of the system
together with the access pattern. Internally, it runs `perf record` while
`damo record` is running, and store the `perf` output as a file of name same to
the access pattern record file (specified by `--out` option of `damo record`)
except having `.profile` suffix. Hence, `damon.data.profile` is the default
name of the profile information.
Because the profile information record file is simply `perf record` output,
users can further analyze the profile information using `perf` or any `perf
record` output compatible tools.
### Recording Memory Footprints
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo record` command records memory usage information of the record target
processes and the system together with the access pattern. Internally, it
parses `/proc/meminfo` and `/proc/<pid>/statm` files for the monitoring target
processes, and save the results as a json file of the name same to the access
pattern record file (specified by `--out` option of `damo record`) except
having `.mem_footprint` suffix. Hence, `damon.data.mem_footprint` is the
default name of the profile information.
Users could use the files for vaious purpose. For an example, users could find
when how much memory is allocated by the process and really accessed, by
comparing the recorded residential set size and DAMON-based working set size.
[`damo report footprints`](#footprints) and [`damo report wss`](#wss) could be
used for the purpose.
### Recording Memory Mappings
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo record` command records virtual memory mapping information of the record
target processes. Internally, it parses `/proc/<pid>/maps` files of the
monitoring target processes, and save the results as a json file of the name
same to the access pattern record file (specified by `--out` option of `damo
record`) except having `.vmas` suffix. Hence, `damon.data.vmas` is the default
name of the memory mapping information.
### Recording CPU Usages
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo record` command records CPU usages of monitoring target processes and
kdamonds by default. The record data is saved as a json file of the name same
to the access pattern record file (specified by `--out` option of `damo
record`) except having `.proc_stats` suffix. Hence, `damon.data.proc_stats` is
the default name of the CPU usage information.
`damo report`
-------------
`damo report` visualizes the `damo record`-retrieved data in specific report
format. Users can specify `damo record`-generated record files as the source
of the data to visualize. For some report formats, users can also ask `damo
report` to retrieve the data on its own, and directly do visualization of the
self-retrieved data. Input data, command line options, and usages are
different for specific report formats. Following sections describe some of the
report formats.
### `damo report damon`
`damo report damon` shows the current or recorded status of DAMON. It gets
snapshot of the current status of DAMON and shows it by default. Users can use
`--input_file` option to show the `damo record`-recorded DAMON status file or
`damo args damon`-generated DAMON parameters as the source.
It shows every kdamond with the parameters that applied to it, running status
(`on` or `off`), and DAMOS schemes status including their statistics and
detailed applied regions information. It supports more command line options
for retrieving status of specific parts.
### `damo report access`
`damo report access` visualizes DAMON's access monitoring result snapshots in
customizable formats. From where the data to visualize is retrieved is decided
based on the given command line options and system status.
- If `--input_file` option is given with `damo record`-generated monitoring
results record, the record is used.
- If no data source specification command line option is given, the source of
data is decided based on the system status.
- If any `damo start`-started DAMON instance is running, its current
monitoring results snapshot is used.
- Else if `./damon.data` file exists, use `./damon.data` as `--input_file`.
- Else if
[`DAMON_STAT`](https://docs.kernel.org/admin-guide/mm/damon/stat.html) is
running, its `memory_idle_ms_percentiles` snapshot is used. Note that
`memory_idle_ms_percentiles` provides only a subset of the access pattern,
and hence re-constructed access pattern information lacks many details and
accuracy.
Users can set it to use `damo record`-generated
monitoring results record as the source using `--input_file` option. If
`--input_file` is not provided and DAMON is running, it captures snapshot from
the running DAMON and uses it as the source. If `--input_file` is not provided,
DAMON is not running, but `./damon.data` file does exist, use `./damon.data` as
`--input_file`.
For example:
# damo start
# damo report access
heatmap: 77788899998666666654444443333333322222221111111100000000000000000000000000000000
# min/max temperatures: -2,400,000,000, 1,500, column size: 766.312 MiB
intervals: sample 5 ms aggr 100 ms (max access hz 200)
0 addr 4.000 GiB size 2.326 GiB access 0 hz age 2.800 s
1 addr 6.326 GiB size 8.000 KiB access 200 hz age 2.800 s
2 addr 6.326 GiB size 12.000 KiB access 10 hz age 800 ms
[...]
71 addr 51.462 GiB size 5.534 GiB access 0 hz age 23.700 s
72 addr 56.996 GiB size 5.908 GiB access 0 hz age 23.900 s
73 addr 62.903 GiB size 988.039 MiB access 0 hz age 24 s
memory bw estimate: 121.143 GiB per second
total size: 59.868 GiB
record DAMON intervals: sample 5 ms, aggr 100 ms
The first line of the output shows the hotness (temperature) of regions on the
address range as a heatmap visualization. The location and value of each
column on the line represents the relative location and the
[access temperature](#access-temperature) of each memory region on the
monitoring target address space. The second line shows scales of the
temperature number and size of the heatmap. The third line shows the sampling
and aggregation
[intervals](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#access-frequency-monitoring)
that used for this snapshot. DAMON checks if each page is accessed every
"sampling interval", count the times it shown access for each page, and resets
the counter every "aggregation interval". Hence the observable maximum [access
frequency in hz](#access-hz) depends on the intervals, and the maximum hz is
shown on the same line.
Lines showing more detailed properties of each region follow. The detailed
properties include the start address, (`addr`), size (`size`), [access
frequency in hz](#access-hz) (`access`), and the
[age](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#age-tracking)
of the region. “Access frequency” represents how many times each page in the
region is accessed per second. “Age” means how long the access frequency to
the region was kept. For example the sixth line (starts with “2”) says it
found 12 KiB memory region that starts from ~6.326 GiB address on the address
space. The region was accessed about 10 times per second, and the frequency
was kept for last 800 milliseconds.
Final three lines show the memory bandwidth usage that is estimated from the
snapshot, and the total size of the regions that are listed on the output,
respectively.
#### Access temperature
Access temperature is an abstract representing holistic access-hotness of a
given region. It is calculated as a weighted sum of the access pattern values
(size in bytes, [access rate](#access-rate) in percent, and
[age](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#age-tracking)
in microseconds) of each region. If `access_rate` is zero, the hotness becomes
the weighted sum multiplies `-1`. By default, the weights for the three values
are 0, 100, and 100, respectively. Users can set custom weights using
`--temperature_weights` option.
### Access report styles
`damo report access` provides `--style` option that allows users set the report
style for commonly useful cases. The default style is 'detailed', which shown
on example of the previous [section](#damo-report-access).
`recency-percentiles` style shows the distribution of per-byte idle time in
percentiles. For example,
$ sudo damo report access --style recency-percentiles
# total recency percentiles
<percentile> <idle time>
0 0 ns | |
1 0 ns | |
25 5 m 3.500 s |******** |
50 8 m 56.400 s |************** |
75 11 m 9.500 s |****************** |
99 11 m 56.300 s |********************|
100 11 m 56.300 s |********************|
memory bw estimate: 5.886 GiB per second
total size: 59.868 GiB
`temperature-sz-hist` style shows the distribution of per-byte [access
temperature](#access-temperature) in percentiles. For example,
$ sudo damo report access --style temperature-percentiles
# total temperature percentiles
<percentile> <temperature (weights: [0, 100, 100])>
0 -337,330,000,000 | |
1 -337,330,000,000 | |
25 -312,180,000,000 |* |
50 -209,510,000,000 |******* |
75 -85,890,000,000 |************** |
99 120,000,500 |********************|
100 120,000,500 |********************|
memory bw estimate: 10.402 GiB per second
total size: 59.868 GiB
`recency-sz-hist` style shows the distribution of per-byte idle time in
histogram. For example,
$ sudo damo report access --style recency-sz-hist
<idle time (us)> <total size>
[0 ns, 1 m 11.500 s) 12.101 GiB |*************** |
[1 m 11.500 s, 2 m 23.000 s) 0 B | |
[2 m 23.000 s, 3 m 34.500 s) 4.435 GiB |****** |
[3 m 34.500 s, 4 m 46.000 s) 0 B | |
[4 m 46.000 s, 5 m 57.500 s) 5.441 GiB |******* |
[5 m 57.500 s, 7 m 9.000 s) 5.816 GiB |******* |
[7 m 9.000 s, 8 m 20.500 s) 0 B | |
[8 m 20.500 s, 9 m 32.000 s) 5.666 GiB |******* |
[9 m 32.000 s, 10 m 43.500 s) 9.545 GiB |************ |
[10 m 43.500 s, 11 m 55.000 s) 16.864 GiB |********************|
memory bw estimate: 9.180 MiB per second
total size: 59.868 GiB
`temperature-sz-hist` style shows the distribution of per-byte [access
temperature](#access-temperature) in histogram. For example,
$ sudo damo report access --style temperature-sz-hist
<temperature> <total size>
[-71,450,000,000, -63,707,998,999) 18.284 GiB |********************|
[-63,707,998,999, -55,965,997,998) 5.729 GiB |******* |
[-55,965,997,998, -48,223,996,997) 5.650 GiB |******* |
[-48,223,996,997, -40,481,995,996) 5.953 GiB |******* |
[-40,481,995,996, -32,739,994,995) 5.732 GiB |******* |
[-32,739,994,995, -24,997,993,994) 0 B | |
[-24,997,993,994, -17,255,992,993) 5.954 GiB |******* |
[-17,255,992,993, -9,513,991,992) 0 B | |
[-9,513,991,992, -1,771,990,991) 12.567 GiB |************** |
[-1,771,990,991, 5,970,010,010) 92.000 KiB |* |
memory bw estimate: 10.625 MiB per second
total size: 59.868 GiB
`simple-boxes` style is similar to `detailed` style, but provides a box
visualization for access frequency and age of each region. It is useful for
understanding overall access pattern of the system in a glance. For example,
$ sudo damo report access --style simple-boxes
|000000000000000000000000000000000000000| size 54.996 MiB access rate 0 % age 7.300 s
|0000000000000000000000000000000000000000| size 292.797 MiB access rate 0 % age 10.400 s
|000000000000000000000000000000000| size 54.062 MiB access rate 0 % age 700 ms
|00000000000000000000000000000000| size 31.820 MiB access rate 0 % age 500 ms
|99999999999999999999999999999999| size 9.402 MiB access rate 100 % age 500 ms
|00000000000000000000000000000000000| size 6.277 MiB access rate 0 % age 1.400 s
|000000000000000000000000000000000000000| size 116.000 KiB access rate 0 % age 9.900 s
|4| size 8.000 KiB access rate 55 % age 0 ns
|000000000000000000000000000000000000000| size 8.000 KiB access rate 0 % age 9.800 s
total size: 559.688 MiB
`damo report access` further provides flexible customization features.
Actually `--style` option is also built on top of the customization features.
Below sections provide more details about the background and usages of the
features.
### `damo report access`: Page Level Properties Based Access Monitoring
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo` supports DAMON's page level properties based access monitoring feature,
which has been merged into the mainline Linux kernel starting from v6.14.
`damo report access` shows the per-region size of the pages of specific
properties by default if following two conditions met.
First, the access pattern to visulize should contain the information. Such
collection can be made by taking access snapshot with page level
properties-based DAMOS filters. For example, `damo record` or `damo report`
for live snapshot use case with `--snapshot_damos_filter` options can generate
such access pattern collection. The input format for `--snapshot_damos_filter`
is same to [that of `--damos_filter`](#damos_filter_option_format).
Second, the visualization format supports the page level properties based
information. `detailed` and histogram report [styles](#access-report-styles)
will be automatically extended to show the information when it is included in
the access pattern. To make custom format of the reports with the information,
users can use format keywords such as `<filters passed bytes>` and `<filters
passed type>` snapshot format keywords. Use `damo help access_format_options
{region,snapshot,record}_format_keywords` for list and meaning of the keywords.
For example, users can show how much of anonymous and `PG_young` pages reside
in regiosn of different access patterns, like below:
```
$ sudo damo start
$ sudo damo report access --snapshot_damos_filter allow anon allow young
89888888885555555522222222111111100000000000000000000000000000000000000000000000
# min/max temperatures: -9,460,000,000, -368,113,080, column size: 766.312 MiB
intervals: sample 5 ms aggr 100 ms (max access hz 200)
# damos filters (df): allow anon, allow young
df-pass: 777777777987777777777777777777777777777777777777777775444444444444446[...]400000000000
# min/max temperatures: -9,460,000,000, 870,000,500, column size: 143.883 MiB
0 addr 4.000 GiB size 25.285 MiB access 0 hz age 8.900 s df-passed 16.000 KiB
1 addr 4.025 GiB size 227.574 MiB access 0 hz age 8.900 s df-passed 7.320 MiB
2 addr 4.247 GiB size 1011.438 MiB access 0 hz age 8.900 s df-passed 172.566 MiB
3 addr 5.235 GiB size 8.000 KiB access 200 hz age 3.900 s df-passed 8.000 KiB
4 addr 5.235 GiB size 7.387 MiB access 0 hz age 8.700 s df-passed 1.336 MiB
5 addr 5.242 GiB size 17.242 MiB access 0 hz age 8.700 s df-passed 3.645 MiB
[...]
26 addr 29.101 GiB size 5.620 GiB access 0 hz age 1 m 31.400 s df-passed 0 B
27 addr 34.721 GiB size 5.677 GiB access 0 hz age 1 m 33.600 s df-passed 0 B
28 addr 40.398 GiB size 5.934 GiB access 0 hz age 1 m 34.300 s df-passed 0 B
29 addr 46.332 GiB size 15.140 GiB access 0 hz age 1 m 34.600 s df-passed 0 B
30 addr 61.472 GiB size 1.615 GiB access 0 hz age 1 m 34.600 s df-passed 476.000 KiB
31 addr 63.087 GiB size 799.883 MiB access 0 hz age 1 m 34.600 s df-passed 0 B
memory bw estimate: 2.171 GiB per second df-passed: 377.578 MiB per second
total size: 59.868 GiB df-passed 2.190 GiB
record DAMON intervals: sample 5 ms, aggr 100 ms
```
The line starting with `df-pass:` shows the access snapshot heatmap for regions
that having the filters passed. Regions that not having the filters passed are
represented as a gap (`[...]`). Note that the heatmap is in experimental
support now.
### `damo report access`: Programming Visualization
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo report access` provides a highly customizable visualization formats. It
cannot fits all, though. Users can implement and use their own visualization
of the given access monitoring results in Python code using `--exec` option of
`damo report access` be below two ways.
Users can implement the visualization in a Python script and pass the path to
the script with optional arguments via `--exec`. The `--exec` parameter value
can also have optional inputs for the script. The given Python script should
have a function name `main()`, which receives two parameters. `damo report
access` will call the `main()` function. The invocation will pass monitoring
results record information to the first parameter. The tokens of `--exec`
parameter value will be passed as the second parameter. For example:
$ cat foo.py
def main(records, cmd_fields):
print('hello')
print(records)
print(cmd_fields)
for r in records:
for s in r.snapshots:
for r in s.regions:
print(r.start, r.end)
$ sudo ./damo report access --exec "./foo.py a b c"
hello
[<_damo_records.DamonRecord object at 0x7f24e3678190>]
['./foo.py', 'a', 'b', 'c']
4294967296 10660085760
10660085760 17044361216
17044361216 68577918976
Users can also start Python interpreter with the access information records by
passing `interpreter` as `--exec` value. For example:
$ sudo ./damo report access --exec interpreter
DAMON records are available as 'records'
>>> print(records)
[<_damo_records.DamonRecord object at 0x7fe468d13d90>]
>>> help(records[0])
Help on DamonRecord in module _damo_records object:
class DamonRecord(builtins.object)
| DamonRecord(kd_idx, ctx_idx, intervals, scheme_idx, target_id, scheme_filters)
|
| Contains data access monitoring results for single target
|
| Methods defined here:
|
| __init__(self, kd_idx, ctx_idx, intervals, scheme_idx, target_id, scheme_filters)
| Initialize self. See help(type(self)) for accurate signature.
[...]
`records` is a list of `DamonRecord` class that defined on
`src/_damo_records.py` of `damo` repo. The methods and fields could be changed
in future, so no strict script backward compatibility is guaranteed. Instead,
we provide a compatibility strategy that is similar to that of Linux kernel's
in-tree modules only API compatibility guarantee. We will keep some `--exec`
scripts on `report_access_exec_scripts` directory of `damo` repo, and do our
best to keep those not broken. Hence, if you need backward compatibility of
your `--exec` script, please consider upstreaming it into `damo` repo.
### DAMON Monitoring Results Structure
The monitoring results are constructed with three data structures called
'record', 'snapshot', and 'region'.
'Record' contains monitoring results for each kdamond/context/target
combination.
Each 'record' contains multiple 'snapshots' of the monitoring results. If it
was made with `--snapshot` option, the snapshots are retrieved for each
`--snapshot`-specified snapshot dealy time. If it was made as a result of full
recording (no `--snapshot` given), the snapshots are retrieved for each
`aggregation interval`. For example, if `damo report access` was used for live
snapshot visualization, each record will contain only one single snapshot.
Each 'snapshot' contains multiple 'regions' information. Each region
information contains the monitoring results for the region including the start
and end addresses of the memory region, `nr_accesses`, and `age`. The number
of regions per snapshot depends on the `min_nr_regions` and `max_nr_regions`
DAMON parameters, and actual data access pattern of the monitoring target
address space.
### `damo`'s way of showing DAMON Monitoring Results
`damo report access` shows the information in an enclosed hierarchical way like
below:
<record 0 head>
<snapshot 0 head>
<region 0 information>
[...]
<snapshot 0 tail>
[...]
<record 0 tail>
[...]
That is, information of record and snapshot can be shown twice, once at the
beginning (before showing it's internal data), and once at the end. Meanwhile,
the information of regions can be shown only once since it is the lowest level
that not encloses anything. By default, record and snapshot head/tail are
skipped if there is only one record that has only one snapshot. That's why
above `damo report access` example output shows only regions information.
### Customization of The Output
Users can customize what information to be shown in which way for the each
position using `--format` option. The option receives fine-grained format
command for each position of the hierarchical output structure (head and tail
of record and snapshot, and region). The fine-grained per-output position
format command is constructed in below format.
<action> <position> <format string>
`<position>` specifies the output position on the hierarchical structure. It
can be one of `record_head`, `snapshot_head`, `region`, `snapshot_tail`, and
`record_tail`.
`<action>` can be `set` or `append`. `set` is for setting the format of the
`<position>` output. `append` is for append a line of specific format to the
current output of the `<position>`.
Finally, `<format string>` is the template string for the output. The template
can have any words and special format keywords for each position. For example,
`<start address>`, `<end address>`, [`<access rate>`](#access-rate), or
[`<age>`](https://origin.kernel.org/doc/html/latest/mm/damon/design.html#age-tracking)
keywords are available for `region` position. The template can also have
arbitrary strings. The newline character (`\n`) is also supported. Each of
the keywords for each position and their brief description can be shown via
`damo help access_format_options {record,snapshot,region}_format_keywords`
command.
For example:
# damo start
# damo report access \
--format set region "region that starts from <start address> and ends at <end address> was having <access rate> access rate for <age>." \
--format set snapshot_tail "total size: <total bytes>"
region that starts from 4.000 GiB and ends at 16.251 GiB was having 0 % access rate for 40.700 s.
region that starts from 16.251 GiB and ends at 126.938 GiB was having 0 % access rate for 47.300 s.
total size: 122.938 GiB
#### Region Visualization via Boxes
For region information customization, a special keyword called `<box>` is
provided. It represents each region's access pattern with its shape and color.
By default it represents each region's relative age, [access
rate](#access-rate), and size with its length, color, and height, respectively.
For example, `damo report access --format set region "<box>"` shows
visualization of the access pattern, by showing location of each region in
Y-axis, the hotness with color of each box, and how long the hotness has
continued in X-axis. Showing only the first column of the output would be
somewhat similar to an access heatmap of the target address space.
For convenient use of it with a default format, `damo report access` provides
`--region_box` option. Output of the command with the option would help users
better to understand.
Users can further customize the box using `damo report access` options that
having `--region_box_` prefix. For example, users can set what access
information to be represented by the length, color, and height, and whether the
values should be represented in logscale or linearscale.
#### Sorting and Filtering Regions Based on Access Pattern
By default, `damo report access` shows all regions that sorted by their start
address. Different users would have different interest to regions having
specific access pattern. Someone would be interested in hot and small regions,
while some others are interested in cold and big regions.
For such cases, users can make it to sort regions with specific access pattern
values as keys including `access_rate`, `age`, and `size` via
`--sort_regions_by` option. `--sort_regions_dsc` option can be used to do
desscending order sorting.
Further, users can make `damo report access` to show only regions of specific
access pattern and address ranges using options including `--sz_region`,
`--access_rate`, `--age`, and `--address`. Note that the filtering could
reduce DAMON's overhead, and therefore recommended to be used if you don't need
full results and your system is sensitive to any resource waste.
#### Sorting Regions Based on Hotness
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
Users can sort the regions based on hotness of the regions by providing
[access temperature](#access-temperature) as the sort key
(`--sort_regions_by`).
For example:
```
snapshot time: [0 ns, 100 ms] (100 ms)
|0000000000000000000000000000000000000000| size 3.022 GiB access 0 hz age 11 m 31.300 s
|000000000000000000000000000000000000000| size 5.899 GiB access 0 hz age 11 m 28.300 s
|000000000000000000000000000000000000000| size 5.319 GiB access 0 hz age 11 m 19.900 s
|000000000000000000000000000000000000000| size 5.557 GiB access 0 hz age 11 m 4.900 s
|000000000000000000000000000000000000000| size 4.509 GiB access 0 hz age 10 m 35.400 s
|000000000000000000000000000000000000000| size 5.563 GiB access 0 hz age 9 m 33.200 s
|00000000000000000000000000000000000000| size 5.512 GiB access 0 hz age 7 m 52.100 s
|000000000000000000000000000000000000| size 5.699 GiB access 0 hz age 5 m 57.500 s
|000000000000000000000000000000000| size 5.854 GiB access 0 hz age 2 m 53.900 s
|00000000000000000000000000000| size 4.306 GiB access 0 hz age 1 m 13.100 s
|00000000000000000| size 5.949 GiB access 0 hz age 6.200 s
|00000000000| size 2.074 MiB access 0 hz age 1.800 s
|00000000| size 1.242 GiB access 0 hz age 900 ms
|3| size 8.000 KiB access 80 hz age 200 ms
|00| size 4.000 KiB access 20 hz age 300 ms
|99| size 4.000 KiB access 200 hz age 300 ms
|9999999999| size 16.000 KiB access 200 hz age 1.600 s
|00000000000000000000000000000| size 1.435 GiB access 10 hz age 1 m 13.100 s
memory bw estimate: 14.358 GiB per second
total size: 59.868 GiB
record DAMON intervals: sample 5 ms, aggr 100 ms
```
#### `damo report access --raw_form`
`--raw_form` option of `damo report access` directly transforms the recorded
access monitoring results into a human-readable text. For example:
$ damo report access --raw_form --input damon.data
base_time_absolute: 8 m 59.809 s
monitoring_start: 0 ns
monitoring_end: 104.599 ms
monitoring_duration: 104.599 ms
target_id: 18446623438842320000
nr_regions: 3
563ebaa00000-563ebc99e000( 31.617 MiB): 1
7f938d7e1000-7f938ddfc000( 6.105 MiB): 0
7fff66b0a000-7fff66bb2000( 672.000 KiB): 0
monitoring_start: 104.599 ms
monitoring_end: 208.590 ms
monitoring_duration: 103.991 ms
target_id: 18446623438842320000
nr_regions: 4
563ebaa00000-563ebc99e000( 31.617 MiB): 1
7f938d7e1000-7f938d9b5000( 1.828 MiB): 0
7f938d9b5000-7f938ddfc000( 4.277 MiB): 0
7fff66b0a000-7fff66bb2000( 672.000 KiB): 5
The first line shows the recording started timestamp (`base_time_absolute`).
Records of data access patterns follow. Each record is separated by a blank
line. Each record first specifies when the record started (`monitoring_start`)
and ended (`monitoring_end`) relative to the start time, the duration for the
recording (`monitoring_duration`). Recorded data access patterns of each
target follow. Each data access pattern for each task shows the target's id
(``target_id``) and a number of monitored address regions in this access
pattern (``nr_regions``) first. After that, each line shows the start/end
address, size, and the number of observed accesses of each region.
### `damo report heatmap`
`damo report heatmap` plots `damo record`-generated monitoring results in
3-dimensional form, which represents the time in x-axis, address of regions in
y-axis, and the access frequency in z-axis. Users can optionally set the
resolution of the map (`--resol`) and start/end point of each axis
(`--time_range` and `--address_range`). For example:
$ sudo ./damo report heatmap --resol 15 80
11111111111111111111111111111111111111111111111111111111111111111111112211110000
11111111111111111111111111111111111111111111111111111111111111111111111111100000
00000000000000000000000000000000000000000000000000000000000000000001455555530000
00000000000000000000000000000000000000000000000000000000000013333333344444430000
00000000000000000000000000000000000000000000000000000111111127777777000000000000
00000000000000000000000000000000000000000000000000000688888830000000000000000000
00000000000000000000000000000000000000000000037777775000000000000000000000000000
00000000000000000000000000000000000000555555522222222000000000000000000000000000
00000000000000000000000000000003333332555555510000000000000000000000000000000000
00000000000000000000000001111147777774000000000000000000000000000000000000000000
00000000000000000000001888888800000000000000000000000000000000000000000000000000
00000000000000067777773000000000000000000000000000000000000000000000000000000000
00000002555555423333331000000000000000000000000000000000000000000000000000000000
33333332555555400000000000000000000000000000000000000000000000000000000000000000
77777771000000000000000000000000000000000000000000000000000000000000000000000000
# access_frequency: 0123456789
# x-axis: space (139905344733184-139905455165424: 105.316 MiB)
# y-axis: time (3347892748000-3407716412995: 59.824 s)
# resolution: 80x15 (1.316 MiB and 3.988 s for each character)
As the above example shows, it plots the heatmap on the terminal by default.
Users can ask the heatmap to be made as image files using `--output` option.
Currently pdf, png, jpeg, and svg file formats are supported. For example,
below command will create 'heatmap.png' file that contains the visualized
heatmap.
$ sudo ./damo report heatmap --output heatmap.png
#### Heatmap Scoping
If the recorded time and space are huge, users would want to do proper zoom
in/out. Particularly if the target address space is a virtual memory address
space and the user plots the entire address space, the huge unmapped regions
will make the picture looks only black. For this, command line options for
setting the resolution (`--resol`) and x/y axis boundaries (`--time_range` and
`--address_range`) are provided.
To make this effort minimal, `--guide_human` option can be used as below:
# ./damo report heatmap --guide_human
target_id: 18446623438842320000
time: [8 m 59.809 s, 9 m 56.607 s) (56.797 s)
region 0: [86.245 TiB, 86.245 TiB) (31.617 MiB)
region 1: [127.576 TiB, 127.576 TiB) (196.848 MiB)
region 2: [127.998 TiB, 127.998 TiB) (672.000 KiB)
The output shows unions of monitored regions (start and end addresses in byte)
and the union of monitored time duration (start and end time in nanoseconds) of
each target task. Therefore, it would be wise to plot the data points in each
union. If no axis boundary option is given, it will automatically find the
biggest union in ``--guide_human`` output and set the boundary in it.
Users can also interactively find the right scope using `--interactive_edit`
option.
For a case that the user still unsure which range to draw heatmap for,
`--draw_range` option can be used. The option receives either `all` or
`hottest`. If `all` is passed, `damo report heatmap` draws heatmaps for all
the three regions. If file output is requested, the output for first region
will have the user-specified file name. For those of second and third regions,
`.1` and `.2` will be added to the file name, before the file format extension
part (e.g., `heatmap.1.png`). If `hottest` is passed, `damo report heatmap`
will draw the heatmap for hottest region among the three regions.
#### Raw Heatmap Data for Custom Plots
In some cases, users may want to have only the raw data points of the heatmap
so that they can do their own heatmap visualization. For such use case, a
special keyword, `raw` can be given to `--output` option, like below.
# damo report heatmap --output raw --resol 3 3
0 0 0.0
0 7609002 0.0
0 15218004 0.0
66112620851 0 0.0
66112620851 7609002 0.0
66112620851 15218004 0.0
132225241702 0 0.0
132225241702 7609002 0.0
132225241702 15218004 0.0
This command shows a recorded access pattern in a heatmap of 3x3 resolution.
Therefore it shows 9 data points in total. Each line shows each of the data
points. The three numbers in each line represent time in nanoseconds, address
in bytes and the observed access frequency.
Users can convert this text output into a heatmap image (represents z-axis
values with colors) or other 3D representations using various tools such as
`gnuplot`.
### `damo report wss`
The `wss` type extracts the distribution and chronological working set size
changes from the record.
By default, the working set is defined as memory regions shown any access
within each snapshot. Hence, for example, if a record is having N snapshots,
the record is having N working set size values, and `wss` report type shows the
distribution of the N values in size order, or chronological order.
For example:
$ ./damo report wss
# <percentile> <wss>
# target_id 18446623438842320000
# avr: 107.767 MiB
0 0 B | |
25 95.387 MiB |**************************** |
50 95.391 MiB |**************************** |
75 95.414 MiB |**************************** |
100 196.871 MiB |***********************************************************|
Without any option, it shows the distribution of the working set sizes as
above. It shows 0th, 25th, 50th, 75th, and 100th percentile and the average of
the measured working set sizes in the access pattern records. In this case,
the working set size was 95.387 MiB for 25th to 75th percentile but 196.871 MiB
in max and 107.767 MiB on average.
By setting the sort key of the percentile using `--sortby`, you can show how
the working set size has chronologically changed. For example:
$ ./damo report wss --sortby time
# <percentile> <wss>
# target_id 18446623438842320000
# avr: 107.767 MiB
0 0 B | |
25 95.418 MiB |***************************** |
50 190.766 MiB |***********************************************************|
75 95.391 MiB |***************************** |
100 95.395 MiB |***************************** |
The average is still 107.767 MiB, of course. And, because the access was
spiked in very short duration and this command plots only 4 data points, we
cannot show when the access spikes made. Users can specify the resolution of
the distribution (``--range``). By giving more fine resolution, the short
duration spikes could be more easily found.
Similar to that of ``heats --heatmap``, it also supports `gnuplot` based simple
visualization of the distribution via ``--plot`` option.
### `damo report footprints`
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
The `footprints` type extracts the distribution of the
[recorded](#recording-memory-footprints) in chronological or size order. By
comparing the output against that of [wss](#wss) report type, users can know
how much memory is being allocated for the workload and what amount of the
allocated memory is really being accessed. The output format is similar to
that of [wss](#wss).
Because there are various memory footprint metrics, the command asks users to
specify what memory footprint metric they want to visualize. Currently, below
metrics are supported.
- `vsz`: The amount of virtual memory that allocated to the workloads; a.k.a
"virtual set size".
- `rss`: The amount of physical memory that allocated to the workloads; a.k.a
"residential set size".
- `sys_used`: The amount of system's memory that allocated for any usage
(`MemTotal - MemFree`).
For example:
$ ./damo report footprints vsz
# <percentile> <footprint>
# avr: 199.883 MiB
0 199.883 MiB |***********************************************************|
25 199.883 MiB |***********************************************************|
50 199.883 MiB |***********************************************************|
75 199.883 MiB |***********************************************************|
100 199.883 MiB |***********************************************************|
$
$ ./damo report footprints rss
# <percentile> <footprint>
# avr: 196.168 MiB
0 196.168 MiB |***********************************************************|
25 196.168 MiB |***********************************************************|
50 196.168 MiB |***********************************************************|
75 196.168 MiB |***********************************************************|
100 196.168 MiB |***********************************************************|
### `damo report profile`
Note: This feature is an experimental one. Some changes could be made, or the
support can be dropped in future.
The `profile` type shows profiling report for specific access pattern.
It requires two files, namely an access pattern record file and a profiling
information record file that recorded together with the access pattern record
file. Those can be generated by `damo record` (Refer to 'Recording Profile
Information' [section](#recording-profile-information) for details). Users can
further describe access pattern of their interest that they want to know what
happens when the access pattern occurs. Then, `damo report profile` command
read the access pattern, find times when the specific access pattern happened,
collect profiling information for the time ranges, and generate the report with
the filtered information.
For example, below shows what was consuming CPU while 50% or more [access
rate](#access-rate) was made towards 50 MiB size address range starting from
`139,798,348,038,144`, and the total size of the memory regions that got the
access in the address range was 40 or more MiB.
$ sudo ./damo report profile --access_rate 50% 100% \
--address 139798348038144 $((139798348038144 + 50 * 1024 * 1024)) \
--sz_snapshot 40MiB max
Samples: 69K of event 'cpu-clock:pppH', Event count (approx.): 17449500000
Overhead Command Shared Object Symbol
70.32% swapper [kernel.vmlinux] [k] pv_native_safe_halt
28.83% masim masim [.] do_seq_wo
0.03% masim [kernel.vmlinux] [k] _raw_spin_unlock_irqrestore
0.03% ps [kernel.vmlinux] [k] do_syscall_64
0.03% swapper [kernel.vmlinux] [k] __do_softirq
### `damo report times`
Note: This feature is an experimental one. Some changes could be made, or the
support can be dropped in future.
The `times` type shows time intervals in an access pattern record that showing
specific access pattern. This can be useful when user runs `damo` together
with other tools such as profilers.
For example, below shows when there was no access to 50 MiB size address range
starting from `139,798,348,038,144`.
$ sudo ./damo report times --access_rate 0% 0% \
--address 139798348038144 $((139798348038144 + 50 * 1024 * 1024))
93904.291408-93904.393156
93905.919058-93910.903176
93915.994039-93920.876248
93926.049032-93930.918094
93935.988105-93940.956402
93946.027539-93950.997432
93956.067597-93961.036500
93966.101779-93966.910657
### `damo report holistic`
Note: This is an experimental feature at the moment. Many changes would be
made, or the support can be dropped in future.
The `holistic` type shows holistic view of the recorded access pattern, memory
footprints, and CPU consuming functions. As of v2.4.1, it shows access heatmap
and distributions of working set size and memory footprints. It will further
updated to provide more detailed information in a concise manner, and add the
hot functions information.
For example:
```
$ sudo damo record "./masim ./configs/stairs.cfg"
[...]
$ sudo damo report holistic
# Heatmap
# target 0, address range 94737092173824-94737384947712
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000
# x-axis: space (94737092173824-94737384947664: 279.211 MiB)
# y-axis: time (12681562920000-12741660534000: 1 m 0.098 s)
# resolution: 80x5 (3.490 MiB and 12.020 s for each character)
# target 0, address range 140223579160576-140223690682368
33333222222222222222222222222222222222232222222222222222222222222223666666500000
00000000000000000000000000000000000000000000000000002666677567777773333333300000
00000000000000000000000000000022222223777778667777772000000000000000000000000000
00000000000000045555554777777545555551000000000000000000000000000000000000000000
77777885777777512222220000000000000000000000000000000000000000000000000000000000
# x-axis: space (140223579160576-140223690682336: 106.355 MiB)
# y-axis: time (12681562920000-12741660534000: 1 m 0.098 s)
# resolution: 80x5 (1.329 MiB and 12.020 s for each character)
# target 0, address range 140725996015616-140725996150784
00000000000000000000000000000000000000000000000000000000000000000000000000068888
00000000000000000000000000000000000000000000000000000000000000000000000000068888
00000000000000000000000000000000000000000000000000000000000000000000000000067777
00000000000000000000000000000000000000000000000000000000000000000000000000067777
00000000000000000000000000000000000000000000000000000000000000000000000000067777
# x-axis: space (140725996015616-140725996150736: 131.953 KiB)
# y-axis: time (12681562920000-12741660534000: 1 m 0.098 s)
# resolution: 80x5 (1.649 KiB and 12.020 s for each character)
# Memory Footprints Distribution
percentile 0 25 50 75 100
wss 0 B 9.547 MiB 9.566 MiB 9.828 MiB 106.363 MiB
rss 100.879 MiB 100.879 MiB 100.879 MiB 100.879 MiB 100.879 MiB
vsz 104.535 MiB 104.535 MiB 104.535 MiB 104.535 MiB 104.535 MiB
sys_used 2.159 GiB 2.234 GiB 2.241 GiB 2.245 GiB 2.253 GiB
# Hotspot functions
# Samples: 680K of event 'cpu-clock:pppH'
# Event count (approx.): 170020000000
#
# Overhead Command Shared Object Symbol
# ........ ............... ..................................... ...........................................
#
63.01% swapper [kernel.vmlinux] [k] pv_native_safe_halt
34.96% masim masim [.] do_seq_wo
0.08% python3 python3.11 [.] _PyEval_EvalFrameDefault
0.07% ps [kernel.vmlinux] [k] do_syscall_64
0.05% ps [kernel.vmlinux] [k] memset_orig
0.04% ps libc.so.6 [.] open64
0.04% perf perf [.] __symbols__insert
0.03% ps libc.so.6 [.] read
0.03% ps libc.so.6 [.] __close
0.03% ps [kernel.vmlinux] [k] __memcg_slab_post_alloc_hook
```
Miscellaneous Helper Commands
=============================
Abovely explained commands are all core functions of `damo`. For more
convenient use of `damo` and debugging of DAMON or `damo` itself, `damo`
supports more commands. This section explains some of those that could be
useful for some cases.
`damo help`
-----------
Some commands including `damo start` and `damo report access` have long lists
of command line options. Those makes flexible usage of `damo`. Because the
long list makes the help message too verbose, many of the options that
unessential for simple usages are hidden by default. `damo help` can be used
for showing such hidden options.
`damo args`
-----------
Some commands including `damo start` and `damo report access` have long lists
of available (and hidden) command line options. Those makes flexible usage of
`damo`, but makes the usage bit complicated. For easy handling of such
arguments, `damo args` receives such partial command line options, compile
into full options, and print out in various formats including jsong and yaml.
The formatted outputs allow users easily understand what full options will be
generated. The json or yaml format can also be passed to relevant commands
instead of the command line options. Hence, if a user prefer editing the
options in json or yaml format using their personal favorite editor tools
rather than `damo`'s command line interface, they can use the 'damo args'
outputs as a template.
### `damo args damon`
As mentioned for `damo start` above, DAMON control commands including `start`,
`tune`, and additionally `record` allows passing DAMON parameters or DAMOS
specification all at once via json or yaml formats. That's for making
specifying and managing complex requests easier, but writing the whole json or
yaml manually could be annoying, while the partial DAMON/DAMOS parameters setup
command line options are easy for simple use case. To help formatting the json
or yaml input easier, `damo args damon` receives the partial DMAON/DAMOS
parameters setup options and print out resulting json format Kdamond
parameters. For example,
# damo args damon --damos_action stat --format json
prints json format DAMON parameters specification that will be result in a
DAMON configuration that same to one that can be made with `damo start
--damos_action stat`. In other words, `damo start $(damo args damon
--damos_action stat)` will be same to `damo start --damos_action stat`.
The output can be saved in a file instead of printing using `--out` option. To
read the output in more human-friendly way,
[`damo report damon`](#damo-report-damon) can be used.
#### report format
The command also supports `report` format, which is similar to the output of
[`damo report damon`](#damo-report-damon). The format is for human users who
feels `json` or even `yaml` format outputs being too verbose or difficult to
read. It means it is not for machines, and therefore cannot feed to other damo
commands.
#### Multiple kdamonds
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo args damon` was supporting only single kdamond by default, and hence
provided below ways to edit DAMON parameters for multiple kdamonds. From
v2.7.5, partial DAMON parameters update command line options support multiple
kdamonds use case via `--nr_ctxs`, `--nr_schemes` and `--nr_targets`. Read the
[section](#partial-damon-parameters-update) for more details. Below ways for
handling multiple kdamonds are still be supported for users who still prefer
it. If partial DAMON parameters command line options are proven to be useful
and stable, below ways might be deprecated in future.
`--add` option of `damo args damon` receives a file containing output from
other `damo args damon` execution. If the option is given, `damo args damon`
reads the DAMON parameters from the file. Then, it further generates DAMON
parameters with command line options other than `--add` that given to `damo
args damon`, add the newly generated kdamond parameters to those from the file,
and print the resulting parameters. Note that users can save the output to a
file instead of printing, via `--out` option. For example, below commands will
create `kdamonds.json` file that contains two kdamonds running `migrate_hot`
and `migrate_cold` DAMOS actions respectively.
# damo args damon --damos_action migrate_hot 0 --out kdamonds.json
# damo args damon --damos_action migrate_cold 1 \
--add kdamonds.json --out kdamonds.json
`--replace` option of `damo args damon` receives a file containing output from
other `damo args damon` execution, and the index of the kdamond in the file
that the user wants to remove. If the option is given, `damo args damon` reads
the DAMON parameters from the file, replace the kdamond parameters of the index
with DAMON parameters that generated by `damo args damon` options except
`--replace`, and prints resulting parameters. For example, below command will
replace the kdamond for `migrate_cold` from the `kdamonds.json` file that
generated above, with another kdamond for `pageout` instead, and save the
resulting updated kdamond parameters to `kdamonds.json`.
# damo args damon --damos_action pageout --replace kdamonds.json 1 --out kdamonds.json
`--remove` option of `damo args damon` receives a file containing output from
other `damo args damon` execution, and the index of the kdamond in the file
that the user wants to remove. If the option is given, `damo args damon` reads
the DAMON parameters from the file, remove the kdamond parameters of the index,
and prints resulting parameters. For example, below command will remove the
kdamond for `pageout` from the `kdamonds.json` file that updated above, and
save the resulting single kdamond parameters to `kdamonds.json`.
# damo args damon --remove kdamonds.json 1 --out kdamonds.json
`damo report damon` with `--input_file` option can receive the `damo args
damon` generated output and show the DAMON parameters in a format that more
human friendly than json or yaml. `--damon_params` option can also be used to
make the output focus on only parameters. For example, abovely generated
parameters can be shown as below.
```
$ sudo ./damo report damon --damon_params --input_file kdamonds.json
kdamond 0
context 0
ops: paddr
target 0
region [4,294,967,296, 68,577,918,975) (59.868 GiB)
intervals: sample 5 ms, aggr 100 ms, update 1 s
nr_regions: [10, 1,000]
scheme 0
action: migrate_hot to node 0 per aggr interval
target_nid: 0
target access pattern
sz: [0 B, max]
nr_accesses: [0 %, 18,446,744,073,709,551,616 %]
age: [0 ns, max]
quotas
0 ns / 0 B / 0 B per max
priority: sz 0 %, nr_accesses 0 %, age 0 %
watermarks
metric none, interval 0 ns
0 %, 0 %, 0 %
```
`damo dianose`
--------------
Note: This is an experimental feature at the moment. Some changes could be
made, or the support can be dropped in future.
`damo diagnose` prints the status of DAMON and any behaviors that suspicious to
be bugs of DAMON. Hence, the command can be useful for investigation of DAMON
bugs. When you report any issue for DAMON that not easy to be reproduced,
providing the 'damo diagnose' output together with the issue report can be
helpful.
`damo version`
--------------
`damo version` shows the version of the installed `damo`. The version number
is constructed with three numbers. `damo` is doing chronological release
(about once per week), so the version number means nothing but the relative
time of the release. Later one would have more features and bug fixes.
`damo replay` (Replay Recorded Data Access Pattern)
---------------------------------------------------
Note: This feature is an experimental one. Some changes could be made, or the
support can be dropped in future.
`damo replay` receives a `damo record`-generated data access pattern record
file that specified via command line argument (`./damon.data` by default).
Then, the command reproduces the recorded accesses in the file by making
articial memory accesses. This could be useful for some types of system
analysis or experiments with real-world memory access pattern.
Note that current implementation of `damo replay` runs on Python with single
thread. Hence it might not performant enough to saturate full memory bandwidth
of the system. If the record is made by workloads and/or systems that utilize
memory bandwidth more than 'damo replay' and/or replaying systems could, and as
the difference of the performance is big, the replayed accesses would be less
similar to the original one. To show the real memory access performance of
`damo replay` on specific system, users could use `--test_perf` option.
Write-only and CPUs-only Access Monitoring (EXPERIMENTAL)
---------------------------------------------------------
Note: These features are extremely experimental. Many changes would be made
and the support can be dropped in future.
On Linux kernel built with some hacks that exist in
[damon/next](https://git.kernel.org/pub/scm/linux/kernel/git/sj/linux.git/log/?h=damon/next)
tree as of this writing (2025-08-03), users can do data access monitoring for
only writes, or for accesses made by given set of CPUs using `damo`.
Currently, only physical address space monitoring supports this.
### Write-only Access Monitoring
Users can do write-only data access monitoring by adding
`--exp_ops_use_reports` and `--exp_ops_write_only` options with value `y` to
the usual DAMON parameters setup commands including `damo start` and `damo
tune`, like below.
damo start --exp_ops_use_reports y --exp_ops_write_only y
Then all access monitoring results will silently ignore read accesses, and show
only the accesses that made for writes.
Note that only physical address space monitoring is supported for now.
### CPUs-only Access Monitoring
Users can monitor the data accesses made by only specific CPUs by adding
`--exp_ops_use_reports` and `--exp_ops_cpus` options to the usual DAMON
parameters setup commands including `damo start` and `damo tune`, like below.
damo start --exp_ops_use_reports y --exp_ops_cpus 0-3,5-7,9
`--exp_ops_use_reports` argument should always be `y`.
`--exp_ops_cpus` option should be given with a list of the desired CPUs. In
this example, accesses that made by only CPUs of id 0, 1, 2, 3, 5, 6, 7, or 9
will be monitored and reported. The format of the cpus list is same to that
for
[cpuset.cpus](https://docs.kernel.org/admin-guide/cgroup-v2.html#cpuset-interface-files)
file of cgroup v2.
Note that only physical address space monitoring is supported for now.
### Cautions and Plan to Drop Experimental Tag
The write-only and cpus-only monitoring features require changes in Linux
kernel that not yet upstreamed. The changes are available at
[damon/next](https://git.kernel.org/pub/scm/linux/kernel/git/sj/linux.git/log/?h=damon/next)
tree, which is for containing under-development DAMON works, as of this writing
(2025-08-03). To make those upstreamed, we may need significant amount of
efforts. Many changes could be made on the upstreamed version. In the worst
case, we would forgive upstreaming the changes to mainline kernel, and drop the
support on the damon/next tree.
The user interface for these features on `damo` will definitely be changed in
future. At least, `--exp_` part will be removed.
Finally, as of this writing (2025-08-03), the features are nearly not tested,
so there could be many bugs.
So, please feel free to try and let us know bugs that you found, and if it is
useful and worthy enough to make the upstream efforts. But, please don't make
your long term important works depend on these.