Skip to content

Commit 53f0604

Browse files
feat: Add IO and process priority controls
This commit introduces new functionality to manage IO and CPU priority for games running through Proton, addressing performance issues during heavy IO activity (GitHub Issue #8910). - Added to enable or disable the feature. - Added to set the IO scheduling priority. - Added to set the CPU scheduling priority. - Implemented the core logic in the script to apply these settings using none: prio 0 and 0. - Updated and with documentation for the new environment variables and their usage.
1 parent 3a269ab commit 53f0604

3 files changed

Lines changed: 127 additions & 5 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,9 @@ the Wine prefix. Removing the option will revert to the previous behavior.
309309
| `noopwr` | `WINE_DISABLE_VULKAN_OPWR` | Enable hack to disable Vulkan other process window rendering which sometimes causes issues on Wayland due to blit being one frame behind. |
310310
| `hidenvgpu` | `PROTON_HIDE_NVIDIA_GPU` | Force Nvidia GPUs to always be reported as AMD GPUs. Some games require this if they depend on Windows-only Nvidia driver functionality. See also DXVK's nvapiHack config, which only affects reporting from Direct3D. |
311311
| | `WINE_FULLSCREEN_INTEGER_SCALING` | Enable integer scaling mode, to give sharp pixels when upscaling. |
312+
| | `PROTON_ENABLE_IO_PRIORITY` | Enable IO and CPU priority optimizations to improve game responsiveness during heavy IO activity like recording. Set to `0` to disable. Default: `1` (enabled). |
313+
| | `PROTON_IO_PRIORITY` | Set IO scheduling priority for games (0-7, lower = higher priority). Default: `2` (high priority). Only used when `PROTON_ENABLE_IO_PRIORITY=1`. |
314+
| | `PROTON_NICE_VALUE` | Set CPU scheduling priority (nice value) for games (-20 to 19, lower = higher priority). Default: `-2` (slightly higher priority). Requires proper system configuration. |
312315
| `cmdlineappend:` | | Append the string after the colon as an argument to the game command. May be specified more than once. Escape commas and backslashes with a backslash. |
313316
| `xalia` | `PROTON_USE_XALIA` | Enable Xalia, a program that can add a gamepad UI for some keyboard/mouse interfaces. |
314317
| `seccomp` | `PROTON_USE_SECCOMP` | **Note: Obsoleted in Proton 5.13.** In older versions, enable seccomp-bpf filter to emulate native syscalls, required for some DRM protections to work. |

docs/THREAD_PRIORITY.md

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
# Thread priorities
1+
# Thread priorities and IO scheduling
22

33
Proton supports fine-grained thread priority control using `setpriority(2)` to
44
set thread niceness values corresponding to the game threads' Windows base
5-
priority levels. However, most default Linux configurations don't allow
6-
individual threads to raise their priority, so some system configuration is
7-
likely required.
5+
priority levels. Additionally, Proton includes IO priority optimizations to
6+
improve game responsiveness during heavy IO activity.
7+
8+
## Thread Priority Configuration
9+
10+
Most default Linux configurations don't allow individual threads to raise their
11+
priority, so some system configuration is likely required.
812

913
It can be configured as a privileged user by editing the
1014
`/etc/security/limits.conf` file, or using the `/etc/security/limits.d/` conf
@@ -18,3 +22,53 @@ Where -15 could be any value between [-20,0] that will correspond to the
1822
minimum niceness (the highest priority) a thread can get to. The lower the
1923
value, the more CPU time a high priority thread will get, at the expense of
2024
others and other processes, possibly making the system less responsive.
25+
26+
## IO Priority Optimization
27+
28+
Proton automatically configures IO scheduling and CPU priorities to improve game
29+
responsiveness during heavy IO operations (such as screen recording, file
30+
downloads, or system backups). This feature is enabled by default and can help
31+
prevent games from becoming unresponsive during intensive disk activity.
32+
33+
### How it works
34+
35+
- **IO Priority**: Sets games to use the "best-effort" IO scheduling class with
36+
high priority (priority 2 by default), ensuring games get preferential access
37+
to disk resources during heavy IO operations.
38+
39+
- **CPU Priority**: Sets a slightly higher CPU scheduling priority (nice value -2)
40+
to give games a small advantage in CPU scheduling during IO-intensive periods.
41+
42+
### Environment Variables
43+
44+
- `PROTON_ENABLE_IO_PRIORITY`: Enable/disable IO priority optimizations.
45+
Set to `0` to disable, `1` to enable (default).
46+
47+
- `PROTON_IO_PRIORITY`: IO scheduling priority (0-7, lower = higher priority).
48+
Default is `2` (high priority). Only used when IO priority is enabled.
49+
50+
- `PROTON_NICE_VALUE`: CPU scheduling priority (-20 to 19, lower = higher priority).
51+
Default is `-2` (slightly higher priority). Requires proper limits.conf configuration.
52+
53+
### Usage Examples
54+
55+
```bash
56+
# Disable IO priority optimization entirely
57+
PROTON_ENABLE_IO_PRIORITY=0 %command%
58+
59+
# Use maximum IO priority (may affect system responsiveness)
60+
PROTON_IO_PRIORITY=0 %command%
61+
62+
# Use normal CPU priority but keep IO priority optimization
63+
PROTON_NICE_VALUE=0 %command%
64+
65+
# Conservative settings for shared systems
66+
PROTON_IO_PRIORITY=4 PROTON_NICE_VALUE=0 %command%
67+
```
68+
69+
### Troubleshooting
70+
71+
If you experience system unresponsiveness while gaming during heavy IO operations,
72+
you can adjust or disable these optimizations. Conservative values or disabling
73+
the feature entirely may be necessary on systems with limited resources or
74+
specific workload requirements.

proton

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1786,7 +1786,72 @@ class Session:
17861786
def run_proc(self, args, local_env=None):
17871787
if local_env is None:
17881788
local_env = self.env
1789-
return subprocess.call(args, env=local_env, stderr=self.log_file, stdout=self.log_file)
1789+
1790+
# Check if IO priority optimization is enabled (default: enabled)
1791+
enable_io_priority = os.environ.get("PROTON_ENABLE_IO_PRIORITY", "1") == "1"
1792+
1793+
# Set up IO and CPU scheduling for better performance during heavy IO activity
1794+
def preexec_fn():
1795+
if not enable_io_priority:
1796+
return
1797+
1798+
try:
1799+
# Set IO scheduling class to best-effort with high priority (lower value = higher priority)
1800+
# This helps games maintain responsiveness during heavy IO operations like recording
1801+
# ioprio_set(IOPRIO_WHO_PROCESS, pid, IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, priority))
1802+
# IOPRIO_CLASS_BE = 1, priority 2 (range 0-7, 0=highest)
1803+
import ctypes
1804+
libc = ctypes.CDLL("libc.so.6", use_errno=True)
1805+
1806+
# Constants for ioprio_set
1807+
IOPRIO_WHO_PROCESS = 1
1808+
IOPRIO_CLASS_BE = 1 # Best-effort scheduling class
1809+
1810+
def IOPRIO_PRIO_VALUE(ioprio_class, ioprio_data):
1811+
return (ioprio_class << 13) | ioprio_data
1812+
1813+
# Allow user to customize IO priority (default: 2 = high priority)
1814+
io_priority = int(os.environ.get("PROTON_IO_PRIORITY", "2"))
1815+
if io_priority < 0 or io_priority > 7:
1816+
io_priority = 2 # Fallback to safe default
1817+
1818+
# Set IO priority to best-effort class with specified priority
1819+
ioprio = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, io_priority)
1820+
result = libc.ioprio_set(IOPRIO_WHO_PROCESS, 0, ioprio)
1821+
if result != 0:
1822+
# If ioprio_set fails, it's not critical - log and continue
1823+
errno = ctypes.get_errno()
1824+
log(f"Warning: Could not set IO priority (errno: {errno}). Continuing anyway.")
1825+
1826+
# Set CPU scheduler priority (nice value) to slightly higher than normal
1827+
# This gives games a small CPU scheduling advantage during heavy IO
1828+
try:
1829+
# Allow user to customize nice value (default: -2 = slightly higher priority)
1830+
nice_value = int(os.environ.get("PROTON_NICE_VALUE", "-2"))
1831+
if nice_value < -20 or nice_value > 19:
1832+
nice_value = -2 # Fallback to safe default
1833+
1834+
os.setpriority(os.PRIO_PROCESS, 0, nice_value)
1835+
except OSError as e:
1836+
# If we can't set negative nice (higher priority), try positive nice
1837+
if e.errno == 1: # EPERM - Operation not permitted
1838+
try:
1839+
# Set nice value to 0 (normal priority) as fallback
1840+
os.setpriority(os.PRIO_PROCESS, 0, 0)
1841+
except OSError:
1842+
# If even that fails, continue without changing priority
1843+
log("Warning: Could not adjust process priority. Consider configuring /etc/security/limits.conf for better performance.")
1844+
else:
1845+
log(f"Warning: Could not set process priority: {e}")
1846+
1847+
except Exception as e:
1848+
# Don't fail the whole process if priority setting fails
1849+
log(f"Warning: Could not configure process scheduling: {e}")
1850+
1851+
if enable_io_priority:
1852+
return subprocess.call(args, env=local_env, stderr=self.log_file, stdout=self.log_file, preexec_fn=preexec_fn)
1853+
else:
1854+
return subprocess.call(args, env=local_env, stderr=self.log_file, stdout=self.log_file)
17901855

17911856
def run(self):
17921857
if shutil.which('steam-runtime-launcher-interface-0') is not None:

0 commit comments

Comments
 (0)