zram-advisor 1.0.0__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.

Potentially problematic release.


This version of zram-advisor might be problematic. Click here for more details.

@@ -0,0 +1,2 @@
1
+ dist/*
2
+ */__pycache__
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Joe D
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,116 @@
1
+ Metadata-Version: 2.1
2
+ Name: zram-advisor
3
+ Version: 1.0.0
4
+ Summary: zRAM status and setup tools
5
+ Project-URL: Homepage, https://github.com/joedefen/zram-advisor
6
+ Project-URL: Bug Tracker, https://github.com/joedefen/zram-advisor/issues
7
+ Author-email: Joe Defen <joedef@gmail.com>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Keywords: zram,zram service
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Operating System :: POSIX :: Linux
13
+ Classifier: Programming Language :: Python :: 3
14
+ Requires-Python: >=3.8
15
+ Requires-Dist: importlib-metadata; python_version < '3.8'
16
+ Requires-Dist: requests
17
+ Description-Content-Type: text/markdown
18
+
19
+ > **Quick-start**:
20
+ * If running python 5.11+, install `pipx`, and install with `pipx install zram-advisor`
21
+ * else install `pip`, and install with `pip install zram-advisor --user`
22
+ * `zram-advisor` - reports on currently running zRAM
23
+ * `zram-advisor --setup` - configure/starts zRAM w defaults on system w/o rRAM already configured.
24
+
25
+ # zram-advisor: Check/Setup/Test zRAM Tool
26
+ `zram-advisor` can:
27
+ * Check on your running zRAM and report ill advised settings and zRAM effectiveness.
28
+ * Install `fix-zram` which can setup your zRAM and/or reload it with different parameters (e.g., for testing).
29
+ * Provide a browser bookmark file to be imported to help testing your settings.
30
+
31
+ ## Checking Your Running zRAM
32
+ #### Checking with zram-advisor
33
+ Here is the sample output of `zram-advisor` w/o arguments on a system with zRAM running:
34
+ ```
35
+ $ zram-advisor
36
+ Distro : Linux Mint 21.3
37
+ 180 : vm.swappiness.................. in [150, 200]
38
+ 0 : vm.watermark_boost_factor...... in [0, 0]
39
+ 125 : vm.watermark_scale_factor...... in [125, 125]
40
+ 0 : vm.page-cluster................ in [0, 0]
41
+ 1.6G : zRAM.disksize.................. >= 1.4G
42
+ ================ 410s ================
43
+ 952.4M : Total Memory eTotal=2.2G/239%
44
+ 830.2M/87% : Used eUsed=1.4G/155%
45
+ 122.3M/13% : Available eAvail=800.7M/84%
46
+ zram0:
47
+ uncmpr: 814.5M limit=1.6G
48
+ cmpr: 158.5M/17% factor=5.14
49
+ RAM: 165.5M/17% most=240M/25% limit=0
50
+
51
+ ```
52
+ * The top section show key parameters for zRAM and suggested ranges (if it did not like those it would preface the range with "NOT in")
53
+ * The midsection shows traditional key memory stats on the left, and on the right, the "effective values":
54
+ * **eUsed**: is the amount of memory used if the compressed part in zRAM were expanded; than number is "true".
55
+ * **eTotal** and **eAvail** are projected numbers based on the current compression ratio; these number are more accurate as the zRAM memory footprint grows increases.
56
+ * The lower section are stats for each zram device .. typically, there is just one.
57
+ * **uncmpr**: is the amount of "original" memory stored by zRAM; its limit is officially called 'disksize' which is the name/value you see from `zramctl`.
58
+ * **RAM**: is the amount of physical RAM consumed by zRAM including overhead; **most** it the largest RAM used since boot.
59
+
60
+ #### Checking with pmemstat
61
+ Another app (installable with `pipx` or `pip`) is `pmemstat``. The top of it sample output (on the same system as above) was:
62
+ ```
63
+ 14:41:39 Tot=952.4M Used=741.5M Avail=210.9M Oth=0 Sh+Tmp=8.7M PIDs=122
64
+ 0.6/ker zRAM=210.2M eTot:2.2G/240% eUsed:1.5G/166% eAvail:705.7M/74%
65
+ cpu_pct pswap other data ptotal key/info (exe by mem)
66
+ 9.8 945 100 195 1,239 T 122x --TOTALS in MB --
67
+ ───────────────────────────────────────────────────────────────────────────
68
+ 3.3 396 65 106 567 23x chromium
69
+ ```
70
+ * You can see those same "effective" key memory stats, plus you can see kernel cpu% (i.e., the `0.6/ker`). Kernal CPU (most the swap process) can be significant, and that CPU cost is the primary "cost" of using zRAM).
71
+
72
+ ## zram-advisor Options
73
+ ```
74
+ usage: zram-advisor [-h] [-s] [-d] [-t] [--DB]
75
+ options:
76
+ -s, --setup-fix-zram install "fix-zram" program and start zRAM
77
+ -d, --dump-fix-zram print "fix-zram.sh" for manual install
78
+ -t, --gen-test-sites print "bookmarks.html" to import to a web-browser for load test
79
+ ```
80
+ * **--setup-fix-zram** installs a programs `fix-ram` and creates a service called `fix-zram-init` to run it on boot.
81
+ * **--dump-fix-zram** prints the stock `fix-zram.sh` (e.g., so you can modify it) and install your modified script by running it (e.g., `bash my-fix-zram.sh`).
82
+ * **--gen-test-sites** prints a .html that can be imported into most browsers which creates folders of sites that can be opened to create typical memory demands (of browsers at least).
83
+
84
+ **Note:** do not install `fix-zram` if w/o uninstalling any competing tool to configure zRAM.
85
+
86
+ ## Controlling zRAM with fix-zram
87
+ `fix-zram.sh` is bash script bundled with `zram-advisor`. Its usage is:
88
+ ```
89
+ fix-zram [--(load|reload|unload|setup|unsetup)] [-n|--dry-run] [-cN] [N.Nx] [Nm|Ng]
90
+ where:
91
+ --{command} defaults to 'load' but can be one of:
92
+ load - load/start zRAM with given params or their defaults
93
+ reload - remove any existing zRAM and load zram
94
+ unload - unloads any existing zRAM
95
+ setup - copy fix-zram to '/usr/local/bin' and setup service [dflt=no]
96
+ unsetup - remove '/usr/local/bin/fix-zram' and remove service [dflt=no]
97
+ -n,--dry-run - only print commands that would be executed
98
+ -c{integer} - set number of zram devices
99
+ {float}x - set zram-size to {float} * ram at most [dflt=1.75]
100
+ {integer}m - set gross zram-size to {integer} megabytes at most [dflt=12288m]
101
+ {integer}g - set gross zram-size to {integer} gigabytes at most
102
+ ```
103
+ ### fix-zram Run-Time Commands
104
+ `load`, `reload`, and `unload` affect the running system and any effect do not survive reboot. So, these can be used for testing (or initializing) zRAM.
105
+ * `load` and `reload` set the `vm.*` parameters shown by `vram-advisor` (but they do not unset them although a reboot will do that).
106
+ * `unload` and `reload` remove preexisting zRAM if running. Removal only works if all memory stored in zRAM can be placed in memory or another storage device.
107
+
108
+ Typical use:
109
+ * `fix-zram reload 3x 12g` - will unload the current zRAM (if exists and possible), and then install zRAM with sized at the minimum of 3xRAM and 12GB.
110
+
111
+ ### fix-zram Setup Methods
112
+ * `fix-zram --setup` - installs `fix-zram` and creates a `zram-init-fix` service which will load zRAM per the defaults on each load with default values.
113
+ * `fix-zram --unsetup` - removes the installed `fix-zram` and removes the `zram-init-fix` service.
114
+
115
+ Typical use:
116
+ * `fix-zram setup 3x 12g` - installs a zRAM init service that start zRAM sized at the minimum of 3xRAM and 12GB on boot.
@@ -0,0 +1,98 @@
1
+ > **Quick-start**:
2
+ * If running python 5.11+, install `pipx`, and install with `pipx install zram-advisor`
3
+ * else install `pip`, and install with `pip install zram-advisor --user`
4
+ * `zram-advisor` - reports on currently running zRAM
5
+ * `zram-advisor --setup` - configure/starts zRAM w defaults on system w/o rRAM already configured.
6
+
7
+ # zram-advisor: Check/Setup/Test zRAM Tool
8
+ `zram-advisor` can:
9
+ * Check on your running zRAM and report ill advised settings and zRAM effectiveness.
10
+ * Install `fix-zram` which can setup your zRAM and/or reload it with different parameters (e.g., for testing).
11
+ * Provide a browser bookmark file to be imported to help testing your settings.
12
+
13
+ ## Checking Your Running zRAM
14
+ #### Checking with zram-advisor
15
+ Here is the sample output of `zram-advisor` w/o arguments on a system with zRAM running:
16
+ ```
17
+ $ zram-advisor
18
+ Distro : Linux Mint 21.3
19
+ 180 : vm.swappiness.................. in [150, 200]
20
+ 0 : vm.watermark_boost_factor...... in [0, 0]
21
+ 125 : vm.watermark_scale_factor...... in [125, 125]
22
+ 0 : vm.page-cluster................ in [0, 0]
23
+ 1.6G : zRAM.disksize.................. >= 1.4G
24
+ ================ 410s ================
25
+ 952.4M : Total Memory eTotal=2.2G/239%
26
+ 830.2M/87% : Used eUsed=1.4G/155%
27
+ 122.3M/13% : Available eAvail=800.7M/84%
28
+ zram0:
29
+ uncmpr: 814.5M limit=1.6G
30
+ cmpr: 158.5M/17% factor=5.14
31
+ RAM: 165.5M/17% most=240M/25% limit=0
32
+
33
+ ```
34
+ * The top section show key parameters for zRAM and suggested ranges (if it did not like those it would preface the range with "NOT in")
35
+ * The midsection shows traditional key memory stats on the left, and on the right, the "effective values":
36
+ * **eUsed**: is the amount of memory used if the compressed part in zRAM were expanded; than number is "true".
37
+ * **eTotal** and **eAvail** are projected numbers based on the current compression ratio; these number are more accurate as the zRAM memory footprint grows increases.
38
+ * The lower section are stats for each zram device .. typically, there is just one.
39
+ * **uncmpr**: is the amount of "original" memory stored by zRAM; its limit is officially called 'disksize' which is the name/value you see from `zramctl`.
40
+ * **RAM**: is the amount of physical RAM consumed by zRAM including overhead; **most** it the largest RAM used since boot.
41
+
42
+ #### Checking with pmemstat
43
+ Another app (installable with `pipx` or `pip`) is `pmemstat``. The top of it sample output (on the same system as above) was:
44
+ ```
45
+ 14:41:39 Tot=952.4M Used=741.5M Avail=210.9M Oth=0 Sh+Tmp=8.7M PIDs=122
46
+ 0.6/ker zRAM=210.2M eTot:2.2G/240% eUsed:1.5G/166% eAvail:705.7M/74%
47
+ cpu_pct pswap other data ptotal key/info (exe by mem)
48
+ 9.8 945 100 195 1,239 T 122x --TOTALS in MB --
49
+ ───────────────────────────────────────────────────────────────────────────
50
+ 3.3 396 65 106 567 23x chromium
51
+ ```
52
+ * You can see those same "effective" key memory stats, plus you can see kernel cpu% (i.e., the `0.6/ker`). Kernal CPU (most the swap process) can be significant, and that CPU cost is the primary "cost" of using zRAM).
53
+
54
+ ## zram-advisor Options
55
+ ```
56
+ usage: zram-advisor [-h] [-s] [-d] [-t] [--DB]
57
+ options:
58
+ -s, --setup-fix-zram install "fix-zram" program and start zRAM
59
+ -d, --dump-fix-zram print "fix-zram.sh" for manual install
60
+ -t, --gen-test-sites print "bookmarks.html" to import to a web-browser for load test
61
+ ```
62
+ * **--setup-fix-zram** installs a programs `fix-ram` and creates a service called `fix-zram-init` to run it on boot.
63
+ * **--dump-fix-zram** prints the stock `fix-zram.sh` (e.g., so you can modify it) and install your modified script by running it (e.g., `bash my-fix-zram.sh`).
64
+ * **--gen-test-sites** prints a .html that can be imported into most browsers which creates folders of sites that can be opened to create typical memory demands (of browsers at least).
65
+
66
+ **Note:** do not install `fix-zram` if w/o uninstalling any competing tool to configure zRAM.
67
+
68
+ ## Controlling zRAM with fix-zram
69
+ `fix-zram.sh` is bash script bundled with `zram-advisor`. Its usage is:
70
+ ```
71
+ fix-zram [--(load|reload|unload|setup|unsetup)] [-n|--dry-run] [-cN] [N.Nx] [Nm|Ng]
72
+ where:
73
+ --{command} defaults to 'load' but can be one of:
74
+ load - load/start zRAM with given params or their defaults
75
+ reload - remove any existing zRAM and load zram
76
+ unload - unloads any existing zRAM
77
+ setup - copy fix-zram to '/usr/local/bin' and setup service [dflt=no]
78
+ unsetup - remove '/usr/local/bin/fix-zram' and remove service [dflt=no]
79
+ -n,--dry-run - only print commands that would be executed
80
+ -c{integer} - set number of zram devices
81
+ {float}x - set zram-size to {float} * ram at most [dflt=1.75]
82
+ {integer}m - set gross zram-size to {integer} megabytes at most [dflt=12288m]
83
+ {integer}g - set gross zram-size to {integer} gigabytes at most
84
+ ```
85
+ ### fix-zram Run-Time Commands
86
+ `load`, `reload`, and `unload` affect the running system and any effect do not survive reboot. So, these can be used for testing (or initializing) zRAM.
87
+ * `load` and `reload` set the `vm.*` parameters shown by `vram-advisor` (but they do not unset them although a reboot will do that).
88
+ * `unload` and `reload` remove preexisting zRAM if running. Removal only works if all memory stored in zRAM can be placed in memory or another storage device.
89
+
90
+ Typical use:
91
+ * `fix-zram reload 3x 12g` - will unload the current zRAM (if exists and possible), and then install zRAM with sized at the minimum of 3xRAM and 12GB.
92
+
93
+ ### fix-zram Setup Methods
94
+ * `fix-zram --setup` - installs `fix-zram` and creates a `zram-init-fix` service which will load zRAM per the defaults on each load with default values.
95
+ * `fix-zram --unsetup` - removes the installed `fix-zram` and removes the `zram-init-fix` service.
96
+
97
+ Typical use:
98
+ * `fix-zram setup 3x 12g` - installs a zRAM init service that start zRAM sized at the minimum of 3xRAM and 12GB on boot.
@@ -0,0 +1,69 @@
1
+ # HOW TO PUBLISH...
2
+ #
3
+ # Prep Work (ensure need modules are up-to-date):
4
+ # sudo pacman -Syu python-pip
5
+ # sudo pacman -Syu python-build
6
+ # sudo pacman -Syu python-twine
7
+ # -- antiquated way
8
+ # python3 -m pip install --upgrade pip
9
+ # python3 -m pip install --upgrade build
10
+ # python3 -m pip install --upgrade twine
11
+ #
12
+ # PUBLIC Build and deploy (from project directory):
13
+ # ## BUMP the version (below in [project])
14
+ # rm -r dist; python3 -m build; ls dist/.
15
+ # python3 -m twine upload dist/*
16
+ # ## Enter __token__ and the saved TOKEN (in bitwarden)
17
+ # pipx upgrade zram-advisor || pipx install zram-advisor # >= python3.11
18
+ # --OR-- sudo python3 -m pip install zram-advisor # <= python3.10
19
+ # ## VISIT https://pypi.org/project/zram-advisor and delete old versions
20
+ #
21
+ # TEST Build and test (from project directory):
22
+ # ## BUMP the version (below in [project])
23
+ # rm -r dist; python3 -m build
24
+ # python3 -m twine upload --repository testpypi dist/*
25
+ # ## Enter __token__ and the saved TOKEN (in bitwarden)
26
+ # pip install --upgrade --index-url https://test.pypi.org/simple/ --no-deps --user --break-system-packages zram-advisor
27
+ # pip uninstall --break-system-packages zram-advisor
28
+ # ## VISIT https://test.pypi.org/project/zram-advisor and delete old versions
29
+
30
+ [build-system]
31
+ requires = ["hatchling"]
32
+ build-backend = "hatchling.build"
33
+
34
+ [project]
35
+ version = "1.0.0"
36
+ name = "zram-advisor"
37
+ authors = [
38
+ {name = "Joe Defen", email = "joedef@gmail.com"},
39
+ ]
40
+ description = "zRAM status and setup tools"
41
+ readme = "README.md"
42
+ requires-python = ">=3.8"
43
+ keywords = ["zram", "zram service"]
44
+ license = "MIT"
45
+ classifiers = [
46
+ "Programming Language :: Python :: 3",
47
+ "License :: OSI Approved :: MIT License",
48
+ "Operating System :: POSIX :: Linux"
49
+ ]
50
+ dependencies = [
51
+ "requests",
52
+ 'importlib-metadata; python_version<"3.8"',
53
+ ]
54
+
55
+ [project.scripts]
56
+ zram-advisor = "zram_advisor.zram_advisor:run"
57
+
58
+ [tool.hatch.build.targets.wheel]
59
+ packages = ["zram_advisor"]
60
+
61
+ [tool.hatch.build.targets.sdist]
62
+ exclude = [
63
+ "__pycache__",
64
+ "zram_advisor/__pycache__",
65
+ ]
66
+
67
+ [project.urls]
68
+ "Homepage" = "https://github.com/joedefen/zram-advisor"
69
+ "Bug Tracker" = "https://github.com/joedefen/zram-advisor/issues"
@@ -0,0 +1,4 @@
1
+ from .zram_advisor import run
2
+
3
+ if __name__ == "__main__":
4
+ run()
@@ -0,0 +1,271 @@
1
+ #!/bin/bash
2
+ #
3
+ # default kernel settings
4
+ swappiness=180
5
+ watermark_boost_factor=0
6
+ watermark_scale_factor=125
7
+ page_cluster=0
8
+ priority=100
9
+ # default options to this script
10
+ factor=1.75
11
+ capM=$((12*1024)) # the default cap on zRAM
12
+ count=1
13
+ dry_run=no
14
+ command=start
15
+
16
+ usage() {
17
+ echo "$@"
18
+ cat <<END
19
+ USE: fix-zram [--(load|reload|unload|setup|unsetup)] [-n|--dry-run] [-cN] [N.Nx] [Nm|Ng]
20
+ where:
21
+ --{command} defaults to 'load' but can be one of:
22
+ load - load/start zRAM with given params or their defaults
23
+ reload - remove any existing zRAM and load zram
24
+ unload - unloads any existing zRAM
25
+ setup - copy fix-zram to '/usr/local/bin' and setup service
26
+ unsetup - remove '/usr/local/bin/fix-zram' and remove service
27
+ -n,--dry-run - only print commands that would be executed
28
+ -c{integer} - set number of zram devices
29
+ {float}x - set zram-size to {float} * ram at most [dflt=$factor]
30
+ {integer}m - set gross zram-size to {integer} megabytes at most [dflt=${capM}m]
31
+ {integer}g - set gross zram-size to {integer} gigabytes at most
32
+ END
33
+ exit 1
34
+ }
35
+
36
+ ########################################################
37
+ # restart this program if not root
38
+ if [[ $(id --user) != 0 ]]; then
39
+ script_tmp_dir=$(realpath "$0")
40
+ exec sudo bash "${script_tmp_dir}" "$@"
41
+ fi
42
+
43
+ ########################################################
44
+ # Iterate over command-line arguments
45
+ shopt -s extglob # permit patterns like *(-)
46
+ for arg in "$@"; do
47
+ case "$arg" in
48
+ [0-9]*[xX]|[0-9]*.[0-9]*[xX])
49
+ factor="${arg%?}"
50
+ ;;
51
+ [0-9]*[mM])
52
+ capM="${arg%?}"
53
+ ;;
54
+ [0-9]*[gG])
55
+ capG="${arg%?}"
56
+ capM=$((capG*1024))
57
+ ;;
58
+ *(-)c[0-9]*)
59
+ count="${arg##*c}"
60
+ ;;
61
+ *(-)load) command=load ;;
62
+ *(-)reload) command=reload ;;
63
+ *(-)unload) command=unload ;;
64
+ *(-)setup) command=setup ;;
65
+ *(-)unsetup) command=unsetup ;;
66
+ -n|--dry-run) dry_run=yes ;;
67
+ -h|--help|-\?) usage ;;
68
+ *) usage "Unknown option: $arg" ;;
69
+ esac
70
+ done
71
+
72
+ ########################################################
73
+ # Calculations verification
74
+ ramM=$(free -m | awk '/^Mem:/ {print $2}')
75
+ zram_sizeM=$(python3 -c "print(int(round(${factor} * ${ramM})))")
76
+ echo factor=$factor cap=$capM ramM=$ramM zram_size=$zram_sizeM
77
+ if (( capM < zram_sizeM )); then
78
+ zram_sizeM="${capM}"
79
+ fi
80
+ echo OPTS: $command dry-run=$dry_run count=$count factor=$factor capM=$capM
81
+ echo INFO: ramM=$ramM zram_sizeM=$zram_sizeM
82
+
83
+ ########################################################
84
+ # run a command (or don't)
85
+ run() {
86
+ if [[ $dry_run == "yes" ]]; then
87
+ echo 'WOULD ++' "$@"
88
+ else
89
+ echo '++' "$@"
90
+ eval "$@"
91
+ fi
92
+ }
93
+
94
+ ########################################################
95
+ # unload zram
96
+ unload_zram() {
97
+ found=no
98
+ shopt -s nullglob
99
+ devs=(/dev/zram*)
100
+ for dev in "${devs[@]}"; do
101
+ run "swapoff ${dev}"
102
+ found=yes
103
+ done
104
+ shopt -u nullglob
105
+ run 'modprobe -r zram'
106
+ if [[ $found == "no" ]]; then
107
+ echo 'NOTE: zram already unloaded'
108
+ fi
109
+ run "zramctl"
110
+ }
111
+
112
+ ########################################################
113
+ # initialize zram
114
+ load_zram() {
115
+ shopt -s nullglob
116
+ devs=(/dev/zram*)
117
+ for dev in "${devs[@]}"; do
118
+ if [[ $command == 'reload' ]]; then
119
+ unload_zram
120
+ else
121
+ echo "ERROR: ${dev} exists; use --reload to first unload then load"
122
+ exit -1
123
+ fi
124
+ break
125
+ done
126
+ shopt -u nullglob
127
+
128
+ # unload zswap just in case
129
+ run "echo 0 > /sys/module/zswap/parameters/enabled"
130
+
131
+ run "modprobe zram num_devices=${count}"
132
+ sizeM=$(python3 -c "print(int(round(${zram_sizeM} / ${count} )))")
133
+ for (( ii=0; ii<count; ii++ )); do
134
+ run "echo zstd > /sys/block/zram${ii}/comp_algorithm"
135
+ run "echo ${sizeM}M > /sys/block/zram${ii}/disksize"
136
+ run "echo 0 > /sys/block/zram${ii}/mem_limit"
137
+ done
138
+
139
+ run "sysctl -w vm.swappiness=${swappiness} >/dev/null"
140
+ run "sysctl -w vm.watermark_boost_factor=${watermark_boost_factor} > /dev/null"
141
+ run "sysctl -w vm.watermark_scale_factor=${watermark_scale_factor} >/dev/null"
142
+ run "sysctl -w vm.page-cluster=${page_cluster} >/dev/null"
143
+
144
+ for (( ii=0; ii<count; ii++ )); do
145
+ run mkswap /dev/zram${ii}
146
+ run swapon --priority ${priority} /dev/zram${ii}
147
+ done
148
+ run "zramctl"
149
+ }
150
+
151
+
152
+ ########################################################
153
+ # systemd service setup
154
+ setup_systemd() {
155
+ dest="/etc/systemd/system/fix-zram.service"
156
+ service=$(basename "$dest")
157
+ cat <<END > "${dest}"
158
+ #!/bin/sh
159
+ [Unit]
160
+ Description=Init zRAM on boot
161
+
162
+ [Service]
163
+ Type=simple
164
+ ExecStart=/bin/bash ${script_bin_path} -c${count} ${factor}x ${capM}M
165
+
166
+ [Install]
167
+ WantedBy=multi-user.target
168
+ END
169
+
170
+ run "chmod 644 '$dest'"
171
+ run "systemctl enable --now ${service}"
172
+
173
+ }
174
+ unsetup_systemd() {
175
+ dest="/etc/systemd/system/fix-zram.service"
176
+ service=$(basename "$dest")
177
+ if [ -f "$dest" ]; then
178
+ run "systemctl disable --now ${service}"
179
+ run "rm '$dest'"
180
+ fi
181
+ }
182
+
183
+ ########################################################
184
+ # sysVinit service setup
185
+ setup_sysVinit() {
186
+ wrapper="/etc/init.d/fix-zram-init"
187
+ service=$(basename "${wrapper}")
188
+
189
+ cat <<END > "${wrapper}"
190
+ #!/bin/bash
191
+ ### BEGIN INIT INFO
192
+ # Default-Start: 2 3 4 5
193
+ # Default-Stop:
194
+ ### END INIT INFO
195
+
196
+ case "$1" in
197
+ start) sudo bash ${script_bin_path} load -c${count} ${factor}x ${capM}M;;
198
+ stop) sudo bash ${script_bin_path} --unload ;;
199
+ *) ;;
200
+ esac
201
+ exit 0
202
+ END
203
+ run "chmod 755 '$wrapper'"
204
+
205
+ if which chkconfig >/dev/null 2>&1; then
206
+ run "chkconfig --add ${service}"
207
+ elif which update-rc.d >/dev/null 2>&1; then
208
+ run "update-rc.d ${wrapper} defaults"
209
+ fi
210
+ if which service >/dev/null 2>&1; then
211
+ run "service $service enable"
212
+ run "service $service start"
213
+ elif which update-rc.d >/dev/null 2>&1; then
214
+ run "update-rd.d $service enable"
215
+ run "$wrapper start"
216
+ fi
217
+
218
+ }
219
+ unsetup_sysVinit() {
220
+ wrapper="/etc/init.d/fix-zram-init"
221
+ service=$(basename "${wrapper}")
222
+ if which service >/dev/null 2>&1; then
223
+ run "service ${service} stop"
224
+ run "service ${service} disable"
225
+ elif which update-rc.d >/dev/null 2>&1; then
226
+ run "${wrapper} stop"
227
+ run "update-rd.d ${service} disable"
228
+ fi
229
+ run "rm ${wrapper}"
230
+ if which update-rc.d >/dev/null 2>&1; then
231
+ run "update-rc.d -f ${service} remove"
232
+ fi
233
+ run "rm /var/log/${service}.log"
234
+ }
235
+
236
+ ########################################################
237
+ # setup
238
+ setup() {
239
+ script_tmp_dir=$(realpath "$0")
240
+ script_bin_path="/usr/local/bin/fix-zram"
241
+ ( run "cp '$script_tmp_dir' '$script_bin_path'" )
242
+
243
+ init_cmd=$(ps -p 1 -o comm=)
244
+ case "$init_cmd" in
245
+ init) ( setup_sysVinit ) ;;
246
+ systemd) ( setup_systemd ) ;;
247
+ *) echo unhandled init type "$init_cmd" ;;
248
+ esac
249
+ }
250
+ ########################################################
251
+ # unsetup
252
+ unsetup() {
253
+ script_bin_path="/usr/local/bin/fix-zram"
254
+ init_cmd=$(ps -p 1 -o comm=)
255
+ case "$init_cmd" in
256
+ init) ( unsetup_sysVinit ) ;;
257
+ systemd) ( unsetup_systemd ) ;;
258
+ *) echo unhandled init type "$init_cmd" ;;
259
+ esac
260
+ rm $script_bin_path
261
+ }
262
+
263
+ if [[ $command == 'setup' ]]; then
264
+ setup
265
+ elif [[ $command == 'unsetup' ]]; then
266
+ unsetup
267
+ elif [[ $command == 'unload' ]]; then
268
+ unload_zram
269
+ else
270
+ load_zram
271
+ fi
@@ -0,0 +1,54 @@
1
+ 50waystogetajob.com
2
+ 80000hours.org
3
+ www.teamblind.com
4
+ qz.com/work
5
+ brandyourself.com
6
+ www.payscale.com
7
+ getpocket.com
8
+ www.hubspot.com/resources/courses
9
+ internetingishard.netlify.app
10
+ teamtreehouse.com
11
+ www.shopify.com/guides
12
+ www.shopify.com/academy
13
+ www.ted.com
14
+ www.quora.com
15
+ www.blinkist.com
16
+ www.actionablebooks.com/en-ca/summaries
17
+ www.theschooloflife.com/thebookoflife
18
+ www.duolingo.com
19
+ zapier.com/learn
20
+ speaking.io
21
+ review.firstround.com
22
+ degreed.com
23
+ reviewmeta.com
24
+ fast.com
25
+ genius.com
26
+ www.padmapper.com
27
+ workflowy.com
28
+ www.grammarly.com
29
+ trello.com
30
+ www.rescuetime.com
31
+ www.crystalknows.com
32
+ cash.app
33
+ resumeworded.com
34
+ archive.org/web
35
+ discover.getrevue.co
36
+ ifttt.com
37
+ quotecatalog.com
38
+ www.insight-book.com/Quiz.aspx
39
+ ikonick.com
40
+ www.goodreads.com
41
+ weworkremotely.com
42
+ www.freelancewriting.com/jobs
43
+ authenticjobs.com
44
+ angel.co/jobs
45
+ startup.jobs
46
+ invoice-generator.com
47
+ www.hellobonsai.com
48
+ www.indiehackers.com
49
+ www.producthunt.com
50
+ discord.com
51
+ medium.com
52
+ www.patreon.com
53
+ stackexchange.com
54
+ www.thevectorimpact.com
@@ -0,0 +1,411 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Program to analyze the zRAM configuration (if any) and suggest
5
+ some improvements.
6
+
7
+ ===== References =====
8
+ www.kernel.org/doc/Documentation/blockdev/zram.txt
9
+ fedoraproject.org/wiki/Changes/Scale_ZRAM_to_full_memory_size
10
+ kernelnewbies.org/Linux_5.8 - when swappiness rose to 2020-08-02
11
+
12
+ Tested on:
13
+ - Linux Mint (Mate) 21.3 - 6.5 kernel (upgraded)
14
+ - Debian (KDE) 12.4.0
15
+ - Linux Lite 6.6 - 5.x kernel
16
+ - elementary OS 7.1 Horus
17
+ """
18
+ # pylint: disable=invalid-name,multiple-statements,global-statement
19
+ # pylint: disable=too-many-instance-attributes,broad-exception-caught
20
+
21
+ import re
22
+ from types import SimpleNamespace
23
+ import shutil
24
+ import os
25
+ import sys
26
+ import configparser
27
+ import time
28
+ import argparse
29
+ import subprocess
30
+
31
+ ##############################################################################
32
+
33
+ ####################################################################################
34
+
35
+ class Term:
36
+ """ Escape sequences; e.g., see:
37
+ - https://en.wikipedia.org/wiki/ANSI_escape_code
38
+ - https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797#file-ansi-md
39
+ """
40
+ esc = '\x1B'
41
+ # pylint: disable=missing-function-docstring,multiple-statements
42
+ @staticmethod
43
+ def erase_line(): return f'{Term.esc}[2K'
44
+ @staticmethod
45
+ def bold(): return f'{Term.esc}[1m'
46
+ @staticmethod
47
+ def reverse_video(): return f'{Term.esc}[7m'
48
+ @staticmethod
49
+ def normal_video(): return f'{Term.esc}[m'
50
+ @staticmethod
51
+ def pos_up(cnt): return f'{Term.esc}[{cnt}F' if cnt > 0 else ''
52
+ @staticmethod
53
+ def pos_down(cnt): return f'{Term.esc}[{cnt}E' if cnt > 0 else ''
54
+ @staticmethod
55
+ def col(pos): return f'{Term.esc}[{pos}G'
56
+ @staticmethod
57
+ def clear_screen(): return f'{Term.esc}[H{Term.esc}[2J{Term.esc}[3J'
58
+
59
+
60
+ ##############################################################################
61
+ def human(number):
62
+ """ Return a concise number description."""
63
+ if number <= 0:
64
+ return '0'
65
+ suffixes = ['', 'K', 'M', 'G', 'T', 'Q']
66
+ while suffixes:
67
+ suffix = suffixes.pop(0)
68
+ if number < 999.95 or not suffixes:
69
+ num = f'{number:.1f}'
70
+ num = num[0:-2] if num.endswith('.0') else num
71
+ return f'{num}{suffix}'
72
+ number /= 1024
73
+ return 'TooHuge'
74
+
75
+ ##############################################################################
76
+ class ZramAdvisor:
77
+ """ Workhorse class for zram-advisor """
78
+ def __init__(self):
79
+ self.meminfo = None #selected info from meminfo
80
+ self.effective = None # effective system params
81
+ self.probe = None # info about runnable programs
82
+ self.devs = None # info about zram devices
83
+ self.params = None # related kernel parameters
84
+ self.release = None
85
+ self.ram_total = 0
86
+ self.tab_count = 0 # number of tabs created so far
87
+ self.download_dir = os.path.expanduser('~/Downloads')
88
+ self.script_dir = os.path.dirname(os.path.realpath(__file__))
89
+ # options:
90
+ self.DB = False
91
+ self.limit_pct = 80 # arbitrary limit on amount of RAM used by zRAM
92
+
93
+ def human_pct(self, number):
94
+ """ Return the number in human form and as pct total memory. """
95
+ rv = human(number)
96
+ if number > 0 and self.ram_total > 0:
97
+ fraction = number/self.ram_total
98
+ pct = int(round(100*fraction))
99
+ rv += f'/{pct}%'
100
+ return rv
101
+
102
+ def get_meminfo(self):
103
+ """Get most vital stats from /proc/meminfo'"""
104
+ meminfofile = '/proc/meminfo'
105
+ meminfo = {'MemTotal': 0, 'MemAvailable': 0, 'Dirty':0, 'Shmem':0}
106
+ keys = list(meminfo.keys())
107
+
108
+ with open(meminfofile, encoding='utf-8') as fileh:
109
+ for line in fileh:
110
+ match = re.match(r'^([^:]+):\s+(\d+)\s*kB', line)
111
+ if not match:
112
+ continue
113
+ key, value = match.group(1), int(match.group(2))
114
+ if key not in keys:
115
+ continue
116
+ meminfo[key] = value * 1024
117
+ keys.remove(key)
118
+ if not keys:
119
+ break
120
+ assert not keys, f'ALERT: cannot get vitals ({keys}) from {meminfofile}'
121
+ ns = SimpleNamespace(**meminfo)
122
+ ns.MemUsed = ns.MemTotal - ns.MemAvailable # synthetic
123
+ if self.DB: print(f'DB: meminfo: {ns}')
124
+ if self.DB: print(f'DB: RAM={human(ns.MemTotal)}')
125
+ self.ram_total = ns.MemTotal
126
+ return ns
127
+
128
+ @staticmethod
129
+ def keyword_in_manpage(manpage, keyword):
130
+ """ Is a given keyword in the man page?"""
131
+ try:
132
+ # Use subprocess to run the man command and grep for the keyword
133
+ command = f"man {manpage} | grep -q '{keyword}'"
134
+ subprocess.run(command, shell=True, check=True)
135
+ return True
136
+ except subprocess.CalledProcessError:
137
+ return False
138
+
139
+ def prober(self):
140
+ """ Probe for distro specific attributes """
141
+ def has(program): # is program on path?
142
+ return shutil.which(program) is not None
143
+
144
+
145
+ ns = SimpleNamespace(installer=None)
146
+ ns.fraction_str = ''
147
+
148
+ others = ('zramctl', )
149
+ for other in others:
150
+ setattr(ns, other, has(other))
151
+ if self.DB: print(f'DB: probe: {ns}')
152
+ return ns
153
+
154
+ def load_script(self):
155
+ """ Give the user the onboot script"""
156
+ pathname = os.path.join(self.script_dir, 'fix-zram.sh')
157
+ with open(pathname, "r", encoding='utf8') as fh:
158
+ install_script = fh.read()
159
+ return install_script
160
+
161
+ def setup_script(self, install_script):
162
+ """ Dump 'fix-zram' into /tmp and run it."""
163
+ pathname = os.path.join('/tmp', 'fix-zram.sh')
164
+ with open(pathname, "w", encoding='utf-8') as fh:
165
+ fh.write(install_script)
166
+ os.chmod(pathname, 0o755)
167
+ os.system(f'set -x; sudo bash {pathname} --setup')
168
+
169
+ def create_site_import(self):
170
+ """ Get a randomly chosen site """
171
+ random_site_file = os.path.join(self.script_dir, 'random-sites.txt')
172
+ with open(random_site_file, "r", encoding='utf8') as fh:
173
+ sites = [line.rstrip('\n') for line in fh]
174
+ rv = """<!DOCTYPE NETSCAPE-Bookmark-file-1>
175
+ <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
176
+ <TITLE>Bookmarks</TITLE>
177
+ <H1>Bookmarks</H1><DL><p>
178
+ """
179
+ rv += '<DT><H3>Rand0</H3><DL><p>\n'
180
+ for idx, site in enumerate(sites):
181
+ if idx and idx % 10 == 0:
182
+ rv += f'</DL><p>\n<DT><H3>Rand{idx//10}</H3><DL><p>\n'
183
+ href = f'https://{site}/'
184
+ site = site[4:] if site.startswith('www.') else site
185
+ rv += f' <DT><A HREF="{href}">{site}</A>\n'
186
+ rv += '</DL><p>\n</DL><p>\n'
187
+ return rv
188
+
189
+ def get_zram_stats(self):
190
+ """ Get only what we want
191
+ orig_data_size uncompressed size of data stored in this disk.
192
+ compr_data_size compressed size of data stored in this disk
193
+ mem_used_total the amount of memory allocated for this disk.
194
+ mem_limit max RAM ZRAM can use to store (0 means unlimited)
195
+ mem_used_max max RAM zram has consumed to store the data
196
+ """
197
+ fields = ('orig_data_size compr_data_size mem_used_total'
198
+ + ' mem_limit mem_used_max').split()
199
+ infos = {}
200
+ zram_devices = sorted([device for device in os.listdir('/sys/class/block/')
201
+ if device.startswith('zram')])
202
+ for device in zram_devices:
203
+ statfile = f'/sys/class/block/{device}/mm_stat'
204
+ if not os.path.exists(statfile):
205
+ continue # not active
206
+ with open(statfile, encoding='utf-8') as fileh:
207
+ ns = SimpleNamespace()
208
+ for line in fileh: # all the goodies are on 1st line
209
+ nums = line.split()
210
+ for idx, field in enumerate(fields):
211
+ setattr(ns, field, int(nums[idx]))
212
+ break
213
+ infos[device] = ns
214
+ for param in ('disksize', ):
215
+ statfile = f'/sys/class/block/{device}/{param}'
216
+ with open(statfile, encoding='utf-8') as fileh:
217
+ for line in fileh: # one value, one line
218
+ setattr(ns, param, int(line.strip()))
219
+ break
220
+ if self.DB: print(f'DB: {device}: {ns}')
221
+
222
+ return infos
223
+
224
+ def get_vm_params(self):
225
+ """ Looking for (and good values):
226
+ vm.swappiness = 180
227
+ vm.watermark_boost_factor = 0
228
+ vm.watermark_scale_factor = 125
229
+ vm.page-cluster = 0
230
+ """
231
+ def add_param(coll, name, least, most):
232
+ key = name.replace('-', '_')
233
+ coll[key] = SimpleNamespace(
234
+ name=name, value=None, least=least, most=most, key=key)
235
+ params = {}
236
+ add_param(params, 'swappiness', 150, 200)
237
+ add_param(params, 'watermark_boost_factor', 0, 0)
238
+ add_param(params, 'watermark_scale_factor', 125, 125)
239
+ add_param(params, 'page-cluster', 0, 0)
240
+
241
+ vm_dirname = '/proc/sys/vm'
242
+ for param in params.values():
243
+ param_file = os.path.join(vm_dirname, param.name)
244
+ with open(param_file, encoding='utf-8') as fileh:
245
+ param.value = int(fileh.readline().strip())
246
+ if self.DB: print(f'DB: vm.params: {params}')
247
+ return params
248
+
249
+ def get_name_value_info(self, pathname):
250
+ """ Parse a name=value file; e.g., pathname
251
+ - keys are made lower case for uniformity because it varies
252
+ - values are left intact
253
+ """
254
+ ns = SimpleNamespace()
255
+ parser = configparser.ConfigParser()
256
+ with open(pathname, encoding='utf-8') as stream:
257
+ parser.read_string('[top]\n' + stream.read())
258
+
259
+ for section in parser.sections():
260
+ for key, value in parser.items(section):
261
+ setattr(ns, key.lower(), value.replace('"', ''))
262
+ if self.DB: print(f'DB: {os.path.basename(pathname)}: {ns}')
263
+ return ns
264
+
265
+ def compute_effective(self):
266
+ """ Compute the effective values """
267
+ def dump_effective(ns, annotation=''):
268
+ nonlocal self
269
+ for key, value in vars(ns).items():
270
+ print(f'DB: {annotation} {key}: {self.human_pct(value)}')
271
+
272
+ if not self.devs:
273
+ return None
274
+ meminfo = self.meminfo
275
+ stats = None
276
+ for stat in self.devs.values():
277
+ # NOTE: generalization for more than one weak unless all
278
+ # are identically configured
279
+ if not stats:
280
+ stats = vars(stat).copy()
281
+ continue
282
+ for key, value in vars(stat).items():
283
+ stats[key] += value
284
+ stats = SimpleNamespace(**stats)
285
+
286
+ ns = SimpleNamespace(e_used=meminfo.MemUsed,
287
+ e_avail=meminfo.MemAvailable, e_total=meminfo.MemTotal,
288
+ e_max_used=meminfo.MemTotal, stats=stats)
289
+ e_used = meminfo.MemUsed - stats.mem_used_total + stats.orig_data_size
290
+ ratio = None
291
+ if e_used <= ns.e_used: # zram hurts. assume not enuf data to project
292
+ e_used = ns.e_used
293
+ ratio = 3.5 # wild guess for projection
294
+ # if self.DB: dump_effective(ns, '(unchg)')
295
+ # return ns
296
+ ns.e_used = e_used
297
+ limit_pct = self.limit_pct
298
+ if stats.mem_limit > 0:
299
+ stats_limit_pct = (stats.limit / meminfo.MemTotal)*100
300
+ limit_pct = min(1.0, limit_pct, stats_limit_pct)
301
+ # projected amount of orig used memory that fits in limit
302
+ if ratio is None: # hopefully about 4 ;-)
303
+ ratio = stats.orig_data_size / stats.mem_used_total
304
+ e_max_used = ratio * meminfo.MemTotal * limit_pct/100
305
+ # now limit by disksize
306
+ e_max_used = min(e_max_used, stats.disksize)
307
+ # now add uncompressed memory
308
+ e_max_used += meminfo.MemTotal - e_max_used/ratio
309
+ ns.e_max_used = e_max_used
310
+ ns.e_avail = e_max_used - e_used
311
+ if self.DB: dump_effective(ns)
312
+ return ns
313
+
314
+
315
+ def show_system_summary(self):
316
+ """ Just the facts, ma'am """
317
+ print(f'{"Distro":>16} : {self.release.marquee}')
318
+ for param in self.params.values():
319
+ ok = '....' if param.least <= param.value <= param.most else ' NOT'
320
+ print(f'{param.value:>16} : vm.{param.name.ljust(24, ".")}'
321
+ f'{ok} in [{param.least}, {param.most}]')
322
+ if not self.devs:
323
+ print(' NO zRAM: zRAM is either not installed or not enabled')
324
+ sys.exit(1)
325
+ GB = 1024*1024*1024
326
+ ram = self.meminfo.MemTotal
327
+ min_disksize = (1.5*ram if ram <= 8*GB else 4*GB)
328
+ actual_disksize = self.effective.stats.disksize
329
+ ok = '....' if min_disksize <= actual_disksize else ' NOT'
330
+ print(f'{human(actual_disksize):>16} : {"zRAM.disksize".ljust(27, ".")}'
331
+ f'{ok} >= {human(min_disksize)}')
332
+
333
+ start = time.time()
334
+ time.sleep(2)
335
+ for _ in range(1000*1000):
336
+ meminfo = self.meminfo
337
+ eff = self.effective
338
+ delta = int(round(time.time() - start))
339
+ print('='*16, f'{delta}s', '='*16)
340
+ print(f'{human(self.meminfo.MemTotal):>16} : {"Total Memory":<16}',
341
+ f'eTotal={self.human_pct(eff.e_max_used)}')
342
+ print(f'{self.human_pct(meminfo.MemUsed):>16} : {"Used":<16}',
343
+ f' eUsed={self.human_pct(eff.e_used)}')
344
+ print(f'{self.human_pct(meminfo.MemAvailable):>16} : {"Available":<16}',
345
+ f'eAvail={self.human_pct(eff.e_avail)}')
346
+ for dev, stats in self.devs.items():
347
+ print(f'{dev}:')
348
+ print(f' uncmpr: {human(stats.orig_data_size)} limit={human(stats.disksize)}')
349
+ factor = (stats.orig_data_size/stats.compr_data_size
350
+ if stats.compr_data_size > 0 else 0)
351
+ print(f' cmpr: {self.human_pct(stats.compr_data_size)}',
352
+ f'factor={factor:.2f}')
353
+ print(f' RAM: {self.human_pct(stats.mem_used_total)}'
354
+ if stats.mem_used_total > 0 else 'n/a',
355
+ f'most={self.human_pct(stats.mem_used_max)}',
356
+ f'limit={self.human_pct(stats.mem_limit)}')
357
+ if self.DB:
358
+ break
359
+ time.sleep(1)
360
+ self.meminfo = self.get_meminfo()
361
+ self.devs = self.get_zram_stats()
362
+ self.effective = self.compute_effective()
363
+
364
+ emit = Term.pos_up(1) + Term.erase_line() + '\r'
365
+ print((4 + len(self.devs) * 4) * emit, end='')
366
+
367
+ def main(self):
368
+ """ Do something useful. """
369
+ parser = argparse.ArgumentParser()
370
+ parser.add_argument('-s', '--setup-fix-zram', action="store_true",
371
+ help='install "fix-zram" program and start zRAM')
372
+ parser.add_argument('-d', '--dump-fix-zram', action="store_true",
373
+ help='print "fix-zram.sh" for manual install')
374
+ parser.add_argument('-t', '--gen-test-sites', action="store_true",
375
+ help='print "bookmarks.html" to import to a web-browser for load test')
376
+ parser.add_argument('--DB', action="store_true",
377
+ help='debug creation of low-level objects/data')
378
+ opts = parser.parse_args()
379
+
380
+ try:
381
+ self.release = self.get_name_value_info('/etc/os-release')
382
+ self.release.marquee = self.release.pretty_name
383
+ except Exception:
384
+ try:
385
+ self.release = self.get_name_value_info('/etc/lsb-release')
386
+ self.release.marquee = self.distrib_description
387
+ except Exception:
388
+ print("cannot get os-release or lsb-release")
389
+
390
+ if opts.dump_fix_zram:
391
+ install_script = self.load_script()
392
+ print(install_script, end='')
393
+ elif opts.setup_fix_zram:
394
+ install_script = self.load_script()
395
+ self.setup_script(install_script)
396
+ elif opts.gen_test_sites:
397
+ import_html = self.create_site_import()
398
+ print(import_html, end='')
399
+ else:
400
+ self.meminfo = self.get_meminfo()
401
+ self.probe = self.prober()
402
+ self.devs = self.get_zram_stats()
403
+ self.params = self.get_vm_params()
404
+ self.effective = self.compute_effective()
405
+ self.show_system_summary()
406
+ def run():
407
+ """ Entry point"""
408
+ ZramAdvisor().main()
409
+
410
+ if __name__ == "__main__":
411
+ run()