Repository: archlinux/archinstall

Issue:
[master] Lag in menu after selecting a harddrive
Running `viztracer` generates a 2.6G trace and crashes most machines trying to analyze it.
Here's the only evidence of the issue thus far:

https://user-images.githubusercontent.com/861439/167908067-694654d5-56a3-4baa-8bcb-9378472c8677.mov


https://user-images.githubusercontent.com/861439/167908074-be9c081f-2180-42ea-84bc-7fe0fed73e20.mov

I haven't been able to track it down.
Reported by `@rez` on discord.

Doesn't always happen, I tried a "speedrum" earlier today of `master` and it worked, with a slight hint of the lag: https://cdn.discordapp.com/attachments/726808924401172483/973994546126024714/archinstall_speedrun.gif


Discussion:
![screenshot](https://user-images.githubusercontent.com/861439/167910062-f92c2f29-51cb-481d-bc96-6abb7637a371.png)

Nothing really stands out.
`_read_next_key (/home/anton/github/archinstall/archinstall/lib/menu/simple_menu.py:1421` is a bit suspicious.
Ok so, it seams the printing of the block-device information is causing the delay. As we appear to refresh the information each time the arrows are pushed.

![screenshot](https://user-images.githubusercontent.com/861439/167910736-84d0ead6-abbc-4970-9e2b-57aef619f67d.png)

Here, highlighted is `__repr__` of `/home/anton/github/archinstall/archinstall/lib/disk/blockdevice.py:34`.
This is called from `menu_text` in `/home/anton/github/archinstall/archinstall/lib/menu/selection_menu.py:124`.

And `__repr__` has a horrific delay due to:
 * `self.size`
 * `self.free_space`
 * `self.bus_type`

But this is just a symptom because: https://github.com/archlinux/archinstall/blob/08452de09c8461178e27da27633778910a4e1b7a/archinstall/lib/general.py#L318-L341

It's a delay of `0.1 * 3` per time we print the information.
One of the delayed cycles look like this:
![screenshot](https://user-images.githubusercontent.com/861439/167920512-7dbc2ff1-7e37-43d5-afc2-3cc58835bcb7.png)

Showing the items take the longest, but the poll is pretty slow so I'll take a look at that first.

Off-topic: How do you create these graphics? I like them!
> [ Off-topic, but how do you create these graphics? I like them! ]

```
$ pip install viztracer
$ viztracer python -m archinstall
```
Will generate `result.json` which you can upload and view on https://ui.perfetto.dev/

There's some other tools as well for local visualization that is a bit more oldschool.
```
$ python -m cProfile -o profile_data.pyprof guided.py
$ pyprof2calltree -i profile_data.pyprof -k
```
Available in `community/pyprof2calltree` and `extra/kcachegrind`.
Kudos to https://stackoverflow.com/a/3561512/929999 who taught me that 12 years ago. Damn life saver.

Resolving patch:
diff --git a/archinstall/lib/disk/blockdevice.py b/archinstall/lib/disk/blockdevice.py
--- a/archinstall/lib/disk/blockdevice.py
+++ b/archinstall/lib/disk/blockdevice.py
@@ -3,6 +3,7 @@
 import json
 import logging
 import time
+from functools import cached_property
 from typing import Optional, Dict, Any, Iterator, Tuple, List, TYPE_CHECKING
 # https://stackoverflow.com/a/39757388/929999
 if TYPE_CHECKING:
@@ -32,6 +33,10 @@ def __init__(self, path :str, info :Optional[Dict[str, Any]] = None):
 		#       I'm placing the encryption password on a BlockDevice level.
 
 	def __repr__(self, *args :str, **kwargs :str) -> str:
+		return self._str_repr
+	
+	@cached_property
+	def _str_repr(self) -> str:
 		return f"BlockDevice({self.device_or_backfile}, size={self._safe_size}GB, free_space={self._safe_free_space}, bus_type={self.bus_type})"
 
 	def __iter__(self) -> Iterator[Partition]:


Test patch: