Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.3.0 #9

Merged
merged 16 commits into from Oct 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [1.3.0] 2022-09-15
### Improvements
- Properly detecting all Steam games subprocesses that need to be optimized (no need to map launchers anymore)
- Launcher mapping now optimizes all matches instead of just the last born process
- New optimizer service property `launcher.mapping.found_timeout`: maximum time in *seconds* to still keep looking for a process mapped to a different process after a match. This property also affects the period to look for Steam subprocesses. (default: `10`)
- The optimizer service property `launcher.mapping.timeout` has now a default value of `60` (seconds)

### Fix
- wild card mapping to proper regex pattern

## [1.2.2] 2022-09-22
### Improvements
- Minor code refactoring and log improvements regarding AMD GPU management
Expand Down
35 changes: 18 additions & 17 deletions README.md
Expand Up @@ -460,24 +460,25 @@ makepkg -si
- It applies the optimizations changes only once per optimization request. So, if it changes the CPUs governors to performance, and you manually change them later to something else, it will not set the governors to performance again (unless another optimization request arrives).
- [Service definition file](https://github.com/vinifmor/guapow/blob/master/guapow/dist/daemon/systemd/root/guapow-opt.service)
- By default, it runs at port **5087** and demands encrypted requests for security reasons (all done automatically).
- Its settings are defined on the files: `~/.config/guapow/opt.conf` (user) or `/etc/guapow/opt.conf` (system). Preference: user > system (if running as **root**, system is the only option)
- <a name="opt_settings">Properties:</a>
- Its settings are defined on the files: `~/.config/guapow/opt.conf` (user) or `/etc/guapow/opt.conf` (system). Preference: user > system (if running as **root**, system is the only option)
- <a name="opt_settings">Properties:</a>
```
port = 5087 (TCP port)
compositor = (pre-defines the installed compositor. Options: kwin, compiz, marco, picom, compton, nvidia)
scripts.allow_root = false (allow custom scripts/commands to run at the root level)
check.finished.interval = 3 (finished applications checking interval in seconds. Min accepted value: 0.5)
launcher.mapping.timeout = 60 (maximum time in seconds to look for a process mapped to a different process. This property also affects the period to look for Steam subprocesses. float values are allowed)
launcher.mapping.found_timeout = 10 (maximum time in seconds to still keep looking for a process mapped to a different process after a match. This property also affects the period to look for Steam subprocesses. float values are allowed)
gpu.cache = false (if 'true': maps all available GPUs once after the first request (if running as a system service) or during startup (if not running as system service). Otherwise, GPUs will be mapped for every request)
gpu.id = # comma separated list of integers representing which GPU cards should be optimized (e.g: 0, 1). If not defined, all available GPUs are considered (default)
gpu.vendor = # pre-defines your GPU vendor for faster GPUs mapping. Supported: nvidia, amd
cpu.performance = false (set cpu governors and energy policy levels to full performance on startup)
request.allowed_users = (restricts users that can request optimizations, separated by comma. e.g: root,xpto)
request.encrypted = true (only accepts encrypted requests for security reasons)
profile.cache = false (cache profile files on demand to skip I/O operations. Changes to profile files require restarting)
profile.pre_caching = false (loads all existing profile files on disk in memory during the intialization process. Requires 'profile.cache' enabled)
nice.check.interval = 5 (processes nice levels monitoring interval in seconds)
```
port = 5087 (TCP port)
compositor = (pre-defines the installed compositor. Options: kwin, compiz, marco, picom, compton, nvidia)
scripts.allow_root = false (allow custom scripts/commands to run at the root level)
check.finished.interval = 3 (finished applications checking interval in seconds. Min accepted value: 0.5)
launcher.mapping.timeout = 30 (max time in seconds to find the application mapped to a given launcher. float values are allowed)
gpu.cache = false (if 'true': maps all available GPUs once after the first request (if running as a system service) or during startup (if not running as system service). Otherwise, GPUs will be mapped for every request)
gpu.id = # comma separated list of integers representing which GPU cards should be optimized (e.g: 0, 1). If not defined, all available GPUs are considered (default)
gpu.vendor = # pre-defines your GPU vendor for faster GPUs mapping. Supported: nvidia, amd
cpu.performance = false (set cpu governors and energy policy levels to full performance on startup)
request.allowed_users = (restricts users that can request optimizations, separated by comma. e.g: root,xpto)
request.encrypted = true (only accepts encrypted requests for security reasons)
profile.cache = false (cache profile files on demand to skip I/O operations. Changes to profile files require restarting)
profile.pre_caching = false (loads all existing profile files on disk in memory during the intialization process. Requires 'profile.cache' enabled)
nice.check.interval = 5 (processes nice levels monitoring interval in seconds)
```

- Its installation can be managed using the **guapow-cli** tool:
- `guapow-cli install-optimizer`: copies the service definition file to the appropriate directory, starts and enables it.
Expand Down
25 changes: 2 additions & 23 deletions example/launcher/games/launchers
@@ -1,30 +1,9 @@
BootGGXrd.bat=GuiltyGearXrd.e # Guilty Gear Xrd
TEKKEN 7.exe=TekkenGame-Win6 # Tekken 7
Out of Space.x86_64=Out of Space.x8 # Out Of Space (windows)
MVCI.exe=c%*\Win64\MVCI.exe # Marvel vs Capcom Infinite
trine2_launcher.exe=c%trine2_32bit.exe # Trine 2 (windows)
DBFighterZ.exe=RED-Win64-Shipp # Dragon Ball FighterZ
launcher.exe=Fouc.exe # FlatOut: Ultimate Carnage (windows)
Pacer.exe=Pacer-Win64-Shi # Pacer
XenonRacer.exe=XenonRacer-Win6 # Xenon Racer
hl2.sh*=hl2_linux # Portal 1 / Team Fortress 2 (native)
Overlanders.exe -FULLSCREEN=Overlanders-Win # Overlanders
ATV.exe=Racer-Win64-Shi # ATV Drift and Tricks
Out of Space.x86_64=Out of Space.x8 # Out Of Space (windows)
DH.exe=DH-Win64-Shippi # Destroy All Humans
Launcher.exe*-uplay_steam_mode=PrinceOfPersia_ # Prince Of Persia (2008)
BmLauncher.exe=ShippingPC-BmGa # Batman Arkham Asylum: GOTY
Dirt4.sh=Dirt4 # Dirt 4 (native)
EverspaceWithSystemLibraries.sh=RSG-Linux-Shipp # Everspace (native)
RSG-Win64-Shipping.exe*=RSG-Win64-Shipp # Everspace (windows)
Sonic & SEGA All-Stars Racing.exe=Sonic & SEGA Al # Sonic and Sega All-Stars Racing Transformed
Launcher.exe*-uplay_steam_mode=PrinceOfPersia_ # Prince Of Persia (2008)
portal2.sh*=portal2_linux # Portal 2 (native)
StreetFighterV.exe=StreetFighterV. # Street Fighter V
HellbladeGame.exe=HellbladeGame-W # Hellblade: Senua's Sacrifice
SamuraiShodown.exe=SamuraiShodown- # Samurai Shodown (2020)
csgo.sh*=csgo_linux64 # CS Go (native)
MeowMotors.exe=MeowMotors-Win6 # Meow Motors
ShadowOfTheTombRaider.sh=c%*/ShadowOfTheTombRaider # Shadow Of The Tomb Raider (native)
Raji.exe=Raji-Win64-Ship # Raji: an ancient epic
start_protected_game.exe*=MultiVersus-Win # MultiVersus
Mordhau.exe=CrRendererMain # Mordhau
COTS.exe=BlueCode-Win64- # Call Of The Sea
2 changes: 1 addition & 1 deletion guapow/__init__.py
Expand Up @@ -2,4 +2,4 @@

ROOT_DIR = os.path.dirname(os.path.abspath(__file__))
__app_name__ = 'guapow'
__version__ = '1.2.2'
__version__ = '1.3.0'
23 changes: 16 additions & 7 deletions guapow/common/config.py
Expand Up @@ -75,6 +75,7 @@ class OptimizerConfig(RootFileModel):
'scripts.allow_root': ('allow_root_scripts', bool, True),
'check.finished.interval': ('check_finished_interval', float, None),
'launcher.mapping.timeout': ('launcher_mapping_timeout', float, None),
'launcher.mapping.found_timeout': ('launcher_mapping_found_timeout', float, None),
'gpu.cache': ('gpu_cache', bool, True),
'gpu.id': ('gpu_ids', Set[int], None),
'gpu.vendor': ('gpu_vendor', str, None),
Expand All @@ -85,16 +86,17 @@ class OptimizerConfig(RootFileModel):

def __init__(self, port: Optional[int] = None, compositor: Optional[str] = None,
allow_root_scripts: Optional[bool] = False,
check_finished_interval: Optional[float] = None, launcher_mapping_timeout: Optional[float] = 30,
gpu_cache: Optional[bool] = False, cpu_performance: Optional[bool] = None,
profile_cache: Optional[bool] = None, pre_cache_profiles: Optional[bool] = None,
gpu_vendor: Optional[str] = None, renicer_interval: Optional[float] = None,
gpu_ids: Optional[Set[int]] = None):
check_finished_interval: Optional[float] = None, launcher_mapping_timeout: Optional[float] = 60,
launcher_mapping_found_timeout: Optional[float] = 10, gpu_cache: Optional[bool] = False,
cpu_performance: Optional[bool] = None, profile_cache: Optional[bool] = None,
pre_cache_profiles: Optional[bool] = None, gpu_vendor: Optional[str] = None,
renicer_interval: Optional[float] = None, gpu_ids: Optional[Set[int]] = None):
self.port = port
self.compositor = compositor
self.allow_root_scripts = allow_root_scripts
self.check_finished_interval = check_finished_interval
self.launcher_mapping_timeout = launcher_mapping_timeout
self.launcher_mapping_found_timeout = launcher_mapping_found_timeout
self.gpu_cache = gpu_cache
self.gpu_vendor = gpu_vendor
self.gpu_ids = gpu_ids
Expand All @@ -121,6 +123,7 @@ def is_valid(self) -> bool:
self.profile_cache is not None,
self.has_valid_check_finished_interval(),
self.has_valid_launcher_mapping_timeout(),
self.has_valid_launcher_mapping_found_timeout(),
self.has_valid_renicer_interval()])

def has_valid_port(self) -> bool:
Expand All @@ -129,6 +132,9 @@ def has_valid_port(self) -> bool:
def has_valid_launcher_mapping_timeout(self) -> bool:
return self.launcher_mapping_timeout is not None and self.launcher_mapping_timeout >= 0

def has_valid_launcher_mapping_found_timeout(self) -> bool:
return self.launcher_mapping_found_timeout is not None and self.launcher_mapping_found_timeout >= 0

def has_valid_check_finished_interval(self) -> bool:
return self.check_finished_interval is not None and self.check_finished_interval >= 0.5

Expand All @@ -149,7 +155,10 @@ def setup_valid_properties(self):
self.check_finished_interval = 3

if not self.has_valid_launcher_mapping_timeout():
self.launcher_mapping_timeout = 30
self.launcher_mapping_timeout = 60

if not self.has_valid_launcher_mapping_found_timeout():
self.launcher_mapping_found_timeout = 10

if self.gpu_cache is None:
self.gpu_cache = False
Expand Down Expand Up @@ -212,7 +221,7 @@ def is_service() -> bool:
@classmethod
def empty(cls) -> "OptimizerConfig":
instance = cls(allow_root_scripts=None, check_finished_interval=None, launcher_mapping_timeout=None,
gpu_cache=None)
gpu_cache=None, launcher_mapping_found_timeout=None)
instance.request = None
return instance

Expand Down
23 changes: 0 additions & 23 deletions guapow/common/steam.py
@@ -1,26 +1,3 @@
import os.path
import re
from typing import Optional, Tuple

RE_STEAM_CMD = re.compile(r'^.+\s+SteamLaunch\s+AppId\s*=\s*\d+\s+--\s+(.+)')
RE_PROTON_CMD = re.compile(r'^.+/proton\s+waitforexitandrun\s+(/.+)$')
RE_EXE_NAME = re.compile(r'^(.+\.\w+)(\s+.+)?$')


def get_exe_name(file_path: str) -> Optional[str]:
exe_name = RE_EXE_NAME.findall(os.path.basename(file_path))
return exe_name[0][0].strip() if exe_name else None


def get_proton_exec_name_and_paths(cmd: str) -> Optional[Tuple[Optional[str], str, str]]:
if cmd:
result = RE_PROTON_CMD.findall(cmd)
if result:
return get_exe_name(result[0]), 'Z:{}'.format(result[0].replace('/', '\\')), result[0]


def get_steam_runtime_command(cmd: str) -> Optional[str]:
if cmd:
result = RE_STEAM_CMD.findall(cmd)
if result:
return result[0].strip()
2 changes: 1 addition & 1 deletion guapow/common/util.py
Expand Up @@ -19,7 +19,7 @@ def has_any_regex(word: str) -> bool:

def map_only_any_regex(word: str) -> Optional[Pattern]:
escaped_word = re.escape(re_any_operator.sub('@', word))
return re.compile(r'^{}$'.format(escaped_word.replace('@', '.+')))
return re.compile(r'^{}$'.format(escaped_word.replace('@', '.*')))


def strip_file_extension(cmd: str) -> Optional[str]:
Expand Down
3 changes: 2 additions & 1 deletion guapow/dist/daemon/opt.conf
Expand Up @@ -5,7 +5,8 @@
# compositor = # pre-defines the installed compositor. Options: kwin, compiz, marco, picom, compton, nvidia
# scripts.allow_root = false # allow custom scripts/commands to run at the root level
# check.finished.interval = 3 # finished applications checking interval in seconds
# launcher.mapping.timeout = 30 # max time in seconds to find the application mapped to a given launcher. float values are allowed
# launcher.mapping.timeout = 60 (maximum time in seconds to look for a process mapped to a different process. This property also affects the period to look for Steam subprocesses. float values are allowed)
# launcher.mapping.found_timeout = 10 (maximum time in seconds to still keep looking for a process mapped to a different process after a match. This property also affects the period to look for Steam subprocesses. float values are allowed)
# gpu.cache = false # if 'true': maps all available GPUs on startup. Otherwise, GPUs will be mapped for every request
# gpu.id = # comma separated list of integers representing which GPU cards should be optimized (e.g: 0, 1). If not defined, all available GPUs are considered (default)
# gpu.vendor = # pre-defines your GPU vendor for faster GPUs mapping. Supported: nvidia, amd
Expand Down
22 changes: 16 additions & 6 deletions guapow/service/optimizer/flow.py
@@ -1,4 +1,5 @@
from asyncio import Lock
from logging import Logger
from typing import Set, Optional


Expand All @@ -7,23 +8,32 @@ class OptimizationQueue:
Responsible to properly control what is being processed
"""

def __init__(self, queued_pids: Set[int]):
def __init__(self, queued_pids: Set[int], logger: Optional[Logger] = None):
self._queued_pids = queued_pids
self._lock_queued_pids = Lock()
self._logger = logger

def _log(self, msg: str):
if self._logger:
self._logger.debug(msg)

async def add_pid(self, pid: int) -> bool:
async with self._lock_queued_pids:
if pid not in self._queued_pids:
self._queued_pids.add(pid)
return True
if pid is not None:
async with self._lock_queued_pids:
if pid not in self._queued_pids:
self._log(f"Adding pid {pid} to the optimization queue")
self._queued_pids.add(pid)
return True

return False

async def remove_pids(self, *pids: int):
if pids is not None:
async with self._lock_queued_pids:
for pid in pids:
self._queued_pids.discard(pid)
if pid is not None:
self._log(f"Removing pid {pid} from the optimization queue")
self._queued_pids.discard(pid)

def get_view(self) -> Optional[Set[int]]:
if self._queued_pids is not None:
Expand Down