damo 3.3.2__tar.gz → 3.3.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {damo-3.3.2 → damo-3.3.4}/PKG-INFO +5 -5
- {damo-3.3.2 → damo-3.3.4}/README.md +4 -4
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_records.py +40 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon.py +68 -5
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon_args.py +93 -30
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon_features.py +16 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon_sysfs.py +44 -2
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_attrs.py +3 -93
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_version.py +1 -1
- {damo-3.3.2 → damo-3.3.4}/src/damo.egg-info/PKG-INFO +5 -5
- {damo-3.3.2 → damo-3.3.4}/pyproject.toml +0 -0
- {damo-3.3.2 → damo-3.3.4}/setup.cfg +0 -0
- {damo-3.3.2 → damo-3.3.4}/setup.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/__init__.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_ascii_color.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_deprecated.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_deprecation_notice.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_dist.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_fmt_str.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_fs.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_print.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_subcmds.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_subproc.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_sysinfo.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_trace.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damo_yaml.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon_dbgfs.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/_damon_modules.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_adjust.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_args.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_args_accesses_filter.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_args_accesses_format.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_args_damon.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_convert_record_format.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_diagnose.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_features.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_help.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_help_access_filter_options.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_help_access_format_options.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_help_damon_param_options.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_lru_sort.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_module.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_module_general.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_module_stat.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_monitor.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_nr_regions.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_pa_layout.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_reclaim.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_record.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_record_info.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_replay.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_access.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_damon.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_footprint.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_heatmap.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_holistic.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_pa_layout.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_profile.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_record_info.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_sysinfo.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_times.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_report_trace.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_schemes.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_setup_cli_completion.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_start.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_stop.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_tune.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_validate.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo/damo_wss.py +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo.egg-info/SOURCES.txt +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo.egg-info/dependency_links.txt +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo.egg-info/entry_points.txt +0 -0
- {damo-3.3.2 → damo-3.3.4}/src/damo.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: damo
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.4
|
|
4
4
|
Summary: DAMON user-space tool
|
|
5
5
|
Home-page: https://github.com/damonitor/damo
|
|
6
6
|
Author: SeongJae Park
|
|
@@ -71,7 +71,7 @@ The second and last commands will show the access pattern of your workload,
|
|
|
71
71
|
like below:
|
|
72
72
|
|
|
73
73
|

|
|
74
|
-

|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
FAQs
|
|
@@ -90,7 +90,7 @@ Where can I get more detailed usage?
|
|
|
90
90
|
------------------------------------
|
|
91
91
|
|
|
92
92
|
The below sections provide quick introductions for `damo`'s major features.
|
|
93
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
93
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
What does the version numbers mean?
|
|
@@ -115,7 +115,7 @@ We try our best to make `damo` stable and doesn't introduce regressions to
|
|
|
115
115
|
users. However, nothing goes forever. Sometimes, some features will be
|
|
116
116
|
deprecated. Some features will have longer support more than others.
|
|
117
117
|
|
|
118
|
-
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
118
|
+
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) and not explicitly
|
|
119
119
|
marked as experimental will be better supported, and provides at least three
|
|
120
120
|
months of deprecation grace period. Within the grace period, users can ask
|
|
121
121
|
extension of the support. Even after the grace period, please reach out to
|
|
@@ -138,7 +138,7 @@ Quick Intro for Major Features
|
|
|
138
138
|
==============================
|
|
139
139
|
|
|
140
140
|
Below are quick introductions for `damo`'s major features.
|
|
141
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
141
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
Snapshot Data Access Pattern
|
|
@@ -47,7 +47,7 @@ The second and last commands will show the access pattern of your workload,
|
|
|
47
47
|
like below:
|
|
48
48
|
|
|
49
49
|

|
|
50
|
-

|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
FAQs
|
|
@@ -66,7 +66,7 @@ Where can I get more detailed usage?
|
|
|
66
66
|
------------------------------------
|
|
67
67
|
|
|
68
68
|
The below sections provide quick introductions for `damo`'s major features.
|
|
69
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
69
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
What does the version numbers mean?
|
|
@@ -91,7 +91,7 @@ We try our best to make `damo` stable and doesn't introduce regressions to
|
|
|
91
91
|
users. However, nothing goes forever. Sometimes, some features will be
|
|
92
92
|
deprecated. Some features will have longer support more than others.
|
|
93
93
|
|
|
94
|
-
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
94
|
+
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) and not explicitly
|
|
95
95
|
marked as experimental will be better supported, and provides at least three
|
|
96
96
|
months of deprecation grace period. Within the grace period, users can ask
|
|
97
97
|
extension of the support. Even after the grace period, please reach out to
|
|
@@ -114,7 +114,7 @@ Quick Intro for Major Features
|
|
|
114
114
|
==============================
|
|
115
115
|
|
|
116
116
|
Below are quick introductions for `damo`'s major features.
|
|
117
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
117
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
118
118
|
|
|
119
119
|
|
|
120
120
|
Snapshot Data Access Pattern
|
|
@@ -246,6 +246,28 @@ class DamonRecord:
|
|
|
246
246
|
self.snapshots += other.snapshots
|
|
247
247
|
self.snapshots.sort(key=lambda s: s.start_time)
|
|
248
248
|
|
|
249
|
+
class DamoRecords:
|
|
250
|
+
kdamonds = None # list of _damon.Kdamond
|
|
251
|
+
records = None # list of DamonRecord
|
|
252
|
+
|
|
253
|
+
def __init__(self, kdamonds, records):
|
|
254
|
+
if kdamonds is None:
|
|
255
|
+
kdamonds = []
|
|
256
|
+
if records is None:
|
|
257
|
+
records = []
|
|
258
|
+
self.kdamonds = kdamonds
|
|
259
|
+
self.records = records
|
|
260
|
+
|
|
261
|
+
@classmethod
|
|
262
|
+
def from_kvpairs(self, kv):
|
|
263
|
+
return DamoRecords(kdamonds=kv['kdamonds'], records=kv['records'])
|
|
264
|
+
|
|
265
|
+
def to_kvpairs(self, raw=False):
|
|
266
|
+
return collections.OrderedDict([
|
|
267
|
+
('kdamonds', [k.to_kvapairs(raw=raw) for k in self.kdamonds]),
|
|
268
|
+
('records', [r.to_kvpairs(raw=raw) for r in self.records]),
|
|
269
|
+
])
|
|
270
|
+
|
|
249
271
|
# for monitoring results manipulation
|
|
250
272
|
|
|
251
273
|
def merge_records(records):
|
|
@@ -539,6 +561,11 @@ def parse_perf_damon_record(
|
|
|
539
561
|
|
|
540
562
|
def parse_json(json_str):
|
|
541
563
|
kvpairs = json.loads(json_str)
|
|
564
|
+
damo_record_ver = 0
|
|
565
|
+
if 'damo_reocrd_ver' in kvpairs:
|
|
566
|
+
damo_record_ver = kvpairs['damo_record_ver']
|
|
567
|
+
if damo_record_ver == 1:
|
|
568
|
+
return DamoRecords.from_kvpairs(kvpairs['damo_records'])
|
|
542
569
|
return [DamonRecord.from_kvpairs(kvp) for kvp in kvpairs]
|
|
543
570
|
|
|
544
571
|
def parse_compressed_json(record_file):
|
|
@@ -1913,6 +1940,19 @@ def get_records(tried_regions_of=None, record_file=None,
|
|
|
1913
1940
|
filter_copy.filter_records(records)
|
|
1914
1941
|
return records, None
|
|
1915
1942
|
|
|
1943
|
+
def get_damo_records(
|
|
1944
|
+
tried_regions_of=None, record_file=None, snapshot_damos_filters=None,
|
|
1945
|
+
record_filter=None, total_sz_only=False, dont_merge_regions=True):
|
|
1946
|
+
'''
|
|
1947
|
+
Returns DamoRecords and err.
|
|
1948
|
+
'''
|
|
1949
|
+
damon_records, err = get_records(
|
|
1950
|
+
tried_regions_of, record_file, snapshot_damos_filters,
|
|
1951
|
+
record_filter, total_sz_only, dont_merge_regions)
|
|
1952
|
+
if err is not None:
|
|
1953
|
+
return None, err
|
|
1954
|
+
return DamoRecords(kdamonds=[], records=[damon_records]), None
|
|
1955
|
+
|
|
1916
1956
|
def parse_sort_bytes_ranges_input(bytes_ranges_input):
|
|
1917
1957
|
try:
|
|
1918
1958
|
ranges = [[_damo_fmt_str.text_to_bytes(start),
|
|
@@ -15,6 +15,50 @@ import _damo_fmt_str
|
|
|
15
15
|
|
|
16
16
|
# Core data structures
|
|
17
17
|
|
|
18
|
+
prep_action_set_pgidle = 'set_pgidle'
|
|
19
|
+
|
|
20
|
+
prep_actions = [
|
|
21
|
+
prep_action_set_pgidle,
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
class DamonPrep:
|
|
25
|
+
prep_action = None
|
|
26
|
+
|
|
27
|
+
def __init__(self, prep_action=prep_action_set_pgidle):
|
|
28
|
+
if not prep_action in prep_actions:
|
|
29
|
+
raise Exception('wrong prep action (%s)' % prep_action)
|
|
30
|
+
|
|
31
|
+
self.prep_action = prep_action
|
|
32
|
+
|
|
33
|
+
def to_str(self, raw):
|
|
34
|
+
return self.prep_action
|
|
35
|
+
|
|
36
|
+
def __str__(self):
|
|
37
|
+
return self.to_str(False)
|
|
38
|
+
|
|
39
|
+
def __eq__(self, other):
|
|
40
|
+
return type(self) == type(other) and \
|
|
41
|
+
self.prep_action == other.prep_action
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def from_kvpairs(cls, kv):
|
|
45
|
+
return DamonPrep(prep_action=kv['prep_action'])
|
|
46
|
+
|
|
47
|
+
def to_kvpairs(self, raw=False):
|
|
48
|
+
return collections.OrderedDict([
|
|
49
|
+
('prep_action', self.prep_action),
|
|
50
|
+
])
|
|
51
|
+
|
|
52
|
+
damon_filter_type_anon = 'anon'
|
|
53
|
+
damon_filter_type_memcg = 'memcg'
|
|
54
|
+
damon_filter_type_pgidle_unset = 'pgidle_unset'
|
|
55
|
+
|
|
56
|
+
damon_filter_types = [
|
|
57
|
+
damon_filter_type_anon,
|
|
58
|
+
damon_filter_type_memcg,
|
|
59
|
+
damon_filter_type_pgidle_unset,
|
|
60
|
+
]
|
|
61
|
+
|
|
18
62
|
class DamonFilter:
|
|
19
63
|
filter_type = None # anon, memcg
|
|
20
64
|
matching = None
|
|
@@ -22,6 +66,8 @@ class DamonFilter:
|
|
|
22
66
|
path = None
|
|
23
67
|
|
|
24
68
|
def __init__(self, filter_type, matching, allow=False, path=None):
|
|
69
|
+
if not filter_type in damon_filter_types:
|
|
70
|
+
raise Exception('wrong damon filter type (%s)' % filter_type)
|
|
25
71
|
self.filter_type = filter_type
|
|
26
72
|
self.matching = _damo_fmt_str.text_to_bool(matching)
|
|
27
73
|
self.allow = _damo_fmt_str.text_to_bool(allow)
|
|
@@ -36,10 +82,9 @@ class DamonFilter:
|
|
|
36
82
|
if self.matching is False:
|
|
37
83
|
words.append('non')
|
|
38
84
|
words.append(self.filter_type)
|
|
39
|
-
if self.filter_type in ['anon']:
|
|
40
|
-
return ' '.join(words)
|
|
41
85
|
if self.filter_type == 'memcg':
|
|
42
86
|
return ' '.join(words + [self.path])
|
|
87
|
+
return ' '.join(words)
|
|
43
88
|
|
|
44
89
|
def __str__(self):
|
|
45
90
|
return self.to_str(False)
|
|
@@ -67,8 +112,9 @@ class DamonFilter:
|
|
|
67
112
|
class DamonProbe:
|
|
68
113
|
filters = None
|
|
69
114
|
weight = None
|
|
115
|
+
preps = None
|
|
70
116
|
|
|
71
|
-
def __init__(self, filters, weight=None):
|
|
117
|
+
def __init__(self, filters, weight=None, preps=None):
|
|
72
118
|
if type(filters) is not list:
|
|
73
119
|
raise Exception('filters for DamonProbe() is not a list')
|
|
74
120
|
self.filters = filters
|
|
@@ -77,9 +123,19 @@ class DamonProbe:
|
|
|
77
123
|
if type(weight) is not int:
|
|
78
124
|
raise Exception('weight is not an int')
|
|
79
125
|
self.weight = weight
|
|
126
|
+
if preps is None:
|
|
127
|
+
preps = []
|
|
128
|
+
if type(preps) is not list:
|
|
129
|
+
raise Exception('preps is not a list')
|
|
130
|
+
self.preps = preps
|
|
80
131
|
|
|
81
132
|
def to_str(self, raw):
|
|
82
|
-
words = [
|
|
133
|
+
words = []
|
|
134
|
+
if len(self.preps) > 0:
|
|
135
|
+
words.append('prep: %s' % ', '.join([
|
|
136
|
+
prep.to_str(raw) for prep in self.preps]))
|
|
137
|
+
words.append(', filter: ')
|
|
138
|
+
words.append(', '.join([f.to_str(raw) for f in self.filters]))
|
|
83
139
|
words.append(' (weight: %s)' % self.weight)
|
|
84
140
|
return ''.join(words)
|
|
85
141
|
|
|
@@ -89,19 +145,26 @@ class DamonProbe:
|
|
|
89
145
|
def __eq__(self, other):
|
|
90
146
|
return type(self) == type(other) and \
|
|
91
147
|
self.filters == other.filters and \
|
|
92
|
-
self.weight == other.weigt
|
|
148
|
+
self.weight == other.weigt and \
|
|
149
|
+
self.preps == other.preps
|
|
93
150
|
|
|
94
151
|
@classmethod
|
|
95
152
|
def from_kvpairs(cls, kv):
|
|
153
|
+
if 'preps' in kv:
|
|
154
|
+
preps = [DamonPrep.from_kvpairs(pkv) for pkv in kv['preps']]
|
|
155
|
+
else:
|
|
156
|
+
preps = []
|
|
96
157
|
return DamonProbe(
|
|
97
158
|
filters=[
|
|
98
159
|
DamonFilter.from_kvpairs(filter_kv)
|
|
99
160
|
for filter_kv in kv['filters']],
|
|
100
161
|
weight=kv.get('weight', None),
|
|
162
|
+
preps=preps,
|
|
101
163
|
)
|
|
102
164
|
|
|
103
165
|
def to_kvpairs(self, raw=False):
|
|
104
166
|
return collections.OrderedDict([
|
|
167
|
+
('preps', [p.to_kvpairs(raw) for p in self.preps]),
|
|
105
168
|
('filters', [f.to_kvpairs(raw) for f in self.filters]),
|
|
106
169
|
('weight', self.weight),
|
|
107
170
|
])
|
|
@@ -752,6 +752,16 @@ def gen_assign_schemes(ctxs, args):
|
|
|
752
752
|
scheme_idx += nr
|
|
753
753
|
return None
|
|
754
754
|
|
|
755
|
+
def probe_preps_for(preps_args):
|
|
756
|
+
preps = []
|
|
757
|
+
for prep_action in preps_args:
|
|
758
|
+
try:
|
|
759
|
+
prep = _damon.DamonPrep(prep_action=prep_action)
|
|
760
|
+
except Exception as e:
|
|
761
|
+
return None, 'prep creation fail (%s)' % e
|
|
762
|
+
preps.append(prep)
|
|
763
|
+
return preps, None
|
|
764
|
+
|
|
755
765
|
def probe_filter_for(filter_arg_fields):
|
|
756
766
|
fields = filter_arg_fields
|
|
757
767
|
if len(fields) < 2:
|
|
@@ -790,13 +800,25 @@ def probe_filters_for(filters_args):
|
|
|
790
800
|
return filters, None
|
|
791
801
|
|
|
792
802
|
def probes_for(args):
|
|
803
|
+
preps, err = probe_preps_for(args.probe_prep)
|
|
804
|
+
if err is not None:
|
|
805
|
+
return None, err
|
|
806
|
+
if args.nr_probe_preps is None:
|
|
807
|
+
args.nr_probe_preps = [len(preps)]
|
|
808
|
+
if sum(args.nr_probe_preps) != len(preps):
|
|
809
|
+
return None, '--nr_probe_preps mismatches --probe_prep (%d != %d)' % (
|
|
810
|
+
sum(args.nr_probe_preps), len(preps))
|
|
811
|
+
|
|
793
812
|
filters, err = probe_filters_for(args.probe_filter)
|
|
794
813
|
if err is not None:
|
|
795
814
|
return None, err
|
|
796
|
-
|
|
815
|
+
|
|
816
|
+
if len(preps) == 0 and len(filters) == 0:
|
|
797
817
|
return [], None
|
|
818
|
+
|
|
798
819
|
probes = []
|
|
799
820
|
filter_idx = 0
|
|
821
|
+
|
|
800
822
|
if args.nr_probe_filters is None:
|
|
801
823
|
args.nr_probe_filters = [len(args.probe_filter)]
|
|
802
824
|
if sum(args.nr_probe_filters) != len(filters):
|
|
@@ -810,11 +832,21 @@ def probes_for(args):
|
|
|
810
832
|
% (len(args.probe_weight), len(args.nr_probe_filters))
|
|
811
833
|
else:
|
|
812
834
|
args.probe_weight = [0 for _ in args.nr_probe_filters]
|
|
813
|
-
|
|
835
|
+
|
|
836
|
+
nr_probes = len(args.nr_probe_filters)
|
|
837
|
+
for i in range(nr_probes - len(preps)):
|
|
838
|
+
args.nr_probe_preps.append(0)
|
|
839
|
+
prep_idx = 0
|
|
840
|
+
|
|
841
|
+
for probe_idx, nr in enumerate(args.nr_probe_filters):
|
|
842
|
+
preps_for_probe = preps[
|
|
843
|
+
prep_idx:prep_idx + args.nr_probe_preps[probe_idx]]
|
|
814
844
|
filters_for_probe = filters[filter_idx:filter_idx + nr]
|
|
815
845
|
weight = args.probe_weight[len(probes)]
|
|
816
846
|
try:
|
|
817
|
-
probe = _damon.DamonProbe(
|
|
847
|
+
probe = _damon.DamonProbe(
|
|
848
|
+
preps=preps_for_probe, filters=filters_for_probe,
|
|
849
|
+
weight=weight)
|
|
818
850
|
except Exception as e:
|
|
819
851
|
return None, 'probe creation fail (%s)' % e
|
|
820
852
|
probes.append(probe)
|
|
@@ -947,6 +979,21 @@ def deduce_target_update_args(args):
|
|
|
947
979
|
print('warning: override --ops by <deducible target> and --regions')
|
|
948
980
|
args.ops = ['fvaddr']
|
|
949
981
|
|
|
982
|
+
def update_args_defaults(args):
|
|
983
|
+
# having default=[] makes complicated global shared states. Instantiate
|
|
984
|
+
# default values here.
|
|
985
|
+
for arg_name in [
|
|
986
|
+
'probe_prep', 'probe_filter', 'probe_weight', 'damos_action',
|
|
987
|
+
'damos_sz_region', 'damos_access_rate', 'damos_age',
|
|
988
|
+
'damos_apply_interval', 'damos_quotas', 'damos_quota_interval',
|
|
989
|
+
'damos_quota_time', 'damos_quota_space', 'damos_quota_weights',
|
|
990
|
+
'damos_quota_fail_charge_ratio', 'damos_quota_goal',
|
|
991
|
+
'damos_quota_goal_tuner', 'damos_nr_quota_goals', 'damos_filter',
|
|
992
|
+
'damos_nr_filters', 'damos_wmarks', 'damos_max_nr_snapshots',
|
|
993
|
+
]:
|
|
994
|
+
if getattr(args, arg_name) is None:
|
|
995
|
+
setattr(args, arg_name, [])
|
|
996
|
+
|
|
950
997
|
def warn_for(arg, feature):
|
|
951
998
|
if _damo_sysinfo.damon_feature_available(feature):
|
|
952
999
|
return
|
|
@@ -966,6 +1013,17 @@ def warn_unsupported_damon_features_for(args):
|
|
|
966
1013
|
if args.sample_primitives is not None:
|
|
967
1014
|
warn_for('--sample_primitives', 'sysfs/damon_sample_control')
|
|
968
1015
|
|
|
1016
|
+
if len(args.probe_prep) > 0:
|
|
1017
|
+
warn_for('--probe_prep', 'sysfs/probe_preps')
|
|
1018
|
+
for probe_filter_args in args.probe_filter:
|
|
1019
|
+
if _damon.damon_filter_type_pgidle_unset in args.probe_filter:
|
|
1020
|
+
warn_for(
|
|
1021
|
+
'--probe_filter of %s' %
|
|
1022
|
+
_damon.damon_filter_type_pgidle_unset,
|
|
1023
|
+
'sysfs/probe_type_pgidle_unset')
|
|
1024
|
+
|
|
1025
|
+
# mm.git
|
|
1026
|
+
|
|
969
1027
|
if args.probe_weight != []:
|
|
970
1028
|
warn_for('--probe_weight', 'sysfs/probe_weights')
|
|
971
1029
|
|
|
@@ -1158,6 +1216,7 @@ def warn_unsupported_damon_features_for(args):
|
|
|
1158
1216
|
['interface/damon_debugfs', 'interface/damon_sysfs'])
|
|
1159
1217
|
|
|
1160
1218
|
def evaluate_args(args):
|
|
1219
|
+
update_args_defaults(args)
|
|
1161
1220
|
warn_unsupported_damon_features_for(args)
|
|
1162
1221
|
|
|
1163
1222
|
'''
|
|
@@ -1385,8 +1444,16 @@ def set_monitoring_damos_common_args(parser, hide_help=False):
|
|
|
1385
1444
|
help='monitoring operations set'
|
|
1386
1445
|
if not hide_help else argparse.SUPPRESS)
|
|
1387
1446
|
|
|
1447
|
+
parser.add_argument('--probe_prep', action='append',
|
|
1448
|
+
metavar='<prep action>',
|
|
1449
|
+
help='data attribute monitoring probe prep'
|
|
1450
|
+
if not hide_help else argparse.SUPPRESS)
|
|
1451
|
+
parser.add_argument('--nr_probe_preps', type=int, nargs='+',
|
|
1452
|
+
metavar='<integer>',
|
|
1453
|
+
help='number of preps for each probe (in order)'
|
|
1454
|
+
if not hide_help else argparse.SUPPRESS)
|
|
1455
|
+
|
|
1388
1456
|
parser.add_argument('--probe_filter', nargs='+', action='append',
|
|
1389
|
-
default=[],
|
|
1390
1457
|
metavar='<<allow|reject> [non] <type> [option]...>',
|
|
1391
1458
|
help='data attribute monitoring probe filter'
|
|
1392
1459
|
if not hide_help else argparse.SUPPRESS)
|
|
@@ -1395,7 +1462,7 @@ def set_monitoring_damos_common_args(parser, hide_help=False):
|
|
|
1395
1462
|
help='number of filters for each probe (in order)'
|
|
1396
1463
|
if not hide_help else argparse.SUPPRESS)
|
|
1397
1464
|
parser.add_argument('--probe_weight', type=int, action='append',
|
|
1398
|
-
|
|
1465
|
+
metavar='<int>',
|
|
1399
1466
|
help='data attribute probe weight'
|
|
1400
1467
|
if not hide_help else argparse.SUPPRESS)
|
|
1401
1468
|
parser.add_argument(
|
|
@@ -1456,7 +1523,7 @@ def set_monitoring_argparser(parser, hide_help=False):
|
|
|
1456
1523
|
|
|
1457
1524
|
def set_damos_argparser(parser, hide_help):
|
|
1458
1525
|
parser.add_argument('--damos_action', metavar='<action>', nargs='+',
|
|
1459
|
-
action='append',
|
|
1526
|
+
action='append',
|
|
1460
1527
|
help=' '.join([
|
|
1461
1528
|
'damos action to apply to the target regions.',
|
|
1462
1529
|
'<action> should be {%s}.' %
|
|
@@ -1467,21 +1534,21 @@ def set_damos_argparser(parser, hide_help):
|
|
|
1467
1534
|
'should also be given.'
|
|
1468
1535
|
]))
|
|
1469
1536
|
parser.add_argument('--damos_sz_region', metavar=('<min>', '<max>'),
|
|
1470
|
-
nargs=2,
|
|
1537
|
+
nargs=2, action='append',
|
|
1471
1538
|
help='min/max size of damos target regions (bytes)'
|
|
1472
1539
|
if not hide_help else argparse.SUPPRESS)
|
|
1473
1540
|
parser.add_argument(
|
|
1474
|
-
'--damos_access_rate', metavar=('<min>', '<max>'),
|
|
1475
|
-
|
|
1541
|
+
'--damos_access_rate', metavar=('<min>', '<max>'), nargs=2,
|
|
1542
|
+
action='append',
|
|
1476
1543
|
help='min/max access rate of damos target regions (percent)'
|
|
1477
1544
|
if not hide_help else argparse.SUPPRESS)
|
|
1478
1545
|
parser.add_argument(
|
|
1479
1546
|
'--damos_age', metavar=('<min>', '<max>'), nargs=2,
|
|
1480
|
-
|
|
1547
|
+
action='append',
|
|
1481
1548
|
help='min/max age of damos target regions (microseconds)'
|
|
1482
1549
|
if not hide_help else argparse.SUPPRESS)
|
|
1483
1550
|
parser.add_argument('--damos_apply_interval', metavar='<microseconds>',
|
|
1484
|
-
action='append',
|
|
1551
|
+
action='append',
|
|
1485
1552
|
help='the apply interval for the scheme'
|
|
1486
1553
|
if not hide_help else argparse.SUPPRESS)
|
|
1487
1554
|
damos_quotas_help = ' '.join([
|
|
@@ -1490,32 +1557,31 @@ def set_damos_argparser(parser, hide_help):
|
|
|
1490
1557
|
'[<access rate priority weight> (permil)',
|
|
1491
1558
|
'[<age priority weight> (permil)]]]]])'])
|
|
1492
1559
|
parser.add_argument(
|
|
1493
|
-
'--damos_quotas',
|
|
1494
|
-
|
|
1560
|
+
'--damos_quotas', metavar='<quota parameter>', nargs='+',
|
|
1561
|
+
action='append',
|
|
1495
1562
|
help=damos_quotas_help if not hide_help else argparse.SUPPRESS)
|
|
1496
|
-
parser.add_argument('--damos_quota_interval',
|
|
1497
|
-
|
|
1563
|
+
parser.add_argument('--damos_quota_interval', metavar='<milliseconds>',
|
|
1564
|
+
action='append',
|
|
1498
1565
|
help='quota reset interval'
|
|
1499
1566
|
if not hide_help else argparse.SUPPRESS)
|
|
1500
|
-
parser.add_argument('--damos_quota_time',
|
|
1501
|
-
|
|
1567
|
+
parser.add_argument('--damos_quota_time', metavar='<milliseconds>',
|
|
1568
|
+
action='append',
|
|
1502
1569
|
help='time quota'
|
|
1503
1570
|
if not hide_help else argparse.SUPPRESS)
|
|
1504
|
-
parser.add_argument('--damos_quota_space',
|
|
1571
|
+
parser.add_argument('--damos_quota_space', metavar='<bytes>',
|
|
1505
1572
|
action='append', help='space quota'
|
|
1506
1573
|
if not hide_help else argparse.SUPPRESS)
|
|
1507
|
-
parser.add_argument('--damos_quota_weights',
|
|
1508
|
-
|
|
1574
|
+
parser.add_argument('--damos_quota_weights', metavar='<permil>', nargs=3,
|
|
1575
|
+
action='append',
|
|
1509
1576
|
help='quota\'s prioritization weights'
|
|
1510
1577
|
if not hide_help else argparse.SUPPRESS)
|
|
1511
|
-
parser.add_argument('--damos_quota_fail_charge_ratio',
|
|
1578
|
+
parser.add_argument('--damos_quota_fail_charge_ratio',
|
|
1512
1579
|
metavar=('<numerator>', '<denominator>'),
|
|
1513
1580
|
action='append', nargs=2,
|
|
1514
1581
|
help='quota failed regions charge ratio'
|
|
1515
1582
|
if not hide_help else argparse.SUPPRESS)
|
|
1516
1583
|
parser.add_argument(
|
|
1517
1584
|
'--damos_quota_goal', nargs='+', action='append',
|
|
1518
|
-
default=[],
|
|
1519
1585
|
metavar='<metric or value>',
|
|
1520
1586
|
help=' '.join([
|
|
1521
1587
|
'damos quota goal (<metric> <target value> [optional value]).',
|
|
@@ -1523,32 +1589,29 @@ def set_damos_argparser(parser, hide_help):
|
|
|
1523
1589
|
','.join(_damon.qgoal_metrics)])
|
|
1524
1590
|
if not hide_help else argparse.SUPPRESS)
|
|
1525
1591
|
parser.add_argument(
|
|
1526
|
-
'--damos_quota_goal_tuner', action='append',
|
|
1592
|
+
'--damos_quota_goal_tuner', action='append',
|
|
1527
1593
|
help='quota\'s goal-based tuner')
|
|
1528
1594
|
parser.add_argument(
|
|
1529
|
-
'--damos_nr_quota_goals', type=int, nargs='+',
|
|
1530
|
-
default=[], metavar='<integer>',
|
|
1595
|
+
'--damos_nr_quota_goals', type=int, nargs='+', metavar='<integer>',
|
|
1531
1596
|
help='number of quota goals for each scheme (in order)'
|
|
1532
1597
|
if not hide_help else argparse.SUPPRESS)
|
|
1533
1598
|
parser.add_argument(
|
|
1534
1599
|
'--damos_filter', nargs='+', action='append',
|
|
1535
|
-
default=[],
|
|
1536
1600
|
metavar='<<allow|reject> [none] <type> [option]...>',
|
|
1537
1601
|
help='damos filter' if not hide_help else argparse.SUPPRESS)
|
|
1538
1602
|
parser.add_argument(
|
|
1539
|
-
'--damos_nr_filters', type=int, nargs='+',
|
|
1540
|
-
metavar='<integer>',
|
|
1603
|
+
'--damos_nr_filters', type=int, nargs='+', metavar='<integer>',
|
|
1541
1604
|
help='number of filters for each scheme (in order)'
|
|
1542
1605
|
if not hide_help else argparse.SUPPRESS)
|
|
1543
1606
|
parser.add_argument(
|
|
1544
|
-
'--damos_wmarks', nargs=5, action='append',
|
|
1607
|
+
'--damos_wmarks', nargs=5, action='append',
|
|
1545
1608
|
metavar=('<metric (none|free_mem_rate)>', '<interval (us)>',
|
|
1546
1609
|
'<high mark (permil)>', '<mid mark (permil)>',
|
|
1547
1610
|
'<low mark (permil)>'),
|
|
1548
1611
|
help='damos watermarks'
|
|
1549
1612
|
if not hide_help else argparse.SUPPRESS)
|
|
1550
1613
|
parser.add_argument(
|
|
1551
|
-
'--damos_max_nr_snapshots', action='append',
|
|
1614
|
+
'--damos_max_nr_snapshots', action='append',
|
|
1552
1615
|
help='damos max_nr_snapshots')
|
|
1553
1616
|
parser.add_argument('--nr_schemes', metavar='<number>', nargs='+', type=int,
|
|
1554
1617
|
help='number of schemes for each context (in order)'
|
|
@@ -348,11 +348,27 @@ features_list = [
|
|
|
348
348
|
DamonFeature(name='sysfs/attrs_monitoring',
|
|
349
349
|
upstream_status='merged in v7.2-rc1 (45c49d9fd6089)',
|
|
350
350
|
upstreamed_version='7.2'),
|
|
351
|
+
DamonFeature(name='sysfs/probe_type_anon',
|
|
352
|
+
upstream_status='merged in v7.2-rc1 (8caba1448278)',
|
|
353
|
+
upstreamed_version='7.2'),
|
|
354
|
+
DamonFeature(name='sysfs/probe_type_memcg',
|
|
355
|
+
upstream_status='merged in v7.2-rc1 (c71f8e13462d)',
|
|
356
|
+
upstreamed_version='7.2'),
|
|
351
357
|
DamonFeature(name='trace/damon_region_aggregated',
|
|
352
358
|
upstream_status='merged in v7.2-rc1 (45c49d9fd6089)',
|
|
353
359
|
upstreamed_version='7.2'),
|
|
354
360
|
|
|
355
361
|
DamonFeature(name='sysfs/probe_weights',
|
|
362
|
+
upstream_status='merged into mm.git',
|
|
363
|
+
upstreamed_version='none'),
|
|
364
|
+
|
|
365
|
+
DamonFeature(name='sysfs/probe_preps',
|
|
366
|
+
upstream_status='hacking on damon/next',
|
|
367
|
+
upstreamed_version='none'),
|
|
368
|
+
DamonFeature(name='sysfs/probe_prep_set_pgidle',
|
|
369
|
+
upstream_status='hacking on damon/next',
|
|
370
|
+
upstreamed_version='none'),
|
|
371
|
+
DamonFeature(name='sysfs/probe_type_pgidle_unset',
|
|
356
372
|
upstream_status='hacking on damon/next',
|
|
357
373
|
upstreamed_version='none'),
|
|
358
374
|
|
|
@@ -570,6 +570,24 @@ def write_ops_attrs_dir(dir_path, ops_attrs):
|
|
|
570
570
|
if err is not None:
|
|
571
571
|
return err
|
|
572
572
|
|
|
573
|
+
def write_probe_prep_dir(dir_path, prep):
|
|
574
|
+
err = _damo_fs.write_file(
|
|
575
|
+
os.path.join(dir_path, 'prep_action'), prep.prep_action)
|
|
576
|
+
if err is not None:
|
|
577
|
+
return err
|
|
578
|
+
return None
|
|
579
|
+
|
|
580
|
+
def write_probe_preps_dir(dir_path, preps):
|
|
581
|
+
err = ensure_nr_file_for(os.path.join(dir_path, 'nr_preps'), preps)
|
|
582
|
+
if err is not None:
|
|
583
|
+
return err
|
|
584
|
+
|
|
585
|
+
for idx, prep in enumerate(preps):
|
|
586
|
+
err = write_probe_prep_dir(os.path.join(dir_path, '%d' % idx), prep)
|
|
587
|
+
if err is not None:
|
|
588
|
+
return err
|
|
589
|
+
return None
|
|
590
|
+
|
|
573
591
|
def write_probe_filter_dir(dir_path, filter):
|
|
574
592
|
err = _damo_fs.write_file(
|
|
575
593
|
os.path.join(dir_path, 'type'), filter.filter_type)
|
|
@@ -590,6 +608,12 @@ def write_probe_filter_dir(dir_path, filter):
|
|
|
590
608
|
return None
|
|
591
609
|
|
|
592
610
|
def write_probe_dir(dir_path, probe):
|
|
611
|
+
preps_dir = os.path.join(dir_path, 'preps')
|
|
612
|
+
if os.path.isdir(preps_dir):
|
|
613
|
+
err = write_probe_preps_dir(preps_dir, probe.preps)
|
|
614
|
+
if err is not None:
|
|
615
|
+
return err
|
|
616
|
+
|
|
593
617
|
filters_dir = os.path.join(dir_path, 'filters')
|
|
594
618
|
err = ensure_nr_file_for(os.path.join(filters_dir, 'nr_filters'),
|
|
595
619
|
probe.filters)
|
|
@@ -1056,16 +1080,27 @@ def files_content_to_target(files_content):
|
|
|
1056
1080
|
regions = files_content_to_regions(files_content['regions'])
|
|
1057
1081
|
return _damon.DamonTarget(pid, regions, obsolete=obsolete)
|
|
1058
1082
|
|
|
1083
|
+
def files_content_to_probe_preps(files_content):
|
|
1084
|
+
preps = []
|
|
1085
|
+
for kv in number_sorted_dirs(files_content):
|
|
1086
|
+
preps.append(_damon.DamonPrep(prep_action=kv['prep_action'].strip()))
|
|
1087
|
+
return preps
|
|
1088
|
+
|
|
1059
1089
|
def files_content_to_damon_filter(files_content):
|
|
1060
1090
|
path = None
|
|
1061
1091
|
if 'path' in files_content:
|
|
1062
|
-
files_content
|
|
1092
|
+
path = files_content['path'].strip()
|
|
1063
1093
|
return _damon.DamonFilter(
|
|
1064
1094
|
filter_type=files_content['type'].strip(),
|
|
1065
1095
|
matching=files_content['matching'].strip(),
|
|
1066
1096
|
allow=files_content['allow'].strip(), path=path)
|
|
1067
1097
|
|
|
1068
1098
|
def files_content_to_probe(files_content):
|
|
1099
|
+
if 'preps' in files_content:
|
|
1100
|
+
preps = files_content_to_probe_preps(files_content['preps'])
|
|
1101
|
+
else:
|
|
1102
|
+
preps = []
|
|
1103
|
+
|
|
1069
1104
|
filters_content = files_content['filters']
|
|
1070
1105
|
filters = []
|
|
1071
1106
|
for kv in number_sorted_dirs(filters_content):
|
|
@@ -1075,7 +1110,7 @@ def files_content_to_probe(files_content):
|
|
|
1075
1110
|
weight = int(files_content['weight'])
|
|
1076
1111
|
else:
|
|
1077
1112
|
weight = None
|
|
1078
|
-
return _damon.DamonProbe(filters=filters, weight=weight)
|
|
1113
|
+
return _damon.DamonProbe(preps=preps, filters=filters, weight=weight)
|
|
1079
1114
|
|
|
1080
1115
|
def files_content_to_probes(files_content):
|
|
1081
1116
|
probes = []
|
|
@@ -1450,6 +1485,8 @@ def mk_feature_supports_map():
|
|
|
1450
1485
|
if os.path.isdir(
|
|
1451
1486
|
os.path.join(ctx_dir_of(0, 0), 'monitoring_attrs', 'probes')):
|
|
1452
1487
|
supports_map['sysfs/attrs_monitoring'] = True
|
|
1488
|
+
supports_map['sysfs/probe_type_anon'] = True
|
|
1489
|
+
supports_map['sysfs/probe_type_memcg'] = True
|
|
1453
1490
|
|
|
1454
1491
|
|
|
1455
1492
|
if supports_map['sysfs/attrs_monitoring'] is True:
|
|
@@ -1473,6 +1510,11 @@ def mk_feature_supports_map():
|
|
|
1473
1510
|
if os.path.isfile(os.path.join(probe_dir, 'weight')):
|
|
1474
1511
|
supports_map['sysfs/probe_weights'] = True
|
|
1475
1512
|
|
|
1513
|
+
if os.path.isdir(os.path.join(probe_dir, 'preps')):
|
|
1514
|
+
supports_map['sysfs/probe_preps'] = True
|
|
1515
|
+
supports_map['sysfs/probe_prep_set_pgidle'] = True
|
|
1516
|
+
supports_map['sysfs/probe_type_pgidle_unset'] = True
|
|
1517
|
+
|
|
1476
1518
|
if os.path.isdir(os.path.join(ctx_dir_of(0, 0), 'operations_attrs')):
|
|
1477
1519
|
supports_map['sysfs/ops_attrs'] = True
|
|
1478
1520
|
|
|
@@ -339,15 +339,14 @@ def max_access_hz(intervals):
|
|
|
339
339
|
|
|
340
340
|
def snapshot_intervals_str(snapshot, record, fmt):
|
|
341
341
|
intervals = record.intervals
|
|
342
|
-
aggr_sample_ratio = intervals.aggr
|
|
342
|
+
aggr_sample_ratio = intervals.aggr // intervals.sample
|
|
343
343
|
snapshot_aggr_us = infer_aggr_time_us(snapshot, record)
|
|
344
344
|
snapshot_sample_us = snapshot_aggr_us / aggr_sample_ratio
|
|
345
|
-
max_access_hz = aggr_sample_ratio / (snapshot_aggr_us / 1000000)
|
|
346
345
|
|
|
347
|
-
return 'sample %s aggr %s (max
|
|
346
|
+
return 'sample %s aggr %s (max probe hits %s)' % (
|
|
348
347
|
_damo_fmt_str.format_time_us(snapshot_sample_us, fmt.raw_number),
|
|
349
348
|
_damo_fmt_str.format_time_us(snapshot_aggr_us, fmt.raw_number),
|
|
350
|
-
_damo_fmt_str.
|
|
349
|
+
_damo_fmt_str.format_nr(aggr_sample_ratio, fmt.raw_number))
|
|
351
350
|
|
|
352
351
|
def estimated_mem_bw(snapshot, record, fmt, filter_passed_only=False):
|
|
353
352
|
access_bytes = 0
|
|
@@ -768,95 +767,6 @@ def df_passed_heatmap_str(snapshot, record, fmt):
|
|
|
768
767
|
total_bytes=None),
|
|
769
768
|
record, fmt)
|
|
770
769
|
|
|
771
|
-
def rescale(val, orig_scale_minmax, new_scale_minmax, logscale=True):
|
|
772
|
-
'''Return a value in new scale
|
|
773
|
-
|
|
774
|
-
Parameters
|
|
775
|
-
----------
|
|
776
|
-
val : int, float
|
|
777
|
-
The value to rescale
|
|
778
|
-
orig_scale_minmax : list
|
|
779
|
-
min/max values of original scale
|
|
780
|
-
new_scale_minmax : list
|
|
781
|
-
min/max values of new scale
|
|
782
|
-
logscale : bool
|
|
783
|
-
whether to use logscale (True) or linearscale (False)
|
|
784
|
-
|
|
785
|
-
Returns
|
|
786
|
-
-------
|
|
787
|
-
float
|
|
788
|
-
The rescaled value
|
|
789
|
-
'''
|
|
790
|
-
|
|
791
|
-
if logscale:
|
|
792
|
-
log_val = math.log(val, 2) if val > 0 else 0
|
|
793
|
-
log_minmax = [math.log(v, 2) if v > 0 else 0
|
|
794
|
-
for v in orig_scale_minmax]
|
|
795
|
-
val = log_val
|
|
796
|
-
orig_scale_minmax = log_minmax
|
|
797
|
-
orig_length = orig_scale_minmax[1] - orig_scale_minmax[0]
|
|
798
|
-
new_length = new_scale_minmax[1] - new_scale_minmax[0]
|
|
799
|
-
ratio = new_length / orig_length if orig_length > 0 else 1
|
|
800
|
-
return (val - orig_scale_minmax[0]) * ratio + new_scale_minmax[0]
|
|
801
|
-
|
|
802
|
-
class BoxValue:
|
|
803
|
-
val = None
|
|
804
|
-
val_min_max = None # list of min/max
|
|
805
|
-
display_min_max = None # list of min/max
|
|
806
|
-
display_logscale = None # bool
|
|
807
|
-
|
|
808
|
-
def __init__(self, val, val_min_max, display_min_max, display_logscale):
|
|
809
|
-
self.val = val
|
|
810
|
-
self.val_min_max = val_min_max
|
|
811
|
-
self.display_min_max = display_min_max
|
|
812
|
-
self.display_logscale = display_logscale
|
|
813
|
-
|
|
814
|
-
def display_value(self):
|
|
815
|
-
return rescale(self.val, self.val_min_max, self.display_min_max,
|
|
816
|
-
self.display_logscale)
|
|
817
|
-
|
|
818
|
-
class ColoredBox:
|
|
819
|
-
# BoxValue
|
|
820
|
-
length = None
|
|
821
|
-
color = None
|
|
822
|
-
height = None
|
|
823
|
-
|
|
824
|
-
colorset = None
|
|
825
|
-
horizontal_align = None
|
|
826
|
-
|
|
827
|
-
def __init__(self, length, horizontal_align, color, colorset, height):
|
|
828
|
-
self.length = length
|
|
829
|
-
self.color = color
|
|
830
|
-
self.horizontal_align = horizontal_align
|
|
831
|
-
self.colorset = colorset
|
|
832
|
-
self.height = height
|
|
833
|
-
|
|
834
|
-
def __str__(self):
|
|
835
|
-
length = int(self.length.display_value())
|
|
836
|
-
|
|
837
|
-
if self.height.val != None:
|
|
838
|
-
height = int(self.height.display_value())
|
|
839
|
-
else:
|
|
840
|
-
self.height.display_min, self.height.display_max = [1, 1]
|
|
841
|
-
height = 1
|
|
842
|
-
|
|
843
|
-
if type(self.color.val) == str:
|
|
844
|
-
row = '%s' % (self.color.val * length)
|
|
845
|
-
else:
|
|
846
|
-
color_level = int(self.color.display_value())
|
|
847
|
-
row = '%s' % _damo_ascii_color.colored(
|
|
848
|
-
('%d' % color_level) * length, self.colorset, color_level)
|
|
849
|
-
row = '|%s|' % row
|
|
850
|
-
|
|
851
|
-
if self.horizontal_align == 'right':
|
|
852
|
-
indent = ' ' * (self.length.display_min_max[1] - length)
|
|
853
|
-
row = indent + row
|
|
854
|
-
|
|
855
|
-
box = '\n'.join([row] * height)
|
|
856
|
-
if self.height.display_min_max[1] > 1:
|
|
857
|
-
box += '\n'
|
|
858
|
-
return box
|
|
859
|
-
|
|
860
770
|
def apply_min_chars(min_chars, field_name, txt):
|
|
861
771
|
# min_chars: [[<field name>, <number of min chars>]...]
|
|
862
772
|
for name, nr in min_chars:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: damo
|
|
3
|
-
Version: 3.3.
|
|
3
|
+
Version: 3.3.4
|
|
4
4
|
Summary: DAMON user-space tool
|
|
5
5
|
Home-page: https://github.com/damonitor/damo
|
|
6
6
|
Author: SeongJae Park
|
|
@@ -71,7 +71,7 @@ The second and last commands will show the access pattern of your workload,
|
|
|
71
71
|
like below:
|
|
72
72
|
|
|
73
73
|

|
|
74
|
-

|
|
75
75
|
|
|
76
76
|
|
|
77
77
|
FAQs
|
|
@@ -90,7 +90,7 @@ Where can I get more detailed usage?
|
|
|
90
90
|
------------------------------------
|
|
91
91
|
|
|
92
92
|
The below sections provide quick introductions for `damo`'s major features.
|
|
93
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
93
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
94
94
|
|
|
95
95
|
|
|
96
96
|
What does the version numbers mean?
|
|
@@ -115,7 +115,7 @@ We try our best to make `damo` stable and doesn't introduce regressions to
|
|
|
115
115
|
users. However, nothing goes forever. Sometimes, some features will be
|
|
116
116
|
deprecated. Some features will have longer support more than others.
|
|
117
117
|
|
|
118
|
-
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
118
|
+
In short, features that documented on [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) and not explicitly
|
|
119
119
|
marked as experimental will be better supported, and provides at least three
|
|
120
120
|
months of deprecation grace period. Within the grace period, users can ask
|
|
121
121
|
extension of the support. Even after the grace period, please reach out to
|
|
@@ -138,7 +138,7 @@ Quick Intro for Major Features
|
|
|
138
138
|
==============================
|
|
139
139
|
|
|
140
140
|
Below are quick introductions for `damo`'s major features.
|
|
141
|
-
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.
|
|
141
|
+
For more detailed usage, please refer to [USAGE.md](https://github.com/damonitor/damo/blob/v3.3.4/USAGE.md) file.
|
|
142
142
|
|
|
143
143
|
|
|
144
144
|
Snapshot Data Access Pattern
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|