Skip to content

About

Windows 系统性能监控桌面小工具 - Tauri 2 + Rust + TypeScript

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

🖥️ 系统监控悬浮窗 (sys_monitor_tauri)

🌐 English

Windows 桌面系统监控悬浮窗:透明置顶、托盘常驻,实时显示 CPU、内存、GPU、磁盘、网络与进程占用,支持多套显示风格预设与分模块自定义。

✨ 功能

  • ⚡ CPU:占用率环形图 + 实时折线曲线 + 处理器型号
  • 💾 内存:占用率进度条 + 已用 / 总量(GB)
  • 🎮 GPU:每块显卡一行,显示型号、占用率、显存占用
  • 💽 磁盘:容量占用率(默认取最满的盘,卡片上标出盘符与剩余空间;可在设置里指定显示哪个盘)+ 实时读写速度(单位按量级自动换算:KB/s → MB/s → GB/s)
  • 🌐 网络:实时下载 / 上传速度(单位按量级自动换算:KB/s → MB/s → GB/s)
  • ⚙️ 进程:内存占用 Top 8
  • 🎨 显示风格:4 套预设 + 分模块自定义
  • 📌 系统托盘:显示 / 隐藏、置顶 / 取消置顶、打开设置、退出
  • 📊 托盘显示:把最多 4 个指标(CPU / 内存 / GPU / 网络)的数字直接画在托盘图标上
  • 📝 托盘文字:在任务栏托盘图标左边贴一行文字,如 CPU:60% || GPU0:30% || 内存:25%
  • 🕹️ 游戏模式:屏幕角落一层小字,固定显示 CPU / GPU0 / GPU1 / FPS 四项;颜色、字号、横竖排列都能改,位置支持右上 / 左上 / 拖动自定义;窗口点透,不挡游戏操作
  • 🎯 帧率(FPS):游戏模式里显示真实采集的帧率——后端订阅系统的画面呈现事件,覆盖 D3D11 / D3D12 / Vulkan 等一切走 DXGI 呈现路径的程序;需要管理员权限,普通权限下显示 —
  • ⌨️ 全局快捷键:Ctrl + Alt + M 切换显示 / 隐藏

📝 磁盘卡片上的百分比是「容量占用率」,不是任务管理器里那种「活动率 / 忙碌时间」。默认取所有本地盘中最满的那个,卡片标题会标出是哪个盘(如 磁盘 F:),右下角同时给出该盘剩余空间。旁边的「读 / 写」才是吞吐量,单位按量级自动换算(KB/s → MB/s → GB/s,与网络卡同一套换算)——所以「87% 占用 + 读 0.0 KB/s」并不矛盾,意思是「F 盘快满了,但此刻磁盘完全空闲」。

想固定看某个盘(比如系统盘 C:),在设置里把「显示磁盘」从「自动(最满的盘)」改成对应盘符即可,改完立刻生效。切换后卡片标题、百分比、剩余空间、读写速度会一起跟着换到那个盘。

另外,Windows 上那些没有盘符的恢复分区(WINRETOOLS、Image、DELLSUPPORT 之类)不会被计入,否则它们动辄 90%+ 的占用会一直霸占这个数字。

🛠️ 技术栈

层 技术
前端 HTML + CSS + TypeScript + Vite
桌面框架 Tauri 2
后端 Rust(sysinfo + DXGI / PDH 采集)
帧率采集 ETW 实时会话(订阅 Present 事件,覆盖 D3D11 / D3D12 / Vulkan)
托盘 / 全局快捷键 Tauri tray API / tauri-plugin-global-shortcut

📦 安装

🥇 直接使用

从 Releases 下载 sys_monitor_tauri.exe 单文件版,放到任意目录双击运行即可 —— 无需安装,配置与运行数据写在用户目录下。

📦 Release 上只发布这一个单文件。系统监控_x.x.x_x64-setup.exe / 系统监控_x.x.x_x64_zh-CN.msi 安装包需要自己执行 npx tauri build 完整打包生成(见下)。

🧱 从源码构建

环境要求:

  • 🦀 Rust(stable,含 MSVC 工具链)
  • 🟢 Node.js 18+
  • 🌐 WebView2(Windows 10/11 自带)
# 安装前端依赖
npm install

# 调试运行(编译 Rust 并打开窗口,支持热更新)
npx tauri dev
# 只构建 exe(推荐)
npx tauri build --no-bundle

# 完整打包(exe + MSI / NSIS 安装包)
npx tauri build

产物位置:

产物 路径
🚀 exe src-tauri\target\release\sys_monitor_tauri.exe(单文件,可直接运行)
📦 安装包 src-tauri\target\release\bundle\

⚠️ 完整打包需要 WiX 工具链,首次构建会自动下载。

⚠️ MSI 的本地化语言固定为 zh-CN(tauri.conf.json → bundle.windows.wix.language)。不要删掉这项:默认按 en-US 生成 locale.wxl 时代码页是 1252,装不下中文 productName「系统监控」,light.exe 会在写 MSI 摘要流时直接报错退出。

🐚 Git Bash / MSYS2 用户注意:PATH 里的 /usr/bin/link.exe 是 coreutils 的 link,会顶掉 MSVC 的链接器,报 link: missing operand after '\377\376'(\377\376 是 UTF-16 BOM)。请在「x64 Native Tools Command Prompt for VS」中构建,或手动把 MSVC 的 bin\Hostx64\x64 放到 PATH 最前面并设好 LIB。更多环境坑见 docs/development-notes.md。

🖱️ 使用方法

🪟 窗口操作

  • 主窗口默认 320×480,可调范围 280×360 ~ 600×900,无边框、透明
  • 标题栏整条可拖动;窗口四边与四角都有透明缩放热区,可自由拖拽缩放
  • 主窗口位置可选:悬浮自由拖动 / 固定右上角 / 固定左上角(多显示器下以窗口所在显示器的工作区为基准,不会压到任务栏)。这一项在设置里叫「主窗口位置」,只作用于主窗口本身;游戏模式那几行指示器的位置是另一项(「指示器位置」)。

⌨️ 全局快捷键与托盘

  • Ctrl + Alt + M:显示 / 隐藏主窗口(注册失败时——比如这个组合已被别的程序占用——不影响启动,只是该快捷键不可用)
  • 托盘图标右键菜单:显示 / 隐藏、置顶 / 取消置顶、打开设置、退出

🎛️ 设置

点击托盘菜单「设置」打开独立设置窗口,修改后即时生效,主窗口无需重启。

「始终置顶」对主窗口和设置窗口同时生效:勾选时两者都浮在其他窗口之上,取消后两者都不再置顶(设置面板不会自己留在最上层)。

⚙️ 配置项

配置项 说明
📌 始终置顶 主窗口与设置窗口都保持在其他窗口之上
🚀 开机自启动 随系统登录自动启动
🚪 关闭行为 最小化到托盘 / 直接退出
📊 托盘显示 把指标数字画在托盘图标上;仅当「关闭行为 = 最小化到托盘」时才出现
📐 托盘指标 CPU / 内存 / GPU0 / GPU1 / 网络,最多 4 个,按勾选顺序排进图标
📝 托盘文字 在任务栏托盘图标左边贴一行文字(如 `CPU:60%
🎨 托盘文字项 同上的指标,最多 5 个,按勾选顺序从左到右排
✨ 数值闪动 数值变化时那一项闪一下(涨红跌绿),可关
🖌️ 托盘文字颜色 自动(跟随任务栏明暗)/ 深灰 / 浅灰 / 白 / 黑 / 蓝 / 绿 / 橙 / 红
🔠 托盘文字字号 9 ~ 20
🕹️ 游戏模式 屏幕角落显示 CPU / GPU0 / GPU1 / FPS;仅当「关闭行为 = 最小化到托盘」时可勾选,选「直接退出」时置灰并自动取消勾选
🖌️ 游戏模式颜色 默认(亮绿)/ 白 / 黑 / 红 / 自适应(跟随系统明暗)
🔠 游戏模式字号 10 ~ 36
🧭 游戏模式排列 水平(一行)/ 纵向(一列)
📍 指示器位置(游戏模式) 屏幕右上角 / 屏幕左上角 / 自定义(可拖动定位);只移动那几行指示器,与主窗口位置无关
🪟 主窗口位置 悬浮自由拖动 / 固定右上角 / 固定左上角
🎨 文字颜色 7 种预设
🔠 字号 10 ~ 18
🎭 显示风格 4 套预设 + 5 个模块的下拉自定义
💽 显示磁盘 磁盘卡显示哪个盘:自动(最满的盘)或指定盘符;下拉选项按本机实际磁盘动态生成
⏱️ 刷新频率 采集间隔:200 毫秒 / 500 毫秒(默认)/ 1 秒 / 2 秒 / 5 秒

配置文件位于 %APPDATA%\com.duan.sys-monitor\settings.json,字段带默认值,旧版本配置文件向前兼容(缺字段自动补默认值,不会因为多/少一个字段就整份重置)。

保存走「先写临时文件再改名」的原子替换,中途断电 / 进程被强杀都不会留下半截 JSON。万一配置文件确实损坏(解析不了),启动时会把它改名成 settings.json.bad 留档,再用默认值启动 —— 不会一声不响地把旧文件覆盖掉。

磁盘卡的盘符由 diskTarget 控制:

{
  "diskTarget": "auto"
}
取值 含义
"auto" 默认。自动跟随所有本地盘中最满的那个
"C:" / "D:" … 固定显示该盘。盘符取自设置窗口「显示磁盘」下拉框里的选项;若该盘当前不存在(拔了移动硬盘),会自动退回 "auto",卡片不会变成 0% 空壳

🎭 显示风格

设置 →「显示风格」,四个预设按钮一键整套切换:

预设 布局 说明
🌱 默认 单列 CPU 圆环 + 曲线,内存 / GPU / 磁盘进度条,网络双指标卡片
📈 曲线 单列 所有模块迷你折线图,便于观察趋势
✂️ 极简 单列 每个模块压缩为一行「名称 + 数值」,占用桌面空间最小
🔲 双列 双列网格 模块两列排布,窗口变矮,适合贴屏幕侧边

分模块自定义:每个模块有独立下拉框(CPU:圆环 / 迷你曲线 / 进度条 / 纯文字;内存、GPU、磁盘:进度条 / 迷你曲线 / 纯文字;网络:默认卡片 / 纯文字 / 迷你曲线)。改动任意下拉即进入「自定义」模式,点击预设按钮则整套套用。磁盘读写与网络速度的数值与单位都一起自动换算(KB/s → MB/s → GB/s),三种样式共用同一套换算。

磁盘模块还多一个「显示磁盘」下拉框,用来指定磁盘卡显示哪个盘——它和显示风格无关,改它不会把风格切成「自定义」。同理,「刷新频率」也属于性能选项,改它同样不会影响显示风格。

📄 配置文件示例

{
  "autoStart": false,
  "closeAction": "toTray",
  "trayStyle": "simple",
  "desktopMode": "floating",
  "textColor": "#FFFFFF",
  "fontSize": 12,
  "alwaysOnTop": true,
  "stylePreset": "default",
  "layout": "list",
  "cpuDisplay": "ring",
  "memDisplay": "bar",
  "gpuDisplay": "bar",
  "diskDisplay": "bar",
  "diskTarget": "auto",
  "refreshInterval": 500,
  "netDisplay": "stats",
  "trayDisplay": false,
  "trayItems": [],
  "trayText": false,
  "trayTextItems": ["cpu", "mem"],
  "trayTextColor": "auto",
  "trayTextFont": 12,
  "trayTextFlash": true,
  "gameMode": false,
  "gameColor": "default",
  "gameFont": 16,
  "gameLayout": "horizontal",
  "gamePosition": "topRight",
  "gameX": 24,
  "gameY": 24
}

合法取值:

字段 取值
closeAction toTray | exit
desktopMode floating | topRight | topLeft
textColor 任意十六进制色值(界面里给了 7 个预设)
fontSize 10 – 18
stylePreset default | curve | minimal | cards | custom
layout list(单列)| grid(双列)
cpuDisplay ring | spark | bar | text
memDisplay / gpuDisplay / diskDisplay bar | spark | text
diskTarget auto(最满的盘)| 盘符,如 C:
refreshInterval 200 – 5000(毫秒),超范围会被夹到边界值
netDisplay stats | text | spark
trayDisplay true | false —— 是否把数字画在托盘图标上(界面里只在 closeAction: "toTray" 时提供)
trayItems cpu | mem | gpu0 | gpu1 | net(gpu = gpu0 的旧写法),顺序即摆放顺序,最多 4 个
trayText true | false —— 是否显示任务栏文字条
trayTextItems 取值同 trayItems,顺序 = 从左到右,最多 5 个
trayTextColor auto | 任意 #RRGGBB
trayTextFont 9 – 20(px),超范围会被夹到边界值
trayTextFlash true | false —— 数值变化时那一项闪一下
gameMode true | false —— 是否显示游戏模式浮层(需要 closeAction: "toTray",否则会被强制落回 false)
gameColor default(亮绿)| white | black | red | auto
gameFont 10 – 36(px),超范围会被夹到边界值
gameLayout horizontal | vertical
gamePosition topRight | topLeft | custom
gameX / gameY 浮层左上角的物理像素坐标;仅在 gamePosition 为 custom 时生效

trayStyle 是历史遗留字段,只为兼容旧配置保留,前端不再发送它。

📊 托盘显示(trayDisplay / trayItems)

勾上「托盘显示」并选好指标后,托盘图标会变成一块数字牌,指标越少、字越大:

选了几个 排布 字大概多大(20px 图标)
1 个 占满整块 ≈17px,最清楚
2 个 上下两行 ≈12px,很清楚
3~4 个 左上 / 右上 / 左下 / 右下 四角 ≈7px,能看但挤

按勾选顺序排(先勾的排前面),最多 4 个。设置面板里有同尺寸的放大预览。

{
  "trayDisplay": true,
  "trayItems": ["cpu", "mem", "gpu0", "net"]
}
trayItems 取值 指标 图标上显示 悬浮提示
"cpu" CPU 占用率整数(23) CPU 23%
"mem" 内存 占用率整数(62) 内存 62%
"gpu0" / "gpu1" 第 1 / 第 2 块显卡 利用率整数(45) GPU0 45%
"gpu" 同 gpu0(旧配置的写法,仍然认) 同上 GPU 45%
"net" 网络 下载速率:< 1024 KB/s 取整(999)、1024~10239 显示 4.2M、再快显示 430M(1M = 1024 KB/s) 网络 ↓4.2 MB/s ↑20.8 KB/s

几点要知道的:

  • 这一项只在「关闭行为 = 最小化到托盘」时出现。 选「直接退出」时进程不驻留,托盘图标一关就没,这些选项没有意义。
  • 图标上只放得下 1~4 个字符。 Windows 通知区图标就是 16 px(125% 缩放 20 px、200% 缩放 32 px),四角里每格才 8~10 px,所以数字一律取整、不带单位、不带小数。完整数值、单位、上传 / 下载速率看托盘悬浮提示(鼠标停在图标上)——提示里的单位会跟着数值走(KB/s / MB/s / GB/s),上下行各标各的。
  • 想要又全又清楚,用下面的「托盘文字」:图标是系统固定尺寸,塞不下标签和单位。
  • 图标按 devicePixelRatio 出图(100% 缩放画 16 px、125% 画 20 px),尽量不让系统再缩一次;数值没变时不重绘、不 IPC。
  • GPU1 只有在机器上真有第二块显卡时才会显示(避免一个恒为 0 的假指标)。
  • 托盘上不再出现磁盘:容量占用率和读写速度只在主窗口的磁盘卡上看(那张卡本来就把百分比、读写、剩余空间都放在一起了)。老配置里若还留着磁盘项,打开一次设置会自动清掉。
  • 网络口径与主窗口一致(都是下载速率上图标)。
  • 取消勾选「托盘显示」或一个指标都不选,图标会还原成应用默认图标,不会停在最后一帧数字上。

📝 托盘文字(trayText / trayTextItems / trayTextColor / trayTextFont / trayTextFlash)

想要 CPU:60% || GPU0:30% || 内存:25% 这样带标签、带单位的一行字,塞进托盘图标是不可能的(图标就 16~20 px)。所以这一项换了个做法:像 TrafficMonitor 那样,在任务栏托盘图标左边贴一个无边框小窗口显示这行字,任务栏在上下左右都能跟随。

它的宽度跟着内容走(换指标、改字号、数值位数变化都会重算一次),窗口右边固定贴着通知区、向左生长,所以数字变长时是左边在动、文字本身不会在窗口里漂。刻意不预留宽度:预留会让低速值(↓0.4KB/s)在标签后面空出一大块,代价更难看。

它和「托盘显示」一样,整块只在「关闭行为 = 最小化到托盘」时出现,选「直接退出」时既看不到这一项、文字条也不会显示(属于驻留托盘模式的功能)。

{
  "trayText": true,
  "trayTextItems": ["cpu", "gpu0", "mem"],
  "trayTextColor": "auto",
  "trayTextFont": 12,
  "trayTextFlash": true
}
字段 说明
trayTextItems 与 trayItems 同一套取值,顺序 = 从左到右,最多 5 个(= 全选);没装第二块卡时 gpu1 自动跳过。缺字段时默认 ["cpu","mem"](不是空——空列表等于什么都不显示)
trayTextColor "auto"(默认,跟随任务栏明暗自动选深/浅字)或任意 #RRGGBB
trayTextFont 字号,9 ~ 20,超出范围会被夹到边界值
trayTextFlash 默认 true。数值变化时那一项闪一下:涨了闪红、跌了闪绿(A 股习惯),600ms 内淡出。只闪背景不动文字颜色,深/浅任务栏都看得清

几点要知道的:

  • 写法是刻意压紧的:字间距 0,数字紧跟单位(1.0KB/s 而不是 1.0 KB/s),冒号用半角。数值按自然宽度排、不预留,所以标签后面不会空出一块;代价是数字进位(9↔10、99↔100)时那一段会挪 7px 左右。悬浮提示里保留完整写法(网络 ↓4.2 MB/s ↑20.8 KB/s)。
  • 分隔符(默认 ||)与它的样式(opacity: 0.35 + 常规字重 = 浅灰细线)都在源码里,不在设置界面: 分隔符是 src/main.ts 顶部的 TRAY_TEXT_SEP(改这里即可,旁边的注释写了它被引用的两处都会自动跟随); 颜色/粗细是 src/styles.css 里的 .tt-sep(想让它和数字一样实:opacity: 1; font-weight: 600)。 两者都需要重新构建(npx tauri build --no-bundle)才生效。
  • 设置里有「文字条状态」一行,实时显示后端判定:已贴在任务栏上 / 未显示:任务栏处于自动隐藏 / 未显示:前台是全屏应用 / 未显示:开关没开…。勾了却看不到时先看它,不用对着任务栏猜。
  • 文字条不挡任何点击(点透),也不进任务栏 / Alt+Tab。点在它上面的点击会落到任务栏,任务栏会顺势把自己顶到最前面 —— 文字条每轮巡检会把自己搬回任务栏前面,所以点完它照样在。
  • 任务栏自动隐藏、或前台是全屏应用(全屏游戏、视频)时会自动隐藏,不会压在别人的全屏画面上。
  • 只跟随主任务栏(Shell_TrayWnd);副屏任务栏不显示。
  • 落点分两档巡检:每 40ms 只比一次窗口 z 序(点任务栏后那行字会被任务栏盖住,这一档负责立刻搬回它前面,所以点一下不会「闪没」),约 320ms 才完整重算一次落点。改任务栏位置、改缩放、插拔显示器都会自动跟上。
  • 颜色默认 auto:读的是系统的「Windows 模式」(SystemUsesLightTheme),浅色任务栏配深字、深色任务栏配浅字。
  • 设置里的预览是照着任务栏画的:左边文字条、右边托盘图标与时钟示意,底色跟着任务栏明暗,字号按当前设置,数值用的也是实时数据(所以预览里的闪动就是任务栏上的闪动)。

🕹️ 游戏模式(gameMode / gameColor / gameFont / gameLayout / gamePosition / gameX / gameY)

打游戏时想余光扫一眼帧率和显卡占用,不需要整块监控面板。勾上「游戏模式」,屏幕角落就会出现一行小字,只有 CPU / GPU0 / GPU1 / FPS 四项——刻意不多塞指标,它就是给游戏场景准备的。

{
  "gameMode": true,
  "gameColor": "default",
  "gameFont": 16,
  "gameLayout": "horizontal",
  "gamePosition": "topRight",
  "gameX": 24,
  "gameY": 24
}
字段 说明
gameMode 开关。只在「关闭行为 = 最小化到托盘」时可勾选
gameColor "default"(亮绿 #39FF14)/ "white" / "black" / "red" / "auto"(跟随系统明暗自动挑深/浅字)
gameFont 字号,10 ~ 36,超出范围会被夹到边界值
gameLayout "horizontal"(一行)/ "vertical"(一列)
gamePosition "topRight" / "topLeft" / "custom"(界面上分别写作「屏幕右上角 / 屏幕左上角 / 自定义(拖动定位)」)
gameX / gameY 只在 "custom" 下有意义:拖动定位时记录下来的左上角坐标(物理像素)

每项写法和托盘文字一致:标签 + 空格 + 数值(CPU 23%、GPU0 45%、FPS 144),横向排列时各项之间是等距间隔,不带分隔符。

几点要知道的:

  • 联动:这一项和「托盘显示」「托盘文字」同性质,都属于驻留托盘模式的功能。把「关闭行为」手动改成「直接退出」时,它的勾选框会立刻置灰 + 自动取消勾选(后端也会强制把 gameMode 落成 false),已经贴在屏幕上的那行字同时收走——不会留下一个没有托盘托底、关不掉的悬浮层。
  • 默认亮绿是给游戏画面挑的:深色场景里最跳。白 / 黑两色给浅色或明亮场景兜底,auto 跟随系统「Windows 模式」,口径和托盘文字条完全一致。
  • 整层点透:这行字不吃任何鼠标事件,所以不会挡住游戏里的点击、拖拽、开镜;它也不进任务栏、不进 Alt+Tab。只有在你进入「拖动定位」时才临时接管鼠标(不拖了立刻恢复点透)。
  • 位置:右上 / 左上按主显示器计算,统一留 16px 边距。把「指示器位置」选成**「自定义(拖动定位)」时会直接进入可拖状态**——那行字会跳到配置里记着的自定义坐标、带上虚线边框,按住它(鼠标落在那几行字上即可,不用挑缝)拖到目标位置;停手约 1.5 秒后自动落定,坐标写回配置,下次进游戏还在原位。落定后重新变回点透。
    • 副手:设置里那一行的「开始拖动」按钮同样能进入可拖状态——切换过自定义坐标、或者中途点「结束拖动」提前收工时用它重新武装。
    • 若武装后一直没拖过(比如选了自定义又忘了拖),30 秒后自动结束,把点透还给游戏;想提前结束就点「结束拖动」。
  • ⚠️ 这一项只管那几行指示器,和主窗口位置无关。 两者都叫得出「右上角 / 左上角」,所以设置里刻意分开命名并隔开放:指示器是「指示器位置」(在游戏模式块内),主窗口是「主窗口位置」(在最上面的主窗口选项里)。实测确认改「指示器位置」时主窗口纹丝不动(改前主窗口与指示器的矩形互不影响)。
  • 排列:横向是一行,纵向每项一行(适合贴屏幕侧边竖着看)。
  • 纵向时名称与数值各自成一列:名称列按最宽的名称(GPU0)定宽、数值列按最宽的数值(100% / 三位帧率)定宽,于是 CPU / GPU0 / GPU1 / FPS 的左边缘对齐、它们下面数值的左边缘也对齐;顺带把「数值位数变化」对窗口宽度的影响也消掉了。
  • 尺寸不跟着数值抖:每段都按「最宽可能出现」的文本预留(百分比按 100%、帧率按三位数留),所以 9↔10、99↔100 进位时窗口尺寸不变、文字不会左右跳。
  • 没装第二块显卡时不出现 GPU1,只留三项——避免一个恒为 0 的假指标。FPS 则永远保留。
  • 设置里有一行「游戏模式状态」(和「文字条状态」同一套路),直接报后端判定:已显示 / 拖动定位中:拖到目标位置,松手 1.5 秒后自动记住 / 拖动定位中:按住那几行字拖到目标位置(未拖动时 30 秒后自动结束) / 等待前端测量文字尺寸… / 未显示:开关没开,或「关闭行为」不是最小化到托盘 / 未显示:取不到主显示器。勾了却没看到那行字时先看它。
  • FPS 是真实采集的:后端订阅系统的画面呈现(Present)事件,覆盖 D3D11 / D3D12 / Vulkan 等一切走 DXGI 呈现路径的游戏。它取的是正在出帧的那个程序——前台优先(游戏在前台时就是它),前台只是静态界面时退到最忙的那个(所以切出去看一眼设置,overlay 上仍是后台游戏的帧率);没有程序在持续出帧时就显示 —,不会拿"静态窗口每秒重绘两次"冒充帧率。需要管理员权限:ETW 的实时会话只能由提权进程开启,普通权限下那一栏显示 —,设置里的「FPS 采集」一行会写明原因、以及在算哪个进程。CPU / GPU0 / GPU1 三项不需要任何额外权限。

⏱️ 刷新频率(refreshInterval)

{
  "refreshInterval": 500
}

单位毫秒,允许 200 ~ 5000,超出范围会被自动夹到边界值。改完立刻生效,不需要重启。

取值 适用场景
200 想看瞬时尖峰(编译、压测时的抖动)。代价是 CPU 占用最高
500 默认。流畅度与开销的平衡点
1000 / 2000 / 5000 只关心长期趋势,或者想尽量少占用资源

开销参考(本机实测,release 构建):每一拍的固定开销约 7.3ms,其中 networks.refresh() 独占 6.0ms——sysinfo 每次都要把所有网卡重新枚举一遍。折算下来:

间隔 采集约占一个核心
200ms 3.7%
500ms 1.5%
1000ms 0.7%
5000ms 0.15%

另外两点取舍:

  • GPU 卡最快 500ms 更新一次。 GPU 走 DXGI + PDH,单次采集本身就要约 150ms(PDH 需要双拍热身),所以即使把刷新频率设成 200ms,GPU 卡也不会跟着跑那么快。
  • 曲线窗口随刷新频率一起变。 迷你曲线固定保留最近 60 个点,所以 200ms 时曲线覆盖约 12 秒,500ms 时约 30 秒,5 秒时约 5 分钟。想「看更长时间的趋势」除了调慢刷新频率没有别的办法。

📁 目录结构

sys_monitor_tauri/
├── index.html            # 主窗口与设置窗口共用(按 window.label 区分)
├── README.md             # 中文说明(本文件)
├── README_EN.md          # 英文说明
├── src/
│   ├── main.ts           # 前端逻辑:骨架重建 + 数值就地更新、曲线历史缓存、设置同步、拖动 / 缩放
│   ├── styles.css        # 样式(字号走 --font-size-base 变量;单列 / 双列布局)
│   └── assets/
├── docs/
│   └── development-notes.md  # 开发经验笔记:实现取舍、调试确认过的细节、构建环境已知问题
├── src-tauri/
│   ├── tauri.conf.json   # 应用配置(窗口、bundle、identifier、WiX 语言)
│   ├── capabilities/
│   │   └── default.json  # 窗口权限声明(主窗口 / 设置窗口 / 文字条 / 游戏模式浮层)
│   ├── Cargo.toml
│   └── src/
│       ├── main.rs       # 入口
│       ├── lib.rs        # 命令注册、托盘、设置窗口、设置变更广播;在 Builder::run() 之前启动采集线程
│       ├── monitor.rs    # 采集线程:预热 + 周期可配置的主循环、快照缓存、GPU 独立线程缓存
│       ├── gpu.rs        # GPU 采集(DXGI 枚举 + PDH 计数器)
│       ├── fps.rs        # 帧率采集(ETW 实时会话订阅 Present 事件,需要管理员权限)
│       ├── taskbar.rs    # 托盘文字条的任务栏定位:找 Shell_TrayWnd / TrayNotifyWnd、全屏与自动隐藏判断
│       └── settings.rs   # 设置结构体与 JSON 持久化
└── dist/                 # 前端构建产物

⚡ 启动性能

冷启动不再看到「打开一两秒才出第一组数字」的窗口。做法是把采集线程的启动提前到 tauri::Builder::run() 之前:

Tauri 的 setup 钩子是在窗口(WebView2)创建之后才执行的,所以在 setup 里才起线程,会让「冷枚举 CPU / 初始化 PDH 计数器(~300ms)+ 基线热身(250ms)」和「WebView2 启动」串行叠加。改成提前启动后,预热与 WebView2 启动并行,等 setup 拿到 AppHandle 时数据已经就绪。

配套的三点:

  • 采集线程在第一帧前先把 Snapshot 写入 SnapshotCache,前端不等 snapshot 事件,主动调 get_snapshot 拉一次。事件会附带单调递增的 sequence,前端拒绝过期或重复帧,避免缓存里的旧帧把刚到的事件覆盖回去
  • GPU 卡片用 get_gpu_info 单独兜底:启动时先做一次「只枚举适配器」的 DXGI 枚举(~20ms),利用率和显存随后由后台线程补齐
  • 网络 / 磁盘的速率用真实累计字节算差分;只用 usage() 的相对值再做一次差分会被算成 0

实测延迟还需要在不同机器上确认:「不卡住一两秒」有理论依据(预热从串行改为并行),但具体的可见首帧时间取决于 WebView2 / 磁盘 / 防病毒软件,文档不替真实环境背书。

🤝 参与贡献

欢迎提交贡献。

  1. 🍴 Fork 仓库并新建特性分支。
  2. 📦 按「从源码构建」一节装好依赖。
  3. 🚀 用 npx tauri dev 热更新调试。
  4. 🧹 Rust 侧保持 cargo fmt 格式化,尽量不留 cargo clippy 警告。
  5. 📮 提交 PR,说明改动内容与动机。

较大的改动请先开 Issue 对一下方案。

📌 关于贡献的说明:本仓库为专有许可项目。你提交贡献即表示同意作者可依 LICENSE 的条款使用、修改并纳入该贡献,而不是作为开源发布。

📄 许可证

本项目采用 PolyForm Noncommercial License 1.0.0(源码可用协议,非开源协议)。

🆓 免费:个人、非商业用途(学习、研究、测试、个人爱好等)可自由使用、修改与分发。

💼 商业授权:任何商业用途——包括企业/公司内网或生产环境部署、集成到对外销售的产品或服务、再分发收费、提供收费的托管/外包/订阅服务——均不在许可范围内,须在使用之前向作者申请商业授权。请在 Issues 说明使用场景与部署规模,作者会私下回复授权方案与报价。

本仓库的 v1.0.0 及更早版本按 MIT 许可发布(MIT 不可撤销);自引入本许可证起的新版本按上述条款授权。

完整条款见 LICENSE。

About

Windows 系统性能监控桌面小工具 - Tauri 2 + Rust + TypeScript

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages