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
=============

Basic Concepts of DAMON
-----------------------

`damo` is a user space tool for [`DAMON`](https://docs.kernel.org/mm/damon/).
If you finished "Getting Started" tutorial and want to use `damo` in more
advanced and optimized way, you may need to 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.

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 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.

Command Line Auto-completion
----------------------------

`damo` supports the tab key based command line auto-completion, like other CLI
tools.  When it is enabled, `damo` will suggest useful inputs for partially
completed command line inputs.  Run `damo setup_cli_completion` to get help on
enabling it.  For example:

```
$ ./damo setup_cli_completion
It is nearly done, and need one more step.
Please execute "source /tmp/damo_completion_script-pqbiyvpu" on your shell.

Note that this works only for the current shell session.
For permanent completion setup, save "/tmp/damo_completion_script-pqbiyvpu" somewhere,
and modify your .bashrc like things to execute the
"source" of the saved file for every session.
```

Note that the suggestions are only for common and recommended choices.  That's
because there are quite many options that might make users only confused.  It
may therefore not give you full available choices always.  If you really need
to know full available choices, use [`damo help`](#damo-help).

Overview
========

`damo` provides a subcommands-based interface.  You can show the list of the
available commands and brief description of those via `damo --help`.  It's
command line [auto-completion](#command-line-auto-completion) should also be
helpful.  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 Availability Check
------------------------

The first category commands require some system setups.  That is, the system
should be configured in a way that DAMON can be used.  To check the
availability, please use [`damo report sysinfo`](#damo-report-sysinfo) command.
Please read the document [section](#damo-report-sysinfo) for more details about
the command.

Note that the visualization part of the second category commands and the third
category (misc helers) are independent to DAMON, and therefore can be used on
nearly every setup.  It is common and fully supported to run DAMON and collect
outputs of it on a machine, and do visualizations of the outputs on another
machines.

DAMON Control (Access Monitoring and Monitoring-based System Optimization)
==========================================================================

The main purposes of `damo` is operating DAMON, as the name says (DAMO: DAMon
Operator).  In other words, `damo` is for helping control of DAMON and
retrieval/interpretation of the results.

`damo start`
------------

`damo start` make DAMON in kernel starts running as users request.  Users can
specify how and to what address spaces DAMON should do monitor accesses, and do
what access-aware system operations.  The request can be made via several
command line options of the command.

Refer to [`mem_tier.sh`](./scripts/mem_tier.sh) and
[`lru_sort.sh`](./scripts/lru_sort.sh) files under [`scripts/`](./scripts/)
directory of `damo` source tree 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.

If the user wants to monitor the entire physical address space of the system, a
special keyword, `paddr` can be passed.  For example:

    # damo start paddr

If the user wants to monitor a virtual address space of a process, the command
for starting the monitoring target process, or the pid of running target
process can be passed.

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)

### Partial DAMON Parameters Update

`damo` sets DAMON parameters such as [monitoring
intervals](https://docs.kernel.org/mm/damon/design.html#access-frequency-monitoring)
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 is 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 is for specifying each [DAMOS
filter](https://docs.kernel.org/mm/damon/design.html#filters) that need to be
installed for the access-aware system operations.

The option 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.

`<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 same to what the [kernel
documentation](https://docs.kernel.org/mm/damon/design.html#filters) lists.

If the filter is for memory except 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 use multiple `--snapshot_damos_filter`.  For
example,

```
--damos_filter allow anon --damos_filter reject memcg user.slice/workloads/foo
```

Will install two DAMOS filters in same way.

##### 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

In some use cases, users might prefer specifying the full DAMON parameters in
other structured formats like `json` or `yaml`.  For such users, DAMON-control
`damo` commands support `--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).

(Historical fun facts)
In the past, the partial DAMON parameters update command line options supported
only single kdamond and single DAMON context.  That was the main reason of
`--kdamonds` option.  The restriction is gone on the current version of `damo`.
Nowadays, partial DAMON parameters command line option is more recommended.
Refer to [`scripts/mem_tier.sh`](./scripts/mem_tier.sh) for example of such
multiple kdamonds usage.

### Full DAMOS Parameters Update

Same to [Full DAMON Parameters Update](full-damon-parameters-update), some
users might prefer specifying the full DAMOS parameters in other structured
formats like `json` or `yaml`.  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)


### Pre-requisites: `perf` and/or `trace-cmd`

`damo` uses [`perf`](https://perf.wiki.kernel.org/index.php/Main_Page) for
recording DAMON's access monitoring results.  If it is unavailable, `damo` uses
[`trace-cmd`](https://www.trace-cmd.org/) instead.  Please ensure your system
is having `perf` or `trace-cmd` if you will need to record full monitoring
results of DAMON.  Note that `damo` supports not only full recording but
also partial snapshots (`damo record --snpashot` option or [`damo report
access`](#damo-report-access)).  If you will do the partial snapshots recording
instead of the full recording, you don't need to install `perf` or `trace-cmd`
on your system.

`perf` is also internally used for
[recording cpu usages](#recording-cpu-usages).  If it is unavailable, the cpu
usages recording will do nothing.

### 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 CPU usage profile information together in
addition to the DAMON outputs.  Internally, it runs `perf record` while `damo
record` is running, and store the `perf` output as a file of a 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 footprint information of the record target
processes and the system in addition to the DAMON outputs.  Internally, it
parses `/proc/meminfo` and `/proc/<pid>/statm` files (`<pid>` is that of the
monitoring target process) 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 various purposes.  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 and/or system
information 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 each report format.
Following sections describe some of the report formats.

### `damo report sysinfo`

`damo report sysinfo` shows the system information including versions of
software and DAMON features that available on the system.  By default, it shows
versions of software and available DAMON user interface features, like below.

```
$ sudo damo report sysinfo
damo version: v3.1.6-1-g3946ed6d
kernel version: 6.19.0-mm-new-damon+
DAMON version: 6.19+
available DAMON features:
- interface/damon_sysfs (merged in v5.18-rc1 (c951cd3b8901))
- interface/damon_reclaim (merged in v5.16-rc1 (43b0536cb471))
- interface/damon_lru_sort (merged in v6.0-rc1 (40e983cca927))
- interface/damon_stat (merged in v6.17-rc1 (369c415e6073))
```

The first two lines of the output are straightforwardly showing the versions of
`damo` and `kernel`.  The third line shows an inferred version of DAMON.  This
inference can be useful if the kernel have DAMON features that backported from
the mainline.  For the inference, `damo` checks all DAMON features that
available on the current system.  And it finds the available feature that
landed on the mainline most recently.  And conclude the version of the mainline
Linux release as the version of DAMON on the system.

Fourth and later lines of the output shows the available DAMON user interface
features.  If it shows nothing, the system may not ready to run `damo` commands
for controlling DAMON (`start` and `tune`)  and recording its outputs (`damo
record`).  Note that other categories of commands such as visualization of the
retrieved DAMON outputs (`damo report`) are independent to the system setup,
and therefore still available.  If you need to do DAMON control on a given
system but `damo report sysinfo` says it is unavailable, ask help to the system
administrator, the kernel provider, or DAMON community.

The command can show more detailed information including availability of each
DAMON features, when `--print all` option is given.

### `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` 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.

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, the total size of the regions that are listed on the output, and the
monitoring intervals that used for the snapshot, 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.  Another name of it is `idle-time-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.  Another name of it is `cold-memory-tail`.  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

`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
still 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 objects 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`](./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 the 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 understanding.

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 patterns.  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`).
Snapshots of data access patterns follow.  Each snapshot is separated by a
blank line.  Each snapshot first specifies when the monitoring for the snapshot
is started (`monitoring_start`) and ended (`monitoring_end`) relative to the
start time, and the duration for the snapshot (`monitoring_duration`).
Captured 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, `damo report record_info` option can be used as
below:

    $ sudo damo report record_info
    target_id: 0
    time: [24 h 18 m 44.639 s, 24 h 19 m 10.276 s) (25.637 s)
    region   0: [85.599282 TiB, 85.599692 TiB) (429.754 MiB)
    region   1: [127.519339 TiB, 127.519435 TiB) (100.840 MiB)
    region   2: [127.997318 TiB, 127.997318 TiB) (132.000 KiB)

The output shows unions of monitored regions and the union of monitored time
duration of each target task.  On this example output, we can show huge address
gap between the regions.  ~40 TiB gap between regions 0 and 1.  ~400 GiB gap
between regions 1 and 2.  Therefore, it would be wise to plot the data
points in each region.

Based on this output, users can plot the heatmap for only region 1 like below:

    $ sudo damo report heatmap --address_range "127.519339 TiB" "127.519435 TiB"

If no axis boundary option is given, it will automatically find the union
having most heats per size in `report record_info` 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.
