Repository navigation
Expand file tree
/
Copy pathperformance.nix
More file actions
246 lines (234 loc) · 10.2 KB
/
Copy pathperformance.nix
File metadata and controls
246 lines (234 loc) · 10.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
{
config,
lib,
pkgs,
inputs,
...
}:
let
zswapDisable = pkgs.writeShellScript "zswap-disable" ''
echo N > /sys/module/zswap/parameters/enabled
'';
in
{
# journald.settings not yet backported to 26.05's module tree (unstable-only as of this writing);
# swap in unstable's journald module until it lands in stable.
disabledModules = [ "system/boot/systemd/journald.nix" ];
imports = [ "${inputs.unstable}/nixos/modules/system/boot/systemd/journald.nix" ];
options.modules.performance.vendor = lib.mkOption {
type = lib.types.enum [
"amd"
"intel"
"other"
];
default = "other";
description = "CPU vendor for microcode and pstate kernel params";
};
config = {
boot.kernelParams = [
# performance
"lru_gen_enabled=1"
"zswap.enabled=0"
"transparent_hugepage=madvise"
"rcupdate.rcu_normal_after_boot=1"
]
++ lib.optionals (!((config.modules.powersave or { }).enable or false)) [
"skew_tick=1"
]
# 当 modules.powersave.enable 开启时,不设置 ignore_ppc (避免忽略固件功耗限制)
++
lib.optionals
(pkgs.stdenv.hostPlatform.isx86_64 && !((config.modules.powersave or { }).enable or false))
[
"processor.ignore_ppc=1"
];
# CPU microcode (vendor-specific via modules.performance.vendor)
hardware.cpu.amd.updateMicrocode = lib.mkIf pkgs.stdenv.hostPlatform.isx86_64 (
config.modules.performance.vendor == "amd"
);
hardware.cpu.intel.updateMicrocode = lib.mkIf pkgs.stdenv.hostPlatform.isx86_64 (
config.modules.performance.vendor == "intel"
);
boot.kernel.sysctl = {
# Network (common)
"net.core.default_qdisc" = lib.mkOverride 950 "cake";
"net.ipv4.tcp_congestion_control" = lib.mkOverride 950 "bbr";
"net.ipv4.tcp_low_latency" = lib.mkOverride 950 1;
# mkOverride 900: intentionally overrides security.nix's mkOverride 950
# (TCP timestamps traded for performance here).
"net.ipv4.tcp_timestamps" = lib.mkOverride 900 1;
"net.ipv4.tcp_fastopen" = lib.mkOverride 950 3;
"net.core.somaxconn" = lib.mkOverride 950 4096;
"net.core.netdev_max_backlog" = lib.mkOverride 950 4096;
"net.core.rmem_max" = lib.mkOverride 950 16777216;
"net.core.wmem_max" = lib.mkOverride 950 16777216;
"net.core.optmem_max" = lib.mkOverride 950 65536;
"net.ipv4.tcp_rmem" = lib.mkOverride 950 "4096 87380 16777216";
"net.ipv4.tcp_wmem" = lib.mkOverride 950 "4096 65536 16777216";
"net.ipv4.udp_rmem_min" = lib.mkOverride 950 8192;
"net.ipv4.udp_wmem_min" = lib.mkOverride 950 8192;
"net.ipv4.tcp_max_syn_backlog" = lib.mkOverride 950 8192;
"net.ipv4.tcp_max_tw_buckets" = lib.mkOverride 950 2000000;
"net.ipv4.tcp_tw_reuse" = lib.mkOverride 950 1;
"net.ipv4.tcp_fin_timeout" = lib.mkOverride 950 20;
"net.ipv4.tcp_slow_start_after_idle" = lib.mkOverride 950 0;
"net.ipv4.tcp_keepalive_time" = lib.mkOverride 950 60;
"net.ipv4.tcp_keepalive_intvl" = lib.mkOverride 950 10;
"net.ipv4.tcp_keepalive_probes" = lib.mkOverride 950 6;
"net.ipv4.tcp_mtu_probing" = lib.mkOverride 950 1;
"net.ipv4.tcp_sack" = lib.mkOverride 950 1;
"net.ipv4.tcp_adv_win_scale" = lib.mkDefault (-2);
"net.ipv4.tcp_notsent_lowat" = lib.mkDefault 16384;
# 内存压力下主动收缩接收窗口而非仅停止增长;新内核选项(6.x+),无明显下行
"net.ipv4.tcp_shrink_window" = lib.mkDefault 1;
"net.netfilter.nf_conntrack_max" = lib.mkOverride 950 1048576;
"net.netfilter.nf_conntrack_tcp_timeout_established" = lib.mkOverride 950 120;
# optimize ipv6
"net.ipv6.conf.all.accept_ra" = lib.mkOverride 950 2;
"net.ipv6.conf.default.accept_ra" = lib.mkOverride 950 2;
# VM (common)
"vm.swappiness" = lib.mkDefault 180;
"vm.dirty_bytes" = lib.mkDefault 268435456; # 256MB (≈RAM/64, for ~16GB)
"vm.dirty_background_bytes" = lib.mkDefault 134217728; # 128MB (≈RAM/128)
"vm.dirty_writeback_centisecs" = lib.mkDefault 1500;
"vm.dirty_expire_centisecs" = lib.mkDefault 1500;
"vm.watermark_boost_factor" = lib.mkDefault 0;
"vm.watermark_scale_factor" = lib.mkDefault 125;
"vm.compaction_proactiveness" = lib.mkDefault 0;
"kernel.split_lock_mitigate" = lib.mkDefault 0;
"vm.page-cluster" = lib.mkDefault 0;
"vm.nr_hugepages" = lib.mkDefault 0;
"vm.vfs_cache_pressure" = lib.mkDefault 50;
"vm.min_free_kbytes" = lib.mkDefault 65536;
"vm.stat_interval" = lib.mkDefault 10;
"kernel.hung_task_timeout_secs" = lib.mkDefault 600;
# Bazzite/Pop!_OS 都默认这个值(几乎 INT_MAX,非游戏专用特例)
"vm.max_map_count" = lib.mkOverride 900 2147483642;
"fs.inotify.max_user_instances" = lib.mkOverride 900 8192;
# CachyOS 默认值
"fs.file-max" = lib.mkDefault 2097152;
};
# kyber-iosched:确保下面 udev 规则给 NVMe 赋值 kyber 调度器时模块已加载,
# 否则可能静默失败退回默认调度器
boot.kernelModules = [ "kyber-iosched" ];
services.udev.extraRules = ''
# NVMe SSD: kyber 提供延迟隔离
ACTION=="add|change", KERNEL=="nvme[0-9]*", ENV{DEVTYPE}=="disk", ATTR{queue/scheduler}="kyber"
# SATA SSD / eMMC: 设置为 mq-deadline
ACTION=="add|change", KERNEL=="sd[a-z]*|mmcblk[0-9]*", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="mq-deadline"
# 旋转硬盘 HDD: 设置为 bfq
ACTION=="add|change", KERNEL=="sd[a-z]*", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
# Prevent bumb noise
DEVPATH=="/devices/virtual/misc/cpu_dma_latency", OWNER="root", GROUP="audio", MODE="0660"
# HDD Performance Tuning to rotational disks.
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", \
ATTRS{id/bus}=="ata", RUN+="${pkgs.hdparm}/bin/hdparm -B 254 -S 0 /dev/%k"
# When used with ZRAM, it is better to prefer page out only anonymous pages
ACTION=="change", KERNEL=="zram0", ATTR{initstate}=="1", RUN+="${zswapDisable}"
# 低延迟专业音频计时权限,与上面的 cpu_dma_latency 同一套(CachyOS)
KERNEL=="rtc0", GROUP="audio"
KERNEL=="hpet", GROUP="audio"
# SATA 链路电源管理强制最高性能,禁止 ALPM 节电唤醒延迟(CachyOS)
ACTION=="add", SUBSYSTEM=="scsi_host", KERNEL=="host*", \
ATTR{link_power_management_supported}=="1", \
ATTR{link_power_management_policy}=="*", \
ATTR{link_power_management_policy}="max_performance"
'';
systemd.services.pci-latency = lib.mkIf config.services.displayManager.enable {
description = "Adjust latency timers for PCI peripherals";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.writeShellScript "pci-latency" ''
${pkgs.pciutils}/bin/setpci -v -s '*:*' latency_timer=20
${pkgs.pciutils}/bin/setpci -v -s '0:0' latency_timer=0
${pkgs.pciutils}/bin/setpci -v -d "*:*:04xx" latency_timer=80
''}";
};
};
systemd.services."user@".serviceConfig.Delegate = lib.mkIf config.services.displayManager.enable [
"cpu"
"cpuset"
"io"
"memory"
"pids"
];
systemd.services.rtkit-daemon.serviceConfig.LogLevelMax =
lib.mkIf config.services.displayManager.enable "info";
boot.tmp.useTmpfs = lib.mkDefault true;
# THP 细粒度调优,跟 boot.kernelParams 的 transparent_hugepage=madvise 不
# 重复:那个控制要不要用大页,这两条是分配大页时的行为细化。
systemd.tmpfiles.rules = [
"w! /sys/kernel/mm/transparent_hugepage/khugepaged/max_ptes_none - - - - 409"
"w! /sys/kernel/mm/transparent_hugepage/defrag - - - - defer+madvise"
];
services.zram-generator = {
enable = lib.mkDefault true;
settings = {
"zram0" = {
# 封顶 16GB,避免大内存机器把过多内存分给 zram
"zram-size" = "min(ram/2, 16384)";
"compression-algorithm" = "zstd";
};
};
};
hardware.ksm.enable = lib.mkDefault true;
services.fwupd.enable = lib.mkDefault true;
services.fstrim = {
enable = lib.mkDefault true;
interval = lib.mkDefault "daily";
};
systemd.services.fstrim.serviceConfig = {
CPUSchedulingPolicy = "idle";
IOSchedulingClass = "idle";
};
services.earlyoom = {
enable = lib.mkDefault true;
freeMemThreshold = lib.mkDefault 5;
freeSwapThreshold = lib.mkDefault 100;
freeSwapKillThreshold = lib.mkDefault 100;
enableNotifications = lib.mkDefault true;
extraArgs = [
"--avoid"
"(exe|steam|wine|gamescope|mangohud|proton)"
];
};
systemd.oomd.enable = lib.mkDefault false;
services.scx = lib.mkIf pkgs.stdenv.hostPlatform.isx86_64 {
enable = lib.mkDefault true;
scheduler = lib.mkDefault "scx_rusty";
};
# Process priority optimization (desktop only — cachyos rules target interactive workloads)
services.ananicy = lib.mkIf config.services.displayManager.enable {
enable = lib.mkDefault true;
package = pkgs.ananicy-cpp;
rulesProvider = pkgs.ananicy-rules-cachyos;
};
services.journald.settings.Journal = lib.mkDefault {
SystemMaxUse = "64M";
ForwardToWall = false;
Storage = "persistent";
};
# tcp_fastopen_key 不轮换的话内核会在启动时生成一个固定 key 一直用下去
systemd.services."tcp-fastopen-rotate-key" = {
description = "Rotate TCP Fast Open cookie-signing key";
serviceConfig.Type = "oneshot";
script = ''
key=$(${pkgs.openssl}/bin/openssl rand -hex 16 | ${pkgs.gnused}/bin/sed -E 's/(.{8})(.{8})(.{8})(.{8})/\1-\2-\3-\4/')
echo "$key" > /proc/sys/net/ipv4/tcp_fastopen_key
'';
};
systemd.timers."tcp-fastopen-rotate-key" = {
description = "Daily TCP Fast Open key rotation";
wantedBy = [ "timers.target" ];
timerConfig = {
OnCalendar = "daily";
Persistent = true;
RandomizedDelaySec = "1h";
};
};
environment.systemPackages = [
pkgs.hdparm # udev rules require hdparm
];
};
}